PyTorch 深度學習 入門 / 筆記
因為本人開始入坑深度學習,因此紀錄深度學習的一些入門知識和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 運作概要
- 準備好訓練資料(Training data)、預處理(Preprocessing)這些資料
- 建好Neural Network架構(決定神經網路架構、loss function、Optimizer[Optimizer如SGD、momentum、Adam等])
- 將訓練資料丟進Neural Network運算(forward propagation),得到預測結果
- 預測結果以及真實結果來計算loss function值
- 對loss值用反向傳播法(backward propagation)算出每個神經網路中參數的梯度
- 使用Optimizer(SGD、Momentum、Adam…)和參數的梯度更新參數權重
- 重複執行步驟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,我們能先用下面程式碼印出資料長成什麼樣子
輸出結果:
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/