1、Pytorch簡介
PyTorch是一個基于Torch的Python開源機器學習庫,用于自然語言處理等應用程式。它主要由Facebook的人工智能小組開發,不僅能夠實作強大的GPU加速,同時還支援動态神經網絡,這一點是現在很多主流架構如TensorFlow都不支援的。 PyTorch提供了兩個進階功能:
具有強大的GPU加速的張量計算(如Numpy)
包含自動求導系統的深度神經網絡
PyTorch大量使用了Python概念,例如類、結構和條件循環,允許使用者以純面向對象的方式建構深度學習算法。
除了Facebook之外,Twitter、GMU和Salesforce等機構都采用了PyTorch,包括達摩院PAI平台也有使用。
2、Conda環境安裝
參考
https://yuque.antfin-inc.com/yoznxz/gin3ds/rgeb8g。
3、建立Pytorch Python虛拟環境
基于Python3.7版本,是以線建立一個PyTorch的Python虛拟環境。
conda create --name pytorch python=3.7
3.1 、激活環境
(tf2)$conda activate pytorch
3.2、安裝PyTorch
通路官網
https://pytorch.org/get-started/locally/會根據目前系統提供合适的安裝指令:

指令中包含安裝視覺和聲音兩個部分,這裡隻安裝視覺部分:
(pytorch)$conda install pytorch torchvision -c pytorch
3.3、安裝Matplotlib
matplotlib,風格類似 Matlab 的基于 Python 的圖表繪圖系統。
matplotlib 是 Python最著名的繪圖庫,它提供了一整套和 matlab 相似的命 API,十分适合互動式地進行制圖。而且也可以友善地将它作為繪圖控件,嵌入 GUI 應用程式中,在模型訓練中常常用來繪制圖形。
(pytorch)$conda install matplotlib
4、PyTorch之初體驗
4.1、Python環境配置
建立一個test.ipynb,并配置Python環境為pytorch虛拟環境
4.2、Jupyter Kernel配置
在使用Jupyter時,需要連接配接到Jupyter kernel,按照下圖選擇Pytorch虛拟環境。
4.3、簡單手寫數字識别網絡
在VSCode中使用Pytorch實作LeNet-5進行手寫數字識别。
4.3.1、下載下傳MNIST資料集
在PyTorch中,下載下傳和導入MNIST資料集非常簡單,可以使用torchvision庫來完成。torchvision是一個專門進行圖形處理的庫,可加載比較常見的資料庫,如ImageNet、CIFAR10、MNIST等。使用torchvision的好處是避免了重複編寫資料集加載代碼,讓資料集的加載更加簡單。
import torch
import torchvision
import torchvision.transforms as transforms
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
import matplotlib.pyplot as plt
import numpy as np
#向量轉換
transform = transforms.Compose([transforms.ToTensor()])
#訓練集下載下傳
trainset = torchvision.datasets.MNIST(
root = './datasets/ch08/pytorch',
train= True,
download= True,
transform=transform)
#測試集下載下傳
testset = torchvision.datasets.MNIST(
root='./datasets/ch08/pytorch', # 選擇資料的根目錄
train=False,
download=True, # 從網絡上下載下傳圖檔
transform=transform)
上面代碼中參數root設定資料集在本地存放的目錄,可自由選擇。注意,對于訓練集,參數train設定為True;對于測試集,參數train設定為False。關于參數download,如果是第一次運作該代碼,則将其設定為True,表示從網絡上下載下傳MNIST資料集;如果已經下載下傳了資料集,就可以将其設定為False。
4.3.2、加載資料集
#加載訓練集
trainloader = torch.utils.data.DataLoader(
trainset,
batch_size = 4,
shuffle = True,
num_workers = 2)
#加載測試集
testloader = torch.utils.data.DataLoader(
testset,
batch_size=4,
shuffle=False,
num_workers=2)
上面代碼中參數batch_size表示每個小批量樣本集中的樣本數量。參數shuffle表示是否在每個epoch中随機打亂資料集,這樣做的目的是使每個epoch資料集的次序都不一樣,保證每個小批量樣本集盡可能不一樣,提高接下來的訓練效果。參數num_workers表示使用多少個子程序來導入資料。
p
rint(trainset)
print(testset)
列印訓練集和測試集路徑:
Dataset MNIST
Number of datapoints: 60000
Root location: ./datasets/ch08/pytorch
Split: Train
StandardTransform
Transform: Compose(
ToTensor()
)
Dataset MNIST
Number of datapoints: 10000
Root location: ./datasets/ch08/pytorch
Split: Test
StandardTransform
Transform: Compose(
ToTensor()
)
4.3.3、顯示訓練集
def imshow(img):
npimg = img.numpy()
plt.imshow(np.transpose(npimg, (1, 2, 0)))
dataiter = iter(trainloader)
images, labels = dataiter.next()
imshow(torchvision.utils.make_grid(images))
plt.show()
print(' '.join('%11s' % labels[j].numpy() for j in range(4)))
顯示訓練集:
4.3.4、搭建LeNet-5網絡模型
LeNet-5是卷積網絡用于識别的開山之作,由被譽為“卷積網絡之父”的Yann LeCun于1994年提出。雖然這網絡結構現在已經很少使用,但是它對後續卷積網絡的發展起到了奠基作用。這個網絡雖然很小,但是它包含了深度學習的基本子產品:卷積層,池化層,全連接配接層。是其他深度學習模型的基礎。
同時,其中也展現了前述的設計思想:局部感受野、權值共享、下采樣。 LeNet-5模型結構如下圖:
搭建網絡:
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
#第一層卷積
self.conv1 = nn.Conv2d(1, 6, 5) #1個輸入圖檔通道, 6個輸出通道, 5×5 卷積核
#第一層池化層
self.pool1 = nn.MaxPool2d(2, 2) #max pooling, 2×2
#第二層卷積
self.conv2 = nn.Conv2d(6, 16, 5) #6個輸入圖檔通道, 16個輸出通道, 5×5 卷積核
#第二層池化
self.pool2 = nn.MaxPool2d(2, 2)
#全連接配接層
self.fc1 = nn.Linear(16 * 4 * 4, 120) #伸成一維向量
#全連接配接層
self.fc2 = nn.Linear(120, 84) #120個特征圖, 84個神經元
#全連接配接層, 輸出層
self.fc3 = nn.Linear(84, 10) #84個神經元輸入, Softmax輸出10個數字
def forward(self, x):
x = F.relu(self.conv1(x))
x = self.pool1(x)
x = F.relu(self.conv2(x))
x = self.pool2(x)
#拉伸為一維向量
x = x.view(-1, 16 * 4 * 4)
x = F.relu(self.fc1(x))
x = F.relu(self.fc2(x))
x = self.fc3(x)
return x
MNIST圖檔的尺寸為28×28×1,經過第一層卷積層和池化層後,尺寸為:
28-5/1+4 = 24, 24/2 = 12
經過第二層卷積層和池化層後,尺寸為:
12-5/1+1 = 8, 8/2 = 4 由于該池化層濾波器組個數為16,則拉伸一維數組的長度就是1644。函數forward(self, x)定義了卷積神經網絡的前向傳播過程。
net = Net()
print(net)
列印網絡:
Net(
(conv1): Conv2d(1, 6, kernel_size=(5, 5), stride=(1, 1))
(pool1): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
(conv2): Conv2d(6, 16, kernel_size=(5, 5), stride=(1, 1))
(pool2): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
(fc1): Linear(in_features=256, out_features=120, bias=True)
(fc2): Linear(in_features=120, out_features=84, bias=True)
(fc3): Linear(in_features=84, out_features=10, bias=True)
)
整個Net結構非常直覺,可以完整、清晰地檢視我們建構的卷積神經網絡模型的結構。
4.3.5、模型優化
PyTorch中用nn.MSELoss表示均方差。 該項目是一個分類問題,是以損失函數使用交叉熵,PyTorch中用nn.CrossEntropyLoss表示交叉熵。如果是回歸問題,損失函數一般使用均方差, 在卷積神經網絡模型的反向傳播中,仍然是基于梯度下降算法來優化參數的。
梯度優化算法同樣可以應用到卷積神經網絡模型中。使用方法非常簡單,直接調用PyTorch中的torch.optim子產品即可。例如,torch.optim. RMSprop表示RMSprop優化,torch.optim.Adam表示Adam優化。
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(net.parameters(), lr = 0.0001) #梯度優化算法是Adam,學習率設定為0.0001
4.3.6、模型訓練
每次疊代訓練時都要先把所有梯度清零,即執行optimizer.zero_grad()。否則,梯度會累加,造成訓練錯誤和失效。PyTorch中的.backward()可自動完成所有梯度計算。
num_epoches = 5 #設定epoch 數目
cost = [] #損失函數累
for epoch in range(num_epoches):
running_loss = 0.0
for i, data in enumerate(trainloader, 0):
inputs, labels = data #輸入樣本和标簽
optimizer.zero_grad() #每次訓練梯度清零
# 正向傳播、反向傳播和優化過程
outputs = net(inputs)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
running_loss += loss.item()
if (i+1) % 2000 == 0: # 每隔2000個小批量樣本列印一次
print('[epoch: %d, mini-batch: %5d] loss: %.3f' %
(epoch + 1, i + 1, running_loss / 2000))
cost.append(running_loss / 2000)
running_loss = 0.0
訓練結果:
[epoch: 1, mini-batch: 2000] loss: 1.032
[epoch: 1, mini-batch: 4000] loss: 0.424
[epoch: 1, mini-batch: 6000] loss: 0.339
[epoch: 1, mini-batch: 8000] loss: 0.272
...
[epoch: 5, mini-batch: 10000] loss: 0.049
[epoch: 5, mini-batch: 12000] loss: 0.056
[epoch: 5, mini-batch: 14000] loss: 0.044
4.3.7、模型預測
訓練集驗證
correct = 0
total = 0
with torch.no_grad():
for data in trainloader:
images, labels = data
outpus = net(images)
_,predicted = torch.max(outpus.data, 1)
total += labels.size(0)
correct += (predicted == labels).sum().item()
print('Accuracy on the 60000 train images: %.3f %%' % (100 * correct / total))
訓練精度結果:
Accuracy on the 10000 test images: 98.370 %
4.3.8、測試代碼
快速體驗請直接下載下傳完整測試代碼 lenet5.ipynb