欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Python+Pytorch實(shí)戰(zhàn)之彩色圖片識(shí)別

 更新時(shí)間:2022年09月30日 08:45:49   作者:K同學(xué)啊  
這篇文章主要為大家詳細(xì)介紹了如何利用Python+Pytorch實(shí)現(xiàn)彩色圖片識(shí)別功能,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解一下

一、 前期準(zhǔn)備

1. 設(shè)置GPU

如果設(shè)備上支持GPU就使用GPU,否則使用CPU

import torch
import torch.nn as nn
import matplotlib.pyplot as plt
import torchvision

device = torch.device("cuda" if torch.cuda.is_available() else "cpu")

device
device(type='cuda')

2. 導(dǎo)入數(shù)據(jù)

使用dataset下載MNIST數(shù)據(jù)集,并劃分好訓(xùn)練集與測(cè)試集

使用dataloader加載數(shù)據(jù),并設(shè)置好基本的batch_size

torchvision.datasets.MNIST詳解

torchvision.datasets是Pytorch自帶的一個(gè)數(shù)據(jù)庫,我們可以通過代碼在線下載數(shù)據(jù),這里使用的是torchvision.datasets中的MNIST數(shù)據(jù)集。

函數(shù)原型:

torchvision.datasets.MNIST(root, train=True, transform=None, target_transform=None, download=False)

參數(shù)說明:

  • root (string) :數(shù)據(jù)地址
  • train (string) :True = 訓(xùn)練集,F(xiàn)alse = 測(cè)試集
  • download (bool,optional) : 如果為True,從互聯(lián)網(wǎng)上下載數(shù)據(jù)集,并把數(shù)據(jù)集放在root目錄下。
  • transform (callable, optional ):這里的參數(shù)選擇一個(gè)你想要的數(shù)據(jù)轉(zhuǎn)化函數(shù),直接完成數(shù)據(jù)轉(zhuǎn)化
  • target_transform (callable,optional) :接受目標(biāo)并對(duì)其進(jìn)行轉(zhuǎn)換的函數(shù)/轉(zhuǎn)換。
train_ds = torchvision.datasets.CIFAR10('data', 
                                      train=True, 
                                      transform=torchvision.transforms.ToTensor(), # 將數(shù)據(jù)類型轉(zhuǎn)化為Tensor
                                      download=True)

test_ds  = torchvision.datasets.CIFAR10('data', 
                                      train=False, 
                                      transform=torchvision.transforms.ToTensor(), # 將數(shù)據(jù)類型轉(zhuǎn)化為Tensor
                                      download=True)
Files already downloaded and verified
Files already downloaded and verified
batch_size = 32

train_dl = torch.utils.data.DataLoader(train_ds, 
                                       batch_size=batch_size, 
                                       shuffle=True)

test_dl  = torch.utils.data.DataLoader(test_ds, 
                                       batch_size=batch_size)
# 取一個(gè)批次查看數(shù)據(jù)格式
# 數(shù)據(jù)的shape為:[batch_size, channel, height, weight]
# 其中batch_size為自己設(shè)定,channel,height和weight分別是圖片的通道數(shù),高度和寬度。
imgs, labels = next(iter(train_dl))
imgs.shape

torch.Size([32, 3, 32, 32])

3. 數(shù)據(jù)可視化

squeeze()函數(shù)的功能是從矩陣shape中,去掉維度為1的。例如一個(gè)矩陣是的shape是(5, 1),使用過這個(gè)函數(shù)后,結(jié)果為(5, )。

import numpy as np

 # 指定圖片大小,圖像大小為20寬、5高的繪圖(單位為英寸inch)
plt.figure(figsize=(20, 5)) 
for i, imgs in enumerate(imgs[:20]):
    # 維度縮減
    npimg = imgs.numpy().transpose((1, 2, 0))
    # 將整個(gè)figure分成2行10列,繪制第i+1個(gè)子圖。
    plt.subplot(2, 10, i+1)
    plt.imshow(npimg, cmap=plt.cm.binary)
    plt.axis('off')

二、構(gòu)建簡單的CNN網(wǎng)絡(luò)

對(duì)于一般的CNN網(wǎng)絡(luò)來說,都是由特征提取網(wǎng)絡(luò)和分類網(wǎng)絡(luò)構(gòu)成,其中特征提取網(wǎng)絡(luò)用于提取圖片的特征,分類網(wǎng)絡(luò)用于將圖片進(jìn)行分類。

