1. 程式人生 > 程式設計 >使用 PyTorch 實現 MLP 並在 MNIST 資料集上驗證方式

使用 PyTorch 實現 MLP 並在 MNIST 資料集上驗證方式

簡介

這是深度學習課程的第一個實驗,主要目的就是熟悉 Pytorch 框架。MLP 是多層感知器,我這次實現的是四層感知器,程式碼和思路參考了網上的很多文章。個人認為,感知器的程式碼大同小異,尤其是用 Pytorch 實現,除了層數和引數外,程式碼都很相似。

Pytorch 寫神經網路的主要步驟主要有以下幾步:

1 構建網路結構

2 載入資料集

3 訓練神經網路(包括優化器的選擇和 Loss 的計算)

4 測試神經網路

下面將從這四個方面介紹 Pytorch 搭建 MLP 的過程。

專案程式碼地址:lab1

過程

構建網路結構

神經網路最重要的就是搭建網路,第一步就是定義網路結構。我這裡是建立了一個四層的感知器,引數是根據 MNIST 資料集設定的,網路結構如下:

# 建立一個四層感知機網路
class MLP(torch.nn.Module):  # 繼承 torch 的 Module
  def __init__(self):
    super(MLP,self).__init__()  # 
    # 初始化三層神經網路 兩個全連線的隱藏層,一個輸出層
    self.fc1 = torch.nn.Linear(784,512) # 第一個隱含層 
    self.fc2 = torch.nn.Linear(512,128) # 第二個隱含層
    self.fc3 = torch.nn.Linear(128,10)  # 輸出層
    
  def forward(self,din):
    # 前向傳播, 輸入值:din,返回值 dout
    din = din.view(-1,28*28)    # 將一個多行的Tensor,拼接成一行
    dout = F.relu(self.fc1(din))  # 使用 relu 啟用函式
    dout = F.relu(self.fc2(dout))
    dout = F.softmax(self.fc3(dout),dim=1) # 輸出層使用 softmax 啟用函式
    # 10個數字實際上是10個類別,輸出是概率分佈,最後選取概率最大的作為預測值輸出
    return dout

網路結構其實很簡單,設定了三層 Linear。隱含層啟用函式使用 Relu; 輸出層使用 Softmax。網上還有其他的結構使用了 droupout,我覺得入門的話有點高階,而且放在這裡並沒有什麼用,搞得很麻煩還不能提高準確率。

載入資料集

第二步就是定義全域性變數,並載入 MNIST 資料集:

# 定義全域性變數
n_epochs = 10   # epoch 的數目
batch_size = 20 # 決定每次讀取多少圖片

# 定義訓練集個測試集,如果找不到資料,就下載
train_data = datasets.MNIST(root = './data',train = True,download = True,transform = transforms.ToTensor())
test_data = datasets.MNIST(root = './data',transform = transforms.ToTensor())
# 建立載入器
train_loader = torch.utils.data.DataLoader(train_data,batch_size = batch_size,num_workers = 0)
test_loader = torch.utils.data.DataLoader(test_data,num_workers = 0)

這裡引數很多,所以就有很多需要注意的地方了:

root 引數的資料夾即使不存在也沒關係,會自動建立

transform 引數,如果不知道要對資料集進行什麼變化,這裡可自動忽略

batch_size 引數的大小決定了一次訓練多少資料,相當於定義了每個 epoch 中反向傳播的次數

num_workers 引數預設是 0,即不併行處理資料;我這裡設定大於 0 的時候,總是報錯,建議設成預設值

如果不理解 epoch 和 batch_size,可以上網查一下資料。(我剛開始學深度學習的時候也是不懂的)

訓練神經網路

第三步就是訓練網路了,程式碼如下:

