深度學習筆記——pytorch學習01——簡單神經網絡的練習

1.Le-Net5神經網絡流程回顧

Le-Net5神經網絡模型如下:(圖片來自Yann LeCun的論文)
在這裏插入圖片描述
本練習流程如下:
32323→conv1(3655)→28286→relu→maxpool(22)→14146→conv2(61655)→101016→relu→maxpool(22)→5516→view(-1,5516)→1400→fc1(400,120)→1120→relu→fc2(120,84)→1*84→relu→fc3(84,10)→softmax(10)

2.神經網絡的搭建

2.1創建神經網絡類對象

①神經網絡類對象繼承torch.nn.Module模型類
②類構造函數中設置神經網絡的conv、pool、fc屬性,其語句分別爲:
self.conv=nn.Conv2d(inchannels,outchannels,kernel_size)通道數、過濾器數量、過濾器大小,其中kernel_size可以是int數也可以是(4,3)這種模式
self.pool=nn.MaxPool2d(2,2)步長stride默認會自適應
self.fc=nn.Linear(infeatures,outfeatures)輸入特徵數,輸出特徵數
③繼承類需要覆寫forward(self,x)前向傳播方法,設置神經網絡的前向傳播流程,如下:
x=self.pool(F.relu(self.conv(x)))一層卷積、激活、池化操作的神經網絡
x=F.relu(self.fc(x))一層全連接神經網絡
代碼示例如下:

class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        #設置卷積矩陣
        self.conv1=nn.Conv2d(3,6,5)
        self.conv2=nn.Conv2d(6,16,5)
        #設置池化層
        self.pool1=nn.MaxPool2d(2,2)
        self.pool2=nn.MaxPool2d(2,2)
        #設置全連接
        self.fc1=nn.Linear(16*5*5,120)
        self.fc2=nn.Linear(120,84)
        self.fc3=nn.Linear(84,10)

    def forward(self,x):
        x=self.pool1(F.relu(self.conv1(x)))#第一層神經網絡
        x=self.pool2(F.relu(self.conv2(x)))#第二層神經網絡
        x=x.view(-1,16*5*5)#矩陣塑形化爲1維網絡
        x=F.relu(self.fc1(x))#第三層神經網絡,全連接1
        x=F.relu(self.fc2(x))#第四層神經網絡,全連接2
        x=self.fc3(x)#第五層神經網絡,全連接3
        return x

2.2創建神經網絡對象、定義損失函數、梯度優化器

①神經網絡對象創建完成需要交給GPU運行
net=Net()
net.to(device)
②損失函數criterion=nn.CroseeEntropyLoss()可選用其它計算方法,其作用爲:
loss=certerion(outputs,labels)可以計算實際輸出和理想輸出之間的損失函數
③梯度優化器主要設置學習步長lr
optimizer=optim.SGD(net.parameters(),lr=0.001,momentum=0.9)此處選擇SGD,可選其它
演示代碼如下:

 net=Net()#生成神經網絡對象、
    net.to(device)

    criterion = nn.CrossEntropyLoss()#定義損失函數
    optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9)

2.3利用訓練集訓練神經網絡

