PyTorch 深度學習 入門 / 筆記

許振揚 Jhen-Yung Hsu
10 min readJun 2, 2020

--

因為本人開始入坑深度學習,因此紀錄深度學習的一些入門知識和PyTorch深度學習框架的語法,此篇將會持續更新。

PyTorch是什麼?

PyTorch是2017年Facebook的開源深度學習框架,是以Python為基礎,語法與Python極為相近,有Python基礎的人能很快上手

為什麼選擇PyTorch?

現今有許多深度學習框架像是最熱門的3個框架:TensorFlow、Keras、PyTorch,為什麼要選用PyTorch?最主要的原因是學術界大多都使用PyTorch了哈哈!其原因是PyTorch的深度學習架構較直觀、開發上可以很迅速(相較TensorFlow等相同功能需要的程式碼較少、簡潔)

PyTorch安裝

進入PyTorch官網[1]可以要安裝的PyTorch版本、OS、CUDA GPU版本等等,選好這些後就會給你一串安裝的command直接丟到Anaconda Prompt就安裝完成了。

* 本篇於適用於 PyTorch1.5 以後版本,不同版本的函示庫、使用方法可能有所不同

PyTorch核心觀念

此節將講述PyTorch的核心概念,讓你能對PyTorch有基本概念,輕鬆建起基本的深度模型,並以經典的MNIST Dataset(0~9的數字手寫資料集)訓練DNN、CNN模型,那麼我們先來將講述PyTorch網路模型的核心觀念、函式、語法。

[註: 如果看完後觀念和函式的定義還是半知半解的話,能跳到實例部分更好理解]

[註:此處以讀者已有Python的開發基礎來講解]

這裡我們複習、回想一下神經網路大致上是如何運作的,先有觀念後再看實際的程式碼會更有感覺

Neural Network 運作概要

  1. 準備好訓練資料(Training data)、預處理(Preprocessing)這些資料
  2. 建好Neural Network架構(決定神經網路架構、loss functionOptimizer[Optimizer如SGD、momentum、Adam等])
  3. 將訓練資料丟進Neural Network運算(forward propagation),得到預測結果
  4. 預測結果以及真實結果來計算loss function值
  5. 對loss值用反向傳播法(backward propagation)算出每個神經網路中參數的梯度
  6. 使用Optimizer(SGD、Momentum、Adam…)參數的梯度更新參數權重
  7. 重複執行步驟3~6,持續到訓練結束(結束可以是Network loss值小於定義的門檻值、執行N次訓練等)

有了深度學習的Overview後,來正式看看Pytorch如何實現的吧!

基本元素 : Tensor

初學者可以將Tensor(張量)可以直接看作Python中的numpy array比較好理解,只是在加上一些深度學習開發時會用到的運算、屬性等來包裝。

★ Torch.tensor

>>> import torch
>>> import numpy as np
# create tensor
>>> torch.tensor([[1., -1.], [1., -1.]])
tensor([[ 1.0000, -1.0000],
[ 1.0000, -1.0000]])
# Translate np array to tensor
>>> torch.tensor(np.array([[1, 2, 3], [4, 5, 6]]))
tensor([[ 1, 2, 3],
[ 4, 5, 6]])

大多數tensor用法與numpy array幾乎一模一模,更多例子可以看Pytorch官網的入門例子

★ Torch View (reshape)

需要注意與numpy使用上的不同例外是,Pytorch會使用view()來reshape陣列,在python中重塑numpy array時會使用reshape()

x = torch.randn(4, 4) # 2維陣列 4 row, 4 column
y = x.view(16)
z = x.view(-1, 8) # the size -1 is inferred from other dimensions
print(x.size(), y.size(), z.size())
Out:
torch.Size([4, 4]) torch.Size([16]) torch.Size([2, 8])

Neural Network Model、Function

要使用PyTorch深度神經網路需要引入一些函式庫。

torch.nn:創建Neural Network時需要用的到函式庫

torch.nn.funtional:提供許多Neural Network會用的函式庫,如loss function等,與torch.nn的差別是funtional是只提供"純函式",而nn則是包裝成整個nn.module,基本上兩者能互相轉換。

import torch.nn as nn
import torch.nn.functional as F

建立Neraul Netowrk

引入torch.nn後就可以來建立我們自己的神經網路了,整個神經網路模型(model)會包裝在一個class裡面,我們需要建立一個class並繼承torch.nn.model,然後覆寫(override)__init__和forward()來自訂我們的神經網路,以下是官網的例子,還看不是很懂沒關係,我們能先看整個模型定義的方式

