Pytorch進階(2)------手寫數字識別之卷積神經網絡實現

實現了全連接層的簡單神經網絡之後,這期進行卷積神經網絡的實現,代碼沒有太大的變化,只需做一點改動就可以了

import torch
import torch.nn as nn
import time
from torch import optim 
from torch.autograd import variable
from torch.utils.data.dataloader import DataLoader
from torchvision import datasets,transforms

epoch=10
batch_num=64
lr_rate=0.01
sum_loss=0.0

class CNN(nn.Module):
    def __init__(self):
        super().__init__()
        self.cov1=nn.Sequential(
                nn.Conv2d(in_channels=1,out_channels=64,kernel_size=(3,3),stride=1,padding=1),
                nn.ReLU(),
                nn.Conv2d(in_channels=64,out_channels=128,kernel_size=(3,3),stride=1,padding=1),
                nn.ReLU(),
                nn.MaxPool2d(kernel_size=2, stride=2),
         )
        self.layer=nn.Sequential(
                 nn.Linear(in_features=25088, out_features=1024, bias=True),
                 nn.ReLU(),
                 nn.Linear(in_features=1024, out_features=10, bias=True)
                )
    def forward(self,x):
        x=self.cov1(x)
        x=x.view(-1,14*14*128)
        x=self.layer(x)
        return x
    
data_tf=transforms.ToTensor()
train_set=datasets.MNIST(root='data',train=True,transform=data_tf,download=True)
test_set=datasets.MNIST(root='data',train=False,transform=data_tf,download=True)
train_loader=DataLoader(train_set,batch_size=batch_num,shuffle=True)
test_loader=DataLoader(test_set,batch_size=batch_num,shuffle=True)

since = time.time()

net=CNN()

if torch.cuda.is_available():
   net = net.cuda()

sum_true=0.0
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(net.parameters(), lr=lr_rate)
for e in range(epoch):
    for data in train_loader:
        img,label=data

        if torch.cuda.is_available():
           img = img.cuda()
           label = label.cuda()
        
        img=variable(img)
        label=variable(label)
        output=net(img)
        
        loss=criterion(output,label)
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
        sum_loss+=loss.item()
    print('loss is :{:.16f}'.format(sum_loss/len(train_set)))
    sum_loss=0.0
    sum_true=0
    for data in test_loader:
        img,label=data
        
        if torch.cuda.is_available():
           img = img.cuda()
           label = label.cuda()

        out=net(img)
        _,predict=torch.max(out,1)
        num_true=(predict==label).sum()
        sum_true+=num_true.item()
    print('accuracy rate is :{:.4f}'.format(sum_true/len(test_set)))
    
time_elapsed = time.time() - since
print('Training complete in {:.0f}s'.format(time_elapsed) )     

和上一篇的全連接的網絡相比,主要的改動地方就是在類的定義中加入了卷積層和池化層,具體的參數設置本文並沒有仔細研究過,把上其他人設置的參數直接拿來用了,例如卷積核的大小,步長等,這些應該都挺有講究的。主要是爲了先實現這個網絡,和只有全連接的對比一下效果。除了類定義有不同外,還有在剛開始輸入樣本時不需要將樣本展開成一維了,這也是卷積神經網絡的優勢,可以獲取三維的信息,但是在完成卷積層池化層的運算之後,還是需要將樣本展開爲一維向量然後再傳入全連接層進行計算,卷積神經網絡事實上就是在全連接層的網絡前面加入了一系列卷積和池化的操作

這是訓練10輪的結果,可以看到訓練同樣的輪數,識別的準確率相比只有全鏈接層的網絡提高了很多,上一篇中的全連接網絡訓練10輪準確率是94%多一點,這回的接近98%了,另外,在上一次的計算中,我並沒有看到CPU計算和GPU有很多差別,訓練一個epoch,GPU大概比CPU快了4秒,但在面對加入卷積層並加深網絡之後,GPU的計算優勢相當明顯

同樣是訓練1個epoch,CPU用了509s,接近9分鐘,而GPU只用了半分鐘多,況且我的GPU還只是1650,比1060還差一些,中端性能的GPU,而我的CPU是i7-9750H,應該說是較好的CPU了,因此對深度學習而言,利用GPU加速計算相當重要。在一下一期中,我將繼續探索深度神經網絡,爭取實現幾個有代表性的深度網絡,比如VGGNet什麼的。

 

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