①訓練集、訓練加載器設置(此處訓練集選用CIFAR10)
trainset=torchvision.datasets.CIFAR10(root="./data",train=True,download=True,transform=transforn)
root:下載後訓練集的存儲地址,此處下載由外網下載比較慢,可以參考:https://blog.csdn.net/york1996/article/details/81780065解決
trainloader=torch.utils.data.DataLoader(trainset,batch_size=4,shuffle=True,num_workers=2)
batch_size:沒批數據的數量
num_workers:線程數量此處設置爲2,但是必須再main線程中運行,否則報錯。參考解決:http://www.manongjc.com/article/60188.html
②訓練過程。訓練過程爲循環遍歷訓練,可以根據需要定義訓練次數,單次訓練如下:
for i, data in enumerate(trainloader,0)#enumerate爲迭代器,參數1爲迭代對象,參數2爲迭代起始值,返回值i爲索引值,data爲迭代返回對象
inputs,labels=data#提取訓練集圖片及對應標籤
inputs,labels=inputs.to(device),labels.to(device)此處必須由原變量接收,否則只會創建新對象,而不會改變原本對象,與Module模型不一樣。參考:https://blog.csdn.net/qq_27261889/article/details/86575033
outputs=net(inputs)
loss=criterion(outputs,labels)#計算損失函數
loss.backword()#反向傳播
optimizer.step#迭代優化
演示代碼如下:

    for epoch in range(2):
       running_loss=0.0
       for i,data in enumerate(trainloader,0):
           #獲取輸入
           inputs,labels=data
           ####前面必須用原來的對象接收,不然會包類型不匹配錯誤
           ####原因是tensor.to()會產生一個新的tensor對象而不是改變原對象
           ####參考網址:https://blog.csdn.net/qq_27261889/article/details/86575033
           inputs=inputs.to(device)
           labels=labels.to(device)

           #梯度置0
           optimizer.zero_grad()

           #正向傳播,反向傳播,優化
           outputs=net(inputs)
           outputs=outputs.to(device)
           loss=criterion(outputs,labels)
           loss.backward()
           optimizer.step()

2.4 利用測試集測試神經網絡訓練效果

操作與訓練過程相似,只是不需要再計算梯度和方向傳播。此處運用訓練集作爲測試集
代碼示例如下:

correct=0
    total=0
    with torch.no_grad():
        images,labels=data
        images=images.to(device)
        labels=labels.to(device)
        outputs=net(images)
        outputs=outputs.to(device)
        _,predicted=torch.max(outputs.data,1)
        total+=labels.size(0)
        correct+=(predicted==labels).sum().item()
    print('Accuracy of the network on the 10000 test images: %d %%' % (
    100 * correct / total))

3.整體程序及運行結果

整體程序:

import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
import torch
import torchvision
import torchvision.transforms as transforms
import matplotlib.pyplot as plt
import numpy as np


class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        #設置卷積矩陣
        self.conv1=nn.Conv2d(3,6,5)
        self.conv2=nn.Conv2d(6,16,5)
        #設置池化層
        self.pool1=nn.MaxPool2d(2,2)
        self.pool2=nn.MaxPool2d(2,2)
        #設置全連接
        self.fc1=nn.Linear(16*5*5,120)
        self.fc2=nn.Linear(120,84)
        self.fc3=nn.Linear(84,10)

    def forward(self,x):
        x=self.pool1(F.relu(self.conv1(x)))#第一層神經網絡
        x=self.pool2(F.relu(self.conv2(x)))#第二層神經網絡
        x=x.view(-1,16*5*5)#矩陣塑形化爲1維網絡
        x=F.relu(self.fc1(x))#第三層神經網絡,全連接1
        x=F.relu(self.fc2(x))#第四層神經網絡,全連接2
        x=self.fc3(x)#第五層神經網絡,全連接3
        return x

#圖片展示
def imshow(img):
    img=img/2+0.5    #unnormalize
    npimg=img.numpy()
    plt.imshow(np.transpose(npimg,(1,2,0)))
    plt.show()
    #plt.show()必須添加這個才能真正的看見展示的圖片,但是這樣展示窗口庫之後,主程序後續都卡住
    #解決方法可以採用多線程

classes=(
        "plane","car","bird","cat","deer","dog","frog","horse","ship","truck"
    )

#定義GPU設備,如果GPU可用就在GPU上跑,否則在CPU上跑
#然後需要將net對象,input對象,output對象,images對象,lables對象,targets對象全部to到GPU
device=torch.device("cuda:0" if torch.cuda.is_available() else "cpu")

