深度學習pytorch入門實戰

1. torch和torchvision

這兩個都是putorch中常用的包,之前已經使用了很多torch的內容,下面我們介紹一下torchvision
torchvision包的朱要功能是實現數據的處理,導入和預覽等,所以對於計算機視覺的相關處理非常方便

import torch
from torchvision import datasets,transforms
from torch.autograd import Variable

首先導入必要的包,在這裏我們只需用到torchvision中的datasets和transforms兩個包,因此只導入了他們兩個,隨後進行數據集的下載,使用datasets加上需要下載的數據集名稱可以比較方便地下載,我們要使用的數據集叫做MINIST

transform=transforms.Compose([transforms.ToTensor(),transforms.Normalize((0.5,),(0.5,))])
data_train=datasets.MNIST(root='./data/',transform=transform,train=True,download=True)
data_test=datasets.MNIST(root='./data/',transform=transform,train=False)

root用於指定下載後的存放路徑,transform用於指定導入數據集時對數據進行哪種變換,train用於指定下載完成後需要載入哪些數據,如果爲true就說明是訓練集,需要載入,如果是false就是測試集
下面介紹transforms

2.torch.transforms

transforms對載入的數據進行變換,舉個例子,如果需要載入的數據集都是圖片,那麼實際計算中必須轉化爲tensor張量才能處理,或者是圖片大小格式不一樣,都可以使用transforms提供的操作進行歸一化
transforms中有很大一部分可以用於數據增強,如果我們的數據集非常有限,那麼就需要對已有數據進行翻轉,裁剪等系列操作,來豐富數據集這裏我們使用的數據集完全足夠,因此不需要數據增強

我們將上面代碼中的torchvision.tansforms.Compose看作一種容器,他能夠對多種數據組合進行變換,傳入的參數是一個列表,列表中的元素就是對載入的數據進行各種變換操作,在上述代碼中,compose中用了一個類型轉換操作ToTensor和一個數據標準化操作Normalize,這裏使用的標準化變換也叫做標準差變換法,這種方式需要使用原始數據的均值mean和標準差來進行數據的標準化,變換之後數據滿足均值爲零,標準差爲1的標準正態分佈,不過這裏我們指定的均值mean和標準差std都不是原始數據的,而是自行定義的,不過仍然能完成標準化操作,注意,此處定義的均值和標準差兩個參數必須是一維的,因爲MNIST圖像是灰度的而不是RGB彩色圖,因此只有一個圖像通道,所以在歸一化的時候只能定義一維的參數,否則不匹配,後面會報錯下面列舉一下transforms中的數據變換操作:

  • Resize:用於圖片數據的縮放,參數是一個整形數據也可以是(h,w)的序列,分別代表縮放的寬度和高度,只指定一個參數就是高度和寬度都等於這個參數
  • Scale:同Resize
  • CenterCrop:保持圖片中心進行裁剪,參數以及意義同Resize
  • RandomCrop:隨機裁剪,參數同上
  • RandomHorizontalFlip:按隨機概率進行水平翻轉,參數是概率值,默認爲0.5
  • RandomVerticalFlip:豎直反轉,同上
  • ToTensor:將PILImage轉換爲tensor類型
  • ToPILImage:將tensor轉化爲PILImage類型,方便內容的顯示

3. 數據預覽和裝載

再數據載入後還要進行裝載,可以理解爲數據的載入就是對圖片的處理,處理完之後裝載就是打包發送給我們的訓練模型

data_loader_train=torch.utils.data.DataLoader(dataset=data_train,batch_size=64,shuffle=True)
data_loader_test=torch.utils.data.DataLoader(dataset=data_test,batch_size=64,shuffle=True)

dataset用於指定裝載的數據集,batch用於設置每個包圖片個數,shuffle設置是否打亂順序

在裝載完成後我們可以選取一個數據批次進行預覽

images,labels=next(iter(data_loader_train))
img=utils.make_grid(images)

img=img.numpy().transpose(1,2,0)
std=[0.5,0.5,0.5]
mean=[0.5,0.5,0.5]
img=img*std+mean
print([labels[i] for i in range(64)])
import matplotlib.pyplot as plt
%matplotlib inline
plt.imshow(img)