1. torch.nn.Conv2d()詳解

函數(shù)原型:

torch.nn.Conv2d(in_channels, out_channels, kernel_size, stride=1, padding=0, dilation=1, groups=1, bias=True, padding_mode=‘zeros', device=None, dtype=None)

關(guān)鍵參數(shù)說明:

  • in_channels ( int ) – 輸入圖像中的通道數(shù)
  • out_channels ( int ) – 卷積產(chǎn)生的通道數(shù)
  • kernel_size ( int or tuple ) – 卷積核的大小
  • stride ( int or tuple , optional ) – 卷積的步幅。默認(rèn)值:1
  • padding ( int , tuple或str , optional ) – 添加到輸入的所有四個(gè)邊的填充。默認(rèn)值:0
  • padding_mode (字符串,可選) – ‘zeros’, ‘reflect’, ‘replicate’或’circular’. 默認(rèn):‘zeros’

2. torch.nn.Linear()詳解

函數(shù)原型:

torch.nn.Linear(in_features, out_features, bias=True, device=None, dtype=None)

關(guān)鍵參數(shù)說明:

  • in_features:每個(gè)輸入樣本的大小
  • out_features:每個(gè)輸出樣本的大小

3. torch.nn.MaxPool2d()詳解

函數(shù)原型:

torch.nn.MaxPool2d(kernel_size, stride=None, padding=0, dilation=1, return_indices=False, ceil_mode=False)

關(guān)鍵參數(shù)說明:

  • kernel_size:最大的窗口大小
  • stride:窗口的步幅,默認(rèn)值為kernel_size
  • padding:填充值,默認(rèn)為0
  • dilation:控制窗口中元素步幅的參數(shù)

4. 關(guān)于卷積層、池化層的計(jì)算:

下面的網(wǎng)絡(luò)數(shù)據(jù)shape變化過程為:

3, 32, 32(輸入數(shù)據(jù))

-> 64, 30, 30(經(jīng)過卷積層1)-> 64, 15, 15(經(jīng)過池化層1)

-> 64, 13, 13(經(jīng)過卷積層2)-> 64, 6, 6(經(jīng)過池化層2)

-> 128, 4, 4(經(jīng)過卷積層3) -> 128, 2, 2(經(jīng)過池化層3)

-> 512 -> 256 -> num_classes(10)

import torch.nn.functional as F

num_classes = 10  # 圖片的類別數(shù)

class Model(nn.Module):
     def __init__(self):
        super().__init__()
         # 特征提取網(wǎng)絡(luò)
        self.conv1 = nn.Conv2d(3, 64, kernel_size=3)   # 第一層卷積,卷積核大小為3*3
        self.pool1 = nn.MaxPool2d(kernel_size=2)       # 設(shè)置池化層,池化核大小為2*2
        self.conv2 = nn.Conv2d(64, 64, kernel_size=3)  # 第二層卷積,卷積核大小為3*3   
        self.pool2 = nn.MaxPool2d(kernel_size=2) 
        self.conv3 = nn.Conv2d(64, 128, kernel_size=3) # 第二層卷積,卷積核大小為3*3   
        self.pool3 = nn.MaxPool2d(kernel_size=2) 
                                      
        # 分類網(wǎng)絡(luò)
        self.fc1 = nn.Linear(512, 256)          
        self.fc2 = nn.Linear(256, num_classes)
     # 前向傳播
     def forward(self, x):
        x = self.pool1(F.relu(self.conv1(x)))     
        x = self.pool2(F.relu(self.conv2(x)))
        x = self.pool3(F.relu(self.conv3(x)))
        
        x = torch.flatten(x, start_dim=1)

        x = F.relu(self.fc1(x))
        x = self.fc2(x)
       
        return x

加載并打印模型

from torchinfo import summary
# 將模型轉(zhuǎn)移到GPU中(我們模型運(yùn)行均在GPU中進(jìn)行)
model = Model().to(device)

summary(model)
=================================================================
Layer (type:depth-idx)                   Param #
=================================================================
Model                                    --
├─Conv2d: 1-1                            1,792
├─MaxPool2d: 1-2                         --
├─Conv2d: 1-3                            36,928
├─MaxPool2d: 1-4                         --
├─Conv2d: 1-5                            73,856
├─MaxPool2d: 1-6                         --
├─Linear: 1-7                            131,328
├─Linear: 1-8                            2,570
=================================================================
Total params: 246,474
Trainable params: 246,474
Non-trainable params: 0
=================================================================

三、 訓(xùn)練模型

1. 設(shè)置超參數(shù)

loss_fn    = nn.CrossEntropyLoss() # 創(chuàng)建損失函數(shù)
learn_rate = 1e-2 # 學(xué)習(xí)率
opt        = torch.optim.SGD(model.parameters(),lr=learn_rate)

2. 編寫訓(xùn)練函數(shù)

1. optimizer.zero_grad()

函數(shù)會(huì)遍歷模型的所有參數(shù),通過內(nèi)置方法截?cái)喾聪騻鞑サ奶荻攘?,再將每個(gè)參數(shù)的梯度值設(shè)為0,即上一次的梯度記錄被清空。