if __name__ == '__main__':
    net=Net()#生成神經網絡對象、
    net.to(device)

    criterion = nn.CrossEntropyLoss()#定義損失函數
    optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9)

    #設置訓練集
    transform = transforms.Compose(
        [transforms.ToTensor(),
         transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])

    trainset = torchvision.datasets.CIFAR10(
        root="./data", train=True, download=True, transform=transform
    )

    trainloader = torch.utils.data.DataLoader(
        trainset, batch_size=4, shuffle=True, num_workers=2
    )

    #訓練過程
    for epoch in range(2):
       running_loss=0.0
       for i,data in enumerate(trainloader,0):
           #獲取輸入
           inputs,labels=data
           ####前面必須用原來的對象接收,不然會包類型不匹配錯誤
           ####原因是tensor.to()會產生一個新的tensor對象而不是改變原對象
           ####參考網址:https://blog.csdn.net/qq_27261889/article/details/86575033
           inputs=inputs.to(device)
           labels=labels.to(device)

           #梯度置0
           optimizer.zero_grad()

           #正向傳播,反向傳播,優化
           outputs=net(inputs)
           outputs=outputs.to(device)
           loss=criterion(outputs,labels)
           loss.backward()
           optimizer.step()

           #打印狀態信息
           running_loss+=loss.item()
           if i%2000==1999:     #每2000批打印一次
               print('[%d, %5d] loss: %.3f' %
                  (epoch + 1, i + 1, running_loss / 2000))
               runing_loss=0.0
    print("Finished Training")

    # ######測試集上觀察訓練效果
    # #設置測試集
    # testset = torchvision.datasets.CIFAR10(
    #     root="./data", train=False, download=True, transform=transform
    # )
    #
    # testloader = torch.utils.data.DataLoader(
    #     testset, batch_size=4, shuffle=False, num_workers=2
    # )
    #
    # dataiter=iter(testloader)
    # images,labels=dataiter.next()
    # images=images.to(device)
    # labels=labels.to(device)
    # print("GroundTruth","".join('%5s' % classes[labels[j]] for j in range(4)))
    # #測試集的輸入
    # outputs=net(images)
    # outputs=outputs.to(device)
    # _,predicted=torch.max(outputs,1)
    # print('Predicted: ', ' '.join('%5s' % classes[predicted[j]]
    #                           for j in range(4)))
    # # 顯示圖片
    # imshow(torchvision.utils.make_grid(images))

    #####查看神經網絡在整個測試集上的表現
    correct=0
    total=0
    with torch.no_grad():
        images,labels=data
        images=images.to(device)
        labels=labels.to(device)
        outputs=net(images)
        outputs=outputs.to(device)
        _,predicted=torch.max(outputs.data,1)
        total+=labels.size(0)
        correct+=(predicted==labels).sum().item()
    print('Accuracy of the network on the 10000 test images: %d %%' % (
    100 * correct / total))

運行結果:

Files already downloaded and verified
[1,  2000] loss: 2.228
[1,  4000] loss: 4.108
[1,  6000] loss: 5.779
[1,  8000] loss: 7.347
[1, 10000] loss: 8.839
[1, 12000] loss: 10.298
[2,  2000] loss: 1.394
[2,  4000] loss: 2.759
[2,  6000] loss: 4.097
[2,  8000] loss: 5.419
[2, 10000] loss: 6.720
[2, 12000] loss: 7.987
Finished Training
Accuracy of the network on the 10000 test images: 50 %

4問題及解決方法

①當程序中需要進行兩次迴歸時,會報錯,解決方法是第一次迴歸時設置retain_graph=True,不釋放資源。參考:https://oldpan.me/archives/pytorch-retain_graph-work
②trainloader在設置num_workers不等於0時會報多線程錯誤,需要將其放在main線程中。參考:
http://www.manongjc.com/article/60188.html
③plt.imshow()所展示的圖片不會顯示,需要在後面加上plt.show()但是如此一來後續的程序不會運行,可以用多線程解決
④inputs、images、labels在傳輸至GPU時如果不用本身接收會報對象不匹配錯誤,因爲tensor.to()只是產生一個新對象不會改變原對象,參考:https://blog.csdn.net/qq_27261889/article/details/86575033

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章