__init__(self):定義各種層網路,像是全連接層、卷積層、Batch Batch normalization layer、activation layer等等 (上面例子relu是直接再forward使用F.relu(),當然你也能直接再__init__定義一層relu layer)

foward(self, x):foward propagation,將training data經過整個神經網路,在此function定義data怎麼經過各層layer的

Gradient/backward propagation/Optimize

訓練網路時會需要計算梯度,並使用反向傳播法更新權重

假設我們已經算出了Neural Network的loss值並在x變數,我們可以利用反向傳播法計算梯度

x.backward() # 利用loss值計算每個參數的梯度

但這不代表已更新權重,要真正更新權必須創建一個optimizer,我們先引入torch.optim,此函式庫有許多optimizer像是SGD、Adam等,創建好optimizer後使用step()即可更新權重

import torch.optim as optim 
# create your optimizer
optimizer = optim.SGD(net.parameters(), lr=0.01)
...假設已經計算出Network的loss值,並存在x變數...
x.backward() # 反向傳播法計算梯度
optimizer.step() # 更新權重

實例 - PyTorch打造MNIST手寫辨識模型

此節將以建立DNN、CNN來分析MNIST手寫辨識模型

MNIST資料庫

MNIST資料庫為0~9的數字手寫辨識(每張圖size為28*28),有6萬筆Traning data, 1萬筆Testing data,我們能先用下面程式碼印出資料長成什麼樣子

輸出結果:

100張MNIST手寫辨識圖製成的格線圖

DNN (Fully Connected Network)

1. 我們先引入需要函式庫、以及載入MNIST資料集並切成小塊的batch

2. 建好Neural Network架構,此處為fully connected layer

3. 建立 Optimizer;訓練network,epochs決定要跑整個訓練集幾次。

需要注意的是每次更新完參數後要呼叫optimizer.zero_grad()來清空gradient,不使用的話gradient值會一直累積。

4. 利用訓練好的Neural Network來評估Traning set、Testing set上的準確率

[註] 記得使用net.eval()切換成evaluation mode(與Dropout、BatchNorm有關);torch.nograd()亦必須使用,因為再測試時不需要計算Gradient,能加快預測速度

DNN完整程式碼:

上段程式結果如下

output:
epoch:0, loss:0.12780500948429108
epoch:1, loss:0.2258947491645813
Training data Accuracy: 57143/60000 = 0.952
testing data Accuracy: 9473/10000 = 0.947

我們印出每個epoch的 loss來偵錯,以及訓練好Network後計算training set的準確率和testing set上的準確率,可以看到建構簡單的Network準確率就達到約95%

完整程式碼亦可見我的Github: https://github.com/Yunyung/Deep-learning-projects-with-Pytorch/blob/master/MNIST%20DNN.ipynb

CNN (Convolution Neural Network)

CNN經常使用在圖像辨識的應用,而CNN程式碼與前面很雷同,除了網路架構加上Convolution以及Data丟入Network的方式不同,直接看程式碼吧,應該很好理解。

上段程式結果如下

[1,   100] loss: 0.051
[1, 200] loss: 0.047
[1, 300] loss: 0.038
[1, 400] loss: 0.047
[1, 500] loss: 0.047
[1, 600] loss: 0.045
[2, 100] loss: 0.040
[2, 200] loss: 0.032
[2, 300] loss: 0.039
[2, 400] loss: 0.043
[2, 500] loss: 0.034
[2, 600] loss: 0.037
Training data Accuracy: 59372/60000 = 0.99
testing data Accuracy: 9886/10000 = 0.989

可以看到CNN準確率甚至達到99%!

完整程式碼亦可見我的Github: https://github.com/Yunyung/Deep-learning-projects-with-Pytorch/blob/master/MNIST%20CNN.ipynb

其他PyTorch語法

此節紀錄開發時我常用到的PyTorch語法

torch.item() - get a Python number from a tensor containing a single value

>>> x = torch.tensor([[1]])
>>> x
tensor([[ 1]])
>>> x.item()
1
>>> x = torch.tensor(2.5)
>>> x
tensor(2.5000)
>>> x.item()
2.5

References:

[1] PyTorch官網安裝網址 from: https://pytorch.org/get-started/locally/

--

--

許振揚 Jhen-Yung Hsu

I am a student in Taiwan, majoring in CSIE @software engineer