2. loss.backward()

PyTorch的反向傳播(即tensor.backward())是通過autograd包來實(shí)現(xiàn)的,autograd包會(huì)根據(jù)tensor進(jìn)行過的數(shù)學(xué)運(yùn)算來自動(dòng)計(jì)算其對(duì)應(yīng)的梯度。

具體來說,torch.tensor是autograd包的基礎(chǔ)類,如果你設(shè)置tensor的requires_grads為True,就會(huì)開始跟蹤這個(gè)tensor上面的所有運(yùn)算,如果你做完運(yùn)算后使用tensor.backward(),所有的梯度就會(huì)自動(dòng)運(yùn)算,tensor的梯度將會(huì)累加到它的.grad屬性里面去。

更具體地說,損失函數(shù)loss是由模型的所有權(quán)重w經(jīng)過一系列運(yùn)算得到的,若某個(gè)w的requires_grads為True,則w的所有上層參數(shù)(后面層的權(quán)重w)的.grad_fn屬性中就保存了對(duì)應(yīng)的運(yùn)算,然后在使用loss.backward()后,會(huì)一層層的反向傳播計(jì)算每個(gè)w的梯度值,并保存到該w的.grad屬性中。

如果沒有進(jìn)行tensor.backward()的話,梯度值將會(huì)是None,因此loss.backward()要寫在optimizer.step()之前。

3. optimizer.step()

step()函數(shù)的作用是執(zhí)行一次優(yōu)化步驟,通過梯度下降法來更新參數(shù)的值。因?yàn)樘荻认陆凳腔谔荻鹊?,所以在?zhí)行optimizer.step()函數(shù)前應(yīng)先執(zhí)行l(wèi)oss.backward()函數(shù)來計(jì)算梯度。

注意:optimizer只負(fù)責(zé)通過梯度下降進(jìn)行優(yōu)化,而不負(fù)責(zé)產(chǎn)生梯度,梯度是tensor.backward()方法產(chǎn)生的。

# 訓(xùn)練循環(huán)
def train(dataloader, model, loss_fn, optimizer):
    size = len(dataloader.dataset)  # 訓(xùn)練集的大小,一共60000張圖片
    num_batches = len(dataloader)   # 批次數(shù)目,1875(60000/32)

    train_loss, train_acc = 0, 0  # 初始化訓(xùn)練損失和正確率
    
    for X, y in dataloader:  # 獲取圖片及其標(biāo)簽
        X, y = X.to(device), y.to(device)
        
        # 計(jì)算預(yù)測(cè)誤差
        pred = model(X)          # 網(wǎng)絡(luò)輸出
        loss = loss_fn(pred, y)  # 計(jì)算網(wǎng)絡(luò)輸出和真實(shí)值之間的差距,targets為真實(shí)值,計(jì)算二者差值即為損失
        
        # 反向傳播
        optimizer.zero_grad()  # grad屬性歸零
        loss.backward()        # 反向傳播
        optimizer.step()       # 每一步自動(dòng)更新
        
        # 記錄acc與loss
        train_acc  += (pred.argmax(1) == y).type(torch.float).sum().item()
        train_loss += loss.item()
            
    train_acc  /= size
    train_loss /= num_batches

    return train_acc, train_loss

3. 編寫測(cè)試函數(shù)