首先使用next和iter獲取了一個批次圖像的圖片數據與對應標籤,然後使用makegrid方法使其網格化,每個圖片都是四維的,分別是數據個數,色彩通道,高度和寬度,通過makegrid之後變成了三維,因爲圖片都被整合到一起,所以數據個數參數失效,保留剩下的三個參數,我們使用matplotlib顯示圖片色彩通道必須在後面,因此使用numpy的transpose方法調整參數順序,即0,1,2改成1,2,0這樣色彩通道就成了最後一位,就可以使用imshow進行打印,加上inline聲明是使其在notebook中也能顯示,
輸出如下:
在這裏插入圖片描述

每個數據標籤對應的該位次圖像

4. 模型搭建和參數優化

class Model(torch.nn.Module):
    def __init__(self):
        super(Model,self).__init__()
        self.conv1=torch.nn.Sequential(torch.nn.Conv2d(1,64,kernel_size=3,stride=1,padding=1),torch.nn.ReLU(),torch.nn.Conv2d(64,128,kernel_size=3,stride=1,padding=1),torch.nn.ReLU(),\
                                      torch.nn.MaxPool2d(stride=2,kernel_size=2))
        self.dense=torch.nn.Sequential(torch.nn.Linear(14*14*128,1024),\
                                      torch.nn.ReLU(),\
                                      torch.nn.Dropout(p=0.5),\
                                      torch.nn.Linear(1024,10))
        def forward(self,x):
            x=self.conv1(x)
            x=x.view(-1,14*14*128)
            x=self.dense(x)
            return x

可以看出我們的網絡是兩層卷積網絡伴隨兩次ReLU激活,然後一個最大池化層,最後兩層全連接

  • Conv2d:用於搭建卷積層,參數依次爲:輸入通道數,輸出通道數,卷積核大小,步長和填充值
  • MaxPool2d:主要參數是池化窗口大小,步長和填充
  • Dropout:防止過擬合隨機丟棄參數
  • view:對參數進行扁平化,因爲後面全連接層之恩那個處理一維的
model=Model()
cost=torch.nn.CrossEntropyLoss()
optimzer=torch.optim.Adam(model.parameters())
print(model)

輸出的model結構如下:
在這裏插入圖片描述

訓練過程如下:

nepochs=5
for epoch in range(nepochs):
    running_loss=0.0
    running_corrext=0.0
    print("Epoch:{}/{}".format(epoch,nepochs))
    for data in data_loader_train:
        x_train,y_train=data
        x_train,y_train=Variable(x_train),Variable(y_train)
        outputs=model(x_train)
        _,pred=torch.max(outputs.data,1)
        optimzer.zero_grad()
        loss=cost(outputs,y_train)
        loss.backward()
        optimzer.step()
        running_loss+=loss.item()
        running_corrext+=torch.sum(pred==y_train.data)
    test_correct=0.0
        
    for data in data_loader_test:
        x_test,y_test=data
        x_test,y_test=Variable(x_test),Variable(y_test)
        outputs=model(x_test)
        _,pred=torch.max(outputs.data,1)
        test_correct+=torch.sum(pred==y_test.data)
    print("Loss:{:.4f},train ac:{:.4f}%,test ac:{:.4f}%".format(running_loss/len(data_train),100*running_corrext/len(data_train),100*test_correct/len(data_test)))

不使用cuda加速的話時間會比較長,最後輸出結果可以達到98%以上,我們可以用下面的代碼驗證預測

data_loader_test=torch.utils.data.DataLoader(dataset=data_test,batch_size=4,shuffle=True)
x_test,y_test=next(iter(data_loader_test))
inputs=Variable(x_test)
pred=model(inputs)
_,pred=torch.max(pred,1)

print("pred label is: ",[i for i in pred.data])
print("real label is : ",[i for i in y_test])

輸出如下:
在這裏插入圖片描述

上面的預測的結果,下面是真實結果,多輸出幾次可以發現準確度還是很高的

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