# 訓練神經網路
def train():
  # 定義損失函式和優化器
  lossfunc = torch.nn.CrossEntropyLoss()
  optimizer = torch.optim.SGD(params = model.parameters(),lr = 0.01)
  # 開始訓練
  for epoch in range(n_epochs):
    train_loss = 0.0
    for data,target in train_loader:
      optimizer.zero_grad()  # 清空上一步的殘餘更新引數值
      output = model(data)  # 得到預測值
      loss = lossfunc(output,target) # 計算兩者的誤差
      loss.backward()     # 誤差反向傳播,計算引數更新值
      optimizer.step()    # 將引數更新值施加到 net 的 parameters 上
      train_loss += loss.item()*data.size(0)
    train_loss = train_loss / len(train_loader.dataset)
    print('Epoch: {} \tTraining Loss: {:.6f}'.format(epoch + 1,train_loss))

訓練之前要定義損失函式和優化器,這裡其實有很多學問,但本文就不講了,理論太多了。

訓練過程就是兩層 for 迴圈:外層是遍歷訓練集的次數;內層是每次的批次(batch)。最後,輸出每個 epoch 的 loss。(每次訓練的目的是使 loss 函式減小,以達到訓練集上更高的準確率)

測試神經網路

最後,就是在測試集上進行測試,程式碼如下:

# 在資料集上測試神經網路
def test():
  correct = 0
  total = 0
  with torch.no_grad(): # 訓練集中不需要反向傳播
    for data in test_loader:
      images,labels = data
      outputs = model(images)
      _,predicted = torch.max(outputs.data,1)
      total += labels.size(0)
      correct += (predicted == labels).sum().item()
  print('Accuracy of the network on the test images: %d %%' % (
    100 * correct / total))
  return 100.0 * correct / total

這個測試的程式碼是同學給我的,我覺得這個測試的程式碼特別好,很簡潔,一直用的這個。

程式碼首先設定 torch.no_grad(),定義後面的程式碼不需要計算梯度,能夠節省一些記憶體空間。然後,對測試集中的每個 batch 進行測試,統計總數和準確數,最後計算準確率並輸出。

通常是選擇邊訓練邊測試的,這裡先就按步驟一步一步來做。

有的測試程式碼前面要加上 model.eval(),表示這是訓練狀態。但這裡不需要,如果沒有 Batch Normalization 和 Dropout 方法,加和不加的效果是一樣的。

完整程式碼

'''
系統環境: Windows10
Python版本: 3.7
PyTorch版本: 1.1.0
cuda: no
'''
import torch
import torch.nn.functional as F  # 激勵函式的庫
from torchvision import datasets
import torchvision.transforms as transforms
import numpy as np

# 定義全域性變數
n_epochs = 10   # epoch 的數目
batch_size = 20 # 決定每次讀取多少圖片

# 定義訓練集個測試集,如果找不到資料,就下載
train_data = datasets.MNIST(root = './data',num_workers = 0)


# 建立一個四層感知機網路
class MLP(torch.nn.Module):  # 繼承 torch 的 Module
  def __init__(self):
    super(MLP,dim=1) # 輸出層使用 softmax 啟用函式
    # 10個數字實際上是10個類別,輸出是概率分佈,最後選取概率最大的作為預測值輸出
    return dout

# 訓練神經網路
def train():
  #定義損失函式和優化器
  lossfunc = torch.nn.CrossEntropyLoss()
  optimizer = torch.optim.SGD(params = model.parameters(),train_loss))
    # 每遍歷一遍資料集,測試一下準確率
    test()

# 在資料集上測試神經網路
def test():
  correct = 0
  total = 0
  with torch.no_grad(): # 訓練集中不需要反向傳播
    for data in test_loader:
      images,1)
      total += labels.size(0)
      correct += (predicted == labels).sum().item()
  print('Accuracy of the network on the test images: %d %%' % (
    100 * correct / total))
  return 100.0 * correct / total

# 宣告感知器網路
model = MLP()

if __name__ == '__main__':
  train()

10 個 epoch 的訓練效果,最後能達到大約 85% 的準確率。可以適當增加 epoch,但程式碼裡沒有用 gpu 執行,可能會比較慢。

以上這篇使用 PyTorch 實現 MLP 並在 MNIST 資料集上驗證方式就是小編分享給大家的全部內容了,希望能給大家一個參考,也希望大家多多支援我們。