測(cè)試函數(shù)和訓(xùn)練函數(shù)大致相同,但是由于不進(jìn)行梯度下降對(duì)網(wǎng)絡(luò)權(quán)重進(jìn)行更新,所以不需要傳入優(yōu)化器

def test (dataloader, model, loss_fn):
    size        = len(dataloader.dataset)  # 測(cè)試集的大小,一共10000張圖片
    num_batches = len(dataloader)          # 批次數(shù)目,313(10000/32=312.5,向上取整)
    test_loss, test_acc = 0, 0
    
    # 當(dāng)不進(jìn)行訓(xùn)練時(shí),停止梯度更新,節(jié)省計(jì)算內(nèi)存消耗
    with torch.no_grad():
        for imgs, target in dataloader:
            imgs, target = imgs.to(device), target.to(device)
            
            # 計(jì)算loss
            target_pred = model(imgs)
            loss        = loss_fn(target_pred, target)
            
            test_loss += loss.item()
            test_acc  += (target_pred.argmax(1) == target).type(torch.float).sum().item()

    test_acc  /= size
    test_loss /= num_batches

    return test_acc, test_loss

4. 正式訓(xùn)練

1. model.train()

model.train()的作用是啟用 Batch Normalization 和 Dropout。

如果模型中有BN層(Batch Normalization)和Dropout,需要在訓(xùn)練時(shí)添加model.train()。model.train()是保證BN層能夠用到每一批數(shù)據(jù)的均值和方差。對(duì)于Dropout,model.train()是隨機(jī)取一部分網(wǎng)絡(luò)連接來訓(xùn)練更新參數(shù)。

2. model.eval()

model.eval()的作用是不啟用 Batch Normalization 和 Dropout。

如果模型中有BN層(Batch Normalization)和Dropout,在測(cè)試時(shí)添加model.eval()。model.eval()是保證BN層能夠用全部訓(xùn)練數(shù)據(jù)的均值和方差,即測(cè)試過程中要保證BN層的均值和方差不變。對(duì)于Dropout,model.eval()是利用到了所有網(wǎng)絡(luò)連接,即不進(jìn)行隨機(jī)舍棄神經(jīng)元。

訓(xùn)練完train樣本后,生成的模型model要用來測(cè)試樣本。在model(test)之前,需要加上model.eval(),否則的話,有輸入數(shù)據(jù),即使不訓(xùn)練,它也會(huì)改變權(quán)值。這是model中含有BN層和Dropout所帶來的的性質(zhì)。

epochs     = 10
train_loss = []
train_acc  = []
test_loss  = []
test_acc   = []

for epoch in range(epochs):
    model.train()
    epoch_train_acc, epoch_train_loss = train(train_dl, model, loss_fn, opt)
    
    model.eval()
    epoch_test_acc, epoch_test_loss = test(test_dl, model, loss_fn)
    
    train_acc.append(epoch_train_acc)
    train_loss.append(epoch_train_loss)
    test_acc.append(epoch_test_acc)
    test_loss.append(epoch_test_loss)
    
    template = ('Epoch:{:2d}, Train_acc:{:.1f}%, Train_loss:{:.3f}, Test_acc:{:.1f}%,Test_loss:{:.3f}')
    print(template.format(epoch+1, epoch_train_acc*100, epoch_train_loss, epoch_test_acc*100, epoch_test_loss))
print('Done')

Epoch: 1, Train_acc:13.5%, Train_loss:2.280, Test_acc:19.8%,Test_loss:2.150
Epoch: 2, Train_acc:24.6%, Train_loss:2.022, Test_acc:29.0%,Test_loss:1.931
Epoch: 3, Train_acc:33.2%, Train_loss:1.811, Test_acc:36.9%,Test_loss:1.712
Epoch: 4, Train_acc:40.4%, Train_loss:1.637, Test_acc:40.8%,Test_loss:1.609
Epoch: 5, Train_acc:44.0%, Train_loss:1.535, Test_acc:46.4%,Test_loss:1.470
Epoch: 6, Train_acc:47.4%, Train_loss:1.449, Test_acc:47.4%,Test_loss:1.432
Epoch: 7, Train_acc:50.9%, Train_loss:1.365, Test_acc:53.1%,Test_loss:1.313
Epoch: 8, Train_acc:53.9%, Train_loss:1.289, Test_acc:55.2%,Test_loss:1.256
Epoch: 9, Train_acc:56.1%, Train_loss:1.226, Test_acc:50.4%,Test_loss:1.458
Epoch:10, Train_acc:58.4%, Train_loss:1.175, Test_acc:58.9%,Test_loss:1.156
Done

