pytorch實現MLP並在MNIST數據集上驗證


寫在前面

由於MLP的實現框架已經非常完善,網上搜到的代碼大都大同小異,而且MLP的實現是deeplearning學習過程中較為基礎的一個實驗。因此完全可以找一份源碼以參考,重點在於照着源碼手敲一遍,以熟悉pytorch的基本操作。

實驗要求

熟悉pytorch的基本操作:用pytorch實現MLP,並在MNIST數據集上進行訓練

環境配置

實驗環境如下:

  • Win10
  • python3.8
  • Anaconda3
  • Cuda10.2 + cudnn v7
  • GPU : NVIDIA GeForce MX250

配置環境的過程中遇到了一些問題,解決方案如下:

  1. anaconda下載過慢

    使用清華鏡像源,直接百度搜索即可

  2. pytorch安裝失敗

    這里我首先使用的是pip的安裝方法,失敗多次后嘗試了使用anaconda,然后配置了清華鏡像源,最后成功。參考的教程如下:
    win10快速安裝pytorch,清華鏡像源

    當然也可以直接去pytorch官網下載所需版本的whl文件,然后手動pip安裝。由於這種方式我已經學會了,為了學習anaconda,所以沒有采用這種方式。具體方式可以百度如何使用whl。順便貼下pytorch的whl的下載頁面

注意:pytorch的版本是要嚴格對應是否使用GPU、python版本、cuda版本的,如需手動下載pytorch的安裝包,需搞懂其whl文件的命名格式

另外還學習了anaconda的一些基本操作與原理,參考如下:
Anaconda完全入門指南

實驗過程

最終代碼見github:hit-deeplearning-1

首先設置一些全局變量,加載數據。batch_size決定了每次向網絡中輸入的樣本數,epoch決定了整個數據集的迭代次數,具體作用與大小如何調整可參考附錄中的博客。

將數據讀入,如果數據不存在於本地,則可以自動從網上下載,並保存在本地的data文件夾下。

#一次取出的訓練樣本數
batch_size = 16
# epoch 的數目
n_epochs = 10

#讀取數據
train_data = datasets.MNIST(root="./data", train=True, download=True,transform=transforms.ToTensor())
test_data = datasets.MNIST(root="./data", train=False, download=True, 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, batch_size = batch_size, num_workers = 0)

接下來是創建MLP模型,關於如何創建一個模型,可以參考附錄中的博客,總之創建模型模板,訓練模板都是固定的。

其中LinearviewCrossEntropyLossSGD的用法需重點關注。查看官方文檔或博客解決。

這兩條語句將數據放到了GPU上,同理測試的時候也要這樣做。

data = data.cuda()
target = target.cuda()
class MLP(nn.Module):
    def __init__(self):
        #繼承自父類
        super(MLP, self).__init__()
        #創建一個三層的網絡
        #輸入的28*28為圖片大小,輸出的10為數字的類別數
        hidden_first = 512
        hidden_second = 512
        self.first = nn.Linear(in_features=28*28, out_features=hidden_first)
        self.second = nn.Linear(in_features=hidden_first, out_features=hidden_second)
        self.third = nn.Linear(in_features=hidden_second, out_features=10)

    def forward(self, data):
        #先將圖片數據轉化為1*784的張量
        data = data.view(-1, 28*28)
        data = F.relu(self.first(data))
        data = F.relu((self.second(data)))
        data = F.log_softmax(self.third(data), dim = 1)

        return data

def train():
    # 定義損失函數和優化器
    lossfunc = torch.nn.CrossEntropyLoss().cuda()
    #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()
            #將數據放至GPU並計算輸出
            data = data.cuda()
            target = target.cuda()
            output = model(data)
            #計算誤差
            loss = lossfunc(output, target)
            #反向傳播
            loss.backward()
            #將參數更新至網絡中
            optimizer.step()
            #計算誤差
            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))
        # 每遍歷一遍數據集,測試一下准確率
        test()
    #最后將模型保存
    path = "model.pt"
    torch.save(model, path)

test程序不再貼出,直接調用了一個很常用的test程序。

最后是主程序,在這里將模型放到GPU上。

model = MLP()
#將模型放到GPU上
model = model.cuda()
train()

實驗結果

實驗結果如下,可以看到,當對數據迭代訓練十次時,准確率已經可以達到97%

實驗結果

分別運行了兩次,第一次沒有使用cuda加速,第二次使用了cuda加速,任務管理器分別顯示如下:

未使用cuda

使用cuda

可以看到,未使用cuda加速時,cpu占用率達到了100%,而GPU的使用率為0;而使用cuda加速時,cpu占用率只有49%,而GPU使用率為1%。這里GPU使用率較低的原因很多,比如我程序中batch_size設置的較小,另外只將數據和模型放到了GPU上,cpu上仍有部分代碼與數據。經簡單測試,使用cuda的訓練時間在2:30左右,不使用cuda的訓練時間在3:40左右。

參考博客

使用Pytorch構建MLP模型實現MNIST手寫數字識別

如何創建自定義模型

pytorch教程之nn.Module類詳解——使用Module類來自定義網絡層

epoch和batch是什么

深度學習 | 三個概念:Epoch, Batch, Iteration

如何用GPU加速

從頭學pytorch(十三):使用GPU做計算

PyTorch如何使用GPU加速(CPU與GPU數據的相互轉換)

保存模型

PyTorch模型保存與加載


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM