動手學深度學習10- pytorch多層感知機從零實現


多層感知機

import torch
import numpy as np
import sys
sys.path.append('..')
import d2lzh_pytorch as d2l

我們仍然使用Fashion_MNIST數據集,使用多層感知機對圖像進行分類

batch_size = 256
train_iter,test_iter = d2l.get_fahsion_mnist(batch_size)
定義模型的參數

Fashion_MNIST數據集匯總的圖形的形狀為28x28,類別數為10,本節我們依然使用長度為28x28=784的向量表示一張圖像,因此輸入個數為784,輸出個數為10。設置超參數隱藏單元個數為256。

num_inputs, num_outputs,num_hiddens = 784,10,256
W1 = torch.tensor(np.random.normal(0,0.01,(num_inputs,num_hiddens)),dtype=torch.float32               
                 )
b1 = torch.zeros(num_hiddens,dtype=torch.float32)
W2 = torch.tensor(np.random.normal(0,0.01,(num_hiddens,num_outputs)),dtype=torch.float32
                 )
b2 = torch.zeros(num_outputs,dtype=torch.float32)
params = [W1,b1,W2,b2]
for param in params:
    param.requires_grad_(requires_grad=True)
    
定義激活函數

我們使用max函數來實現ReLU,不是直接調用relu函數

def relu(X):
    return torch.max(input=X, other=torch.tensor(0.0))
定義模型

同softmax回歸一樣,我們通過view函數將每張原始的圖像改成長度為num_inputs的向量。然后我們將實現上一節中多層感知機的計算表達式

def net(X):
    X = X.view((-1, num_inputs))
    H = relu(torch.matmul(X, W1) + b1)
    return torch.matmul(H, W2) + b2
定義損失函數
def sgd(params,lr,batch_size):
    for param in params:
#         param.data -=lr* param.grad/batch_size   
        param.data-= lr* param.grad   # 計算loss使用的是pytorch的交叉熵
# 這個梯度可以不用除以batch_size,pytorch 在計算loss的時候已經除過一次了,
'''
mxnet中的softmaxCrossEntropyLoss在反向傳播的時候相對於延batch維度求和,
而pytorch默認的是求平均,所以用pytorch計算得到的loss也比mxnet小很多
大概得到的mxnet計算得到的1/batch_sie這個量級的,所以反向傳播得到的梯度也小得多
為了得到跟原書差不多的效果,應該吧學習率調成batch_size倍,原書的學習率為0.5,
設置是100,
pytorch在計算loss的時候已經除過一次了,這里個的sgd不用除了
'''
loss = torch.nn.CrossEntropyLoss()

訓練模型
def evaluate_accuracy(data_iter, net):
    acc_sum, n = 0.0, 0
    for X, y in data_iter:
        acc_sum += (net(X).argmax(dim=1) == y).float().sum().item()
        n += y.shape[0]
    return acc_sum / n
def train_ch3(net, train_iter, test_iter, loss, num_epochs, batch_size,
              params=None, lr=None, optimizer=None):
    for epoch in range(num_epochs):
        train_l_sum, train_acc_sum, n = 0.0, 0.0, 0
        for X, y in train_iter:
            y_hat = net(X)
            l = loss(y_hat, y).sum()

            # 梯度清零
            if optimizer is not None:
                optimizer.zero_grad()
            elif params is not None and params[0].grad is not None:
                for param in params:
                    param.grad.data.zero_()

            l.backward()
            if optimizer is None:
                sgd(params, lr, batch_size)
            else:
                optimizer.step()  # “softmax回歸的簡潔實現”一節將用到


            train_l_sum += l.item()
            train_acc_sum += (y_hat.argmax(dim=1) == y).sum().item()
            n += y.shape[0]
        test_acc = evaluate_accuracy(test_iter, net)
        print('epoch %d, loss %.4f, train acc %.3f, test acc %.3f'
              % (epoch + 1, train_l_sum / n, train_acc_sum / n, test_acc))


num_epochs, lr = 5, 0.5
train_ch3(net, train_iter, test_iter, loss, num_epochs, batch_size, params, lr)
epoch 1, loss 0.0031, train acc 0.702, test acc 0.775
epoch 2, loss 0.0019, train acc 0.821, test acc 0.807
epoch 3, loss 0.0016, train acc 0.843, test acc 0.831
epoch 4, loss 0.0015, train acc 0.855, test acc 0.818
epoch 5, loss 0.0014, train acc 0.863, test acc 0.816

小結

  • 可以通過手動實現定義模型以及其參數來實現簡單的多層感知機
  • 多層感知機的層數較多時,這種代碼的實現就會明細的繁瑣,尤其是在定義模型參數的時候


免責聲明!

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



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