四、 結(jié)果可視化

到此這篇關(guān)于Python+Pytorch實(shí)戰(zhàn)之彩色圖片識(shí)別的文章就介紹到這了,更多相關(guān)Python Pytorch彩色圖片識(shí)別內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Python 實(shí)現(xiàn)使用dict 創(chuàng)建二維數(shù)據(jù)、DataFrame

    Python 實(shí)現(xiàn)使用dict 創(chuàng)建二維數(shù)據(jù)、DataFrame

    下面小編就為大家分享一篇Python 實(shí)現(xiàn)使用dict 創(chuàng)建二維數(shù)據(jù)、DataFrame,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2018-04-04
  • 詳解Python中可散列的數(shù)據(jù)類型

    詳解Python中可散列的數(shù)據(jù)類型

    在Python中,字典(dict)是一種常用的數(shù)據(jù)類型,其使用鍵(key)和值(value)來存儲(chǔ)和訪問數(shù)據(jù),在字典中,鍵必須是可哈希(hashable)的類型,否則會(huì)導(dǎo)致運(yùn)行時(shí)錯(cuò)誤,因此,在Python中,有一些可散列的數(shù)據(jù)類型可以作為字典的鍵
    2023-06-06
  • Python StrEnum基本概念和使用場景分析

    Python StrEnum基本概念和使用場景分析

    StrEnum是Python枚舉家族的一個(gè)強(qiáng)大補(bǔ)充,特別適合處理字符串常量,它結(jié)合了枚舉的類型安全性和字符串的靈活性,使得在許多場景下的編程變得更加簡潔和安全,本文將介紹StrEnum的基本概念和使用場景,并通過示例代碼來展示它的實(shí)際應(yīng)用,感興趣的朋友跟隨小編一起看看吧
    2024-07-07
  • django如何部署到centos服務(wù)器上

    django如何部署到centos服務(wù)器上

    django項(xiàng)目寫完以后最好能部署到服務(wù)器上,這樣就可以在隨時(shí)隨地查看內(nèi)容了,本文主要介紹了django如何部署到centos服務(wù)器上,感興趣的可以了解一下
    2023-08-08
  • Python3自動(dòng)安裝第三方庫,跟pip說再見

    Python3自動(dòng)安裝第三方庫,跟pip說再見

    很多朋友私信小編Python安裝第三方庫安裝技巧,在這就不一一回復(fù)大家了,今天小編給大家分享一篇教程關(guān)于Python自動(dòng)安裝第三方庫的小技巧,本文以安裝plotly為例給大家詳細(xì)講解,感興趣的朋友跟隨小編一起看看吧
    2021-10-10
  • Python 錯(cuò)誤和異常小結(jié)

    Python 錯(cuò)誤和異常小結(jié)

    這不是一篇關(guān)于Python異常的全面介紹的文章,這只是在學(xué)習(xí)Python異常后的一篇筆記式的記錄和小結(jié)性質(zhì)的文章
    2013-10-10
  • 基于PyQt5自制簡單的文件內(nèi)容檢索小工具

    基于PyQt5自制簡單的文件內(nèi)容檢索小工具

    這篇文章主要為大家詳細(xì)介紹了如何基于PyQt5自制一個(gè)簡單的文件內(nèi)容檢索小工具,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2023-05-05
  • Python?字符替換的四方法

    Python?字符替換的四方法

    本文主要介紹了Python?字符替換的四方法,主要包括replace、translate、maketrans?和正則這是四種方法,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-01-01
  • Python之使用adb shell命令啟動(dòng)應(yīng)用的方法詳解

    Python之使用adb shell命令啟動(dòng)應(yīng)用的方法詳解

    今天小編就為大家分享一篇Python之使用adb shell命令啟動(dòng)應(yīng)用的方法詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2019-01-01
  • python查看包版本、更新單個(gè)包、卸載單個(gè)包的操作方法

    python查看包版本、更新單個(gè)包、卸載單個(gè)包的操作方法

    這篇文章主要介紹了python查看包版本、更新單個(gè)包、卸載單個(gè)包,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-12-12

最新評(píng)論