動手學深度學習-03 多層感知機

多層感知機

  1. 多層感知機的基本知識
  2. 使用多層感知機圖像分類的從零開始的實現
  3. 使用pytorch的簡潔實現

多層感知機的基本知識

深度學習主要關注多層模型。在這裏,我們將以多層感知機(multilayer perceptron,MLP)爲例,介紹多層神經網絡的概念。

隱藏層

下圖展示了一個多層感知機的神經網絡圖,它含有一個隱藏層,該層中有5個隱藏單元。

表達公式

激活函數

上述問題的根源在於全連接層只是對數據做仿射變換(affine transformation),而多個仿射變換的疊加仍然是一個仿射變換。解決問題的一個方法是引入非線性變換,例如對隱藏變量使用按元素運算的非線性函數進行變換,然後再作爲下一個全連接層的輸入。這個非線性函數被稱爲激活函數(activation function)。

下面我們介紹幾個常用的激活函數:

ReLU函數

ReLU(rectified linear unit)函數提供了一個很簡單的非線性變換。給定元素xx,該函數定義爲

可以看出,ReLU函數只保留正數元素,並將負數元素清零。爲了直觀地觀察這一非線性變換,我們先定義一個繪圖函數xyplot。

%matplotlib inline
import torch
import numpy as np
import matplotlib.pyplot as plt
import sys
sys.path.append("/home/kesci/input")
import d2lzh1981 as d2l
print(torch.__version__)

#結果
1.3.0
def xyplot(x_vals, y_vals, name):
    # d2l.set_figsize(figsize=(5, 2.5))
    plt.plot(x_vals.detach().numpy(), y_vals.detach().numpy())
    plt.xlabel('x')
    plt.ylabel(name + '(x)')

x = torch.arange(-8.0, 8.0, 0.1, requires_grad=True)
y = x.relu()
xyplot(x, y, 'relu')

y.sum().backward()
xyplot(x, x.grad, 'grad of relu')

 

 

 

y = x.sigmoid()
xyplot(x, y, 'sigmoid')

 

 

 

x.grad.zero_()#梯度清零
y.sum().backward()
#注意必須是y.sum().backward(),因爲必須是標量,求導數鏈接:#https://blog.csdn.net/u010165147/article/details/83994631
xyplot(x, x.grad, 'grad of sigmoid')

 

y = x.tanh()
xyplot(x, y, 'tanh')

x.grad.zero_()
y.sum().backward()
xyplot(x, x.grad, 'grad of tanh')

 

關於激活函數的選擇

ReLu函數是一個通用的激活函數,目前在大多數情況下使用。但是,ReLU函數只能在隱藏層中使用

用於分類器時,sigmoid函數及其組合通常效果更好。由於梯度消失問題,有時要避免使用sigmoid和tanh函數。

在神經網絡層數較多的時候,最好使用ReLu函數,ReLu函數比較簡單計算量少,而sigmoid和tanh函數計算量大很多。

在選擇激活函數的時候可以先選用ReLu函數如果效果不理想可以嘗試其他激活函數。

 

 多層感知機從零開始的實現

import torch
import numpy as np
import sys
sys.path.append("/home/kesci/input")
import d2lzh1981 as d2l
print(torch.__version__)
#結果
#1.3.0

 獲取訓練集

batch_size = 256
train_iter, test_iter = d2l.load_data_fashion_mnist(batch_size,root='/home/kesci/input/FashionMNIST2065')

 定義模型參數

num_inputs, num_outputs, num_hiddens = 784, 10, 256

W1 = torch.tensor(np.random.normal(0, 0.01, (num_inputs, num_hiddens)), dtype=torch.float)
b1 = torch.zeros(num_hiddens, dtype=torch.float)
W2 = torch.tensor(np.random.normal(0, 0.01, (num_hiddens, num_outputs)), dtype=torch.float)
b2 = torch.zeros(num_outputs, dtype=torch.float)

params = [W1, b1, W2, b2]
for param in params:
    param.requires_grad_(requires_grad=True)

 

定義激活函數

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

定義網絡和損失函數

def net(X):
    X = X.view((-1, num_inputs))
    H = relu(torch.matmul(X, W1) + b1)
    return torch.matmul(H, W2) + b2
loss = torch.nn.CrossEntropyLoss()

訓練

num_epochs, lr = 5, 100.0
# 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:
#                 d2l.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))

d2l.train_ch3(net, train_iter, test_iter, loss, num_epochs, batch_size, params, lr)

#結果
epoch 1, loss 0.0030, train acc 0.712, test acc 0.806
epoch 2, loss 0.0019, train acc 0.821, test acc 0.806
epoch 3, loss 0.0017, train acc 0.847, test acc 0.825
epoch 4, loss 0.0015, train acc 0.856, test acc 0.834
epoch 5, loss 0.0015, train acc 0.863, test acc 0.847

多層感知機pytorch實現

import torch
from torch import nn
from torch.nn import init
import numpy as np
import sys
sys.path.append("/home/kesci/input")
import d2lzh1981 as d2l

print(torch.__version__)
#1.3.0

#初始化模型和各個參數
num_inputs, num_outputs, num_hiddens = 784, 10, 256
    
net = nn.Sequential(
        d2l.FlattenLayer(),
        nn.Linear(num_inputs, num_hiddens),
        nn.ReLU(),
        nn.Linear(num_hiddens, num_outputs), 
        )
    
for params in net.parameters():
    init.normal_(params, mean=0, std=0.01)

#訓練
batch_size = 256
train_iter, test_iter = d2l.load_data_fashion_mnist(batch_size,root='/home/kesci/input/FashionMNIST2065')
loss = torch.nn.CrossEntropyLoss()

optimizer = torch.optim.SGD(net.parameters(), lr=0.5)

num_epochs = 5
d2l.train_ch3(net, train_iter, test_iter, loss, num_epochs, batch_size, None, None, optimizer)

#結果
epoch 1, loss 0.0031, train acc 0.701, test acc 0.774
epoch 2, loss 0.0019, train acc 0.821, test acc 0.806
epoch 3, loss 0.0017, train acc 0.841, test acc 0.805
epoch 4, loss 0.0015, train acc 0.855, test acc 0.834
epoch 5, loss 0.0014, train acc 0.866, test acc 0.840

關注公衆號“AI算法與數學之美”,並回復“動手學深度學習”可獲得本章所有代碼

歡迎大家指正和留言評論

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章