多层感知机

多层感知机

我们已经介绍了包括线性回归和softmax回归在内的单层神经网络。然而深度学习主要关注多层模型。在本节中,我们将以多层感知机(multilayer perceptron,MLP)为例,介绍多层神经网络的概念。

隐藏层

多层感知机在单层神经网络的基础上引入了一到多个隐藏层(hidden layer)。隐藏层位于输入层和输出层之间。图3.3展示了一个多层感知机的神经网络图。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-256XSMdf-1581672381242)(https://img.vim-cn.com/2e/80d067a824cf71512d77c655855fe8c3488cc3.png)]

在图3.3所示的多层感知机中,输入和输出个数分别为4和3,中间的隐藏层中包含了5个隐藏单元(hidden unit)。由于输入层不涉及计算,图3.3中的多层感知机的层数为2。由图3.3可见,隐藏层中的神经元和输入层中各个输入完全连接,输出层中的神经元和隐藏层中的各个神经元也完全连接。因此,多层感知机中的隐藏层和输出层都是全连接层。

具体来说,给定一个小批量样本 X ∈ R n × d \boldsymbol{X} \in \mathbb{R}^{n \times d} XRn×d,其批量大小为 n n n,输入个数为 d d d。假设多层感知机只有一个隐藏层,其中隐藏单元个数为 h h h。记隐藏层的输出(也称为隐藏层变量或隐藏变量)为 H \boldsymbol{H} H,有 H ∈ R n × h \boldsymbol{H} \in \mathbb{R}^{n \times h} HRn×h。因为隐藏层和输出层均是全连接层,可以设隐藏层的权重参数和偏差参数分别为 W h ∈ R d × h \boldsymbol{W}_h \in \mathbb{R}^{d \times h} WhRd×h b h ∈ R 1 × h \boldsymbol{b}_h \in \mathbb{R}^{1 \times h} bhR1×h,输出层的权重和偏差参数分别为 W o ∈ R h × q \boldsymbol{W}_o \in \mathbb{R}^{h \times q} WoRh×q b o ∈ R 1 × q \boldsymbol{b}_o \in \mathbb{R}^{1 \times q} boR1×q

我们先来看一种含单隐藏层的多层感知机的设计。其输出 O ∈ R n × q \boldsymbol{O} \in \mathbb{R}^{n \times q} ORn×q的计算为

H = X W h + b h , O = H W o + b o , \begin{aligned} \boldsymbol{H} &= \boldsymbol{X} \boldsymbol{W}_h + \boldsymbol{b}_h,\\ \boldsymbol{O} &= \boldsymbol{H} \boldsymbol{W}_o + \boldsymbol{b}_o, \end{aligned} HO=XWh+bh,=HWo+bo,

也就是将隐藏层的输出直接作为输出层的输入。如果将以上两个式子联立起来,可以得到

O = ( X W h + b h ) W o + b o = X W h W o + b h W o + b o . \boldsymbol{O} = (\boldsymbol{X} \boldsymbol{W}_h + \boldsymbol{b}_h)\boldsymbol{W}_o + \boldsymbol{b}_o = \boldsymbol{X} \boldsymbol{W}_h\boldsymbol{W}_o + \boldsymbol{b}_h \boldsymbol{W}_o + \boldsymbol{b}_o. O=(XWh+bh)Wo+bo=XWhWo+bhWo+bo.

从联立后的式子可以看出,虽然神经网络引入了隐藏层,却依然等价于一个单层神经网络:其中输出层权重参数为 W h W o \boldsymbol{W}_h\boldsymbol{W}_o WhWo,偏差参数为 b h W o + b o \boldsymbol{b}_h \boldsymbol{W}_o + \boldsymbol{b}_o bhWo+bo。不难发现,即便再添加更多的隐藏层,以上设计依然只能与仅含输出层的单层神经网络等价。

激活函数

上述问题的根源在于全连接层只是对数据做仿射变换(affine transformation),而多个仿射变换的叠加仍然是一个仿射变换。解决问题的一个方法是引入非线性变换,例如对隐藏变量使用按元素运算的非线性函数进行变换,然后再作为下一个全连接层的输入。这个非线性函数被称为激活函数(activation function)。下面我们介绍几个常用的激活函数。

ReLU函数

ReLU(rectified linear unit)函数提供了一个很简单的非线性变换。给定元素 x x x,该函数定义为

ReLU ( x ) = max ⁡ ( x , 0 ) . \text{ReLU}(x) = \max(x, 0). ReLU(x)=max(x,0).

可以看出,ReLU函数只保留正数元素,并将负数元素清零。为了直观地观察这一非线性变换,我们先定义一个绘图函数xyplot

import sys
sys.path.insert(0, '..')

import numpy
import matplotlib.pyplot as plt
import torch
import torch.nn as nn
from torch.autograd import Variable
def xyplot(x_vals,y_vals,name):
    x_vals=x_vals.detach().numpy() # we can't directly use var.numpy() because varibles might 
    y_vals=y_vals.detach().numpy() # already required grad.,thus using var.detach().numpy() 
    plt.plot(x_vals,y_vals) 
    plt.xlabel('x')
    plt.ylabel(name+'(x)')
x=Variable(torch.arange(-8.0,8.0,0.1,dtype=torch.float32).reshape(int(16/0.1),1),requires_grad=True)
y=torch.nn.functional.relu(x)
xyplot(x,y,'relu')

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3FjTATZg-1581672381243)(output_2_0.png)]

y.backward(torch.ones_like(x),retain_graph=True)
xyplot(x,x.grad,"grad of relu")

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gBHZHlgU-1581672381244)(output_3_0.png)]

sigmod函数

sigmod函数可将元素的值变为0,1之间

σ ( s i g m o d ) = 1 1 + e x p ( − x ) \sigma(sigmod)= \frac{1}{1+exp^(-x)} σ(sigmod)=1+exp(x)1

x=Variable(torch.arange(-8.0,8.0,0.1,dtype=torch.float32).reshape(int(16/0.1),1),requires_grad=True)
y=torch.sigmoid(x)
xyplot(x,y,'sigmoid')

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MZuZXhBW-1581672381244)(output_5_0.png)]

y.backward(torch.ones_like(x),retain_graph=True)
xyplot(x,x.grad,'grad of sigmoid')

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LuFjIIsL-1581672381245)(output_6_0.png)]

tanh 函数

tanh函数可以将元素的值变为-1,1之间
t a n h ( x ) = 1 − e x p ( − 2 x ) 1 + e x p ( − 2 x ) tanh(x) = \frac{1-exp^(-2x)}{1+exp^(-2x)} tanh(x)=1+exp(2x)1exp(2x)

x=Variable(torch.arange(-8.0,8.0,0.1,dtype=torch.float32).reshape(int(16/0.1),1),requires_grad=True)
y=torch.tanh(x)
xyplot(x,y,"tanh")

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gaBog9BH-1581672381245)(output_8_0.png)]

y.backward(torch.ones_like(x),retain_graph=True)
xyplot(x,x.grad,"grad of tanh")

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-trb1XhVJ-1581672381246)(output_9_0.png)]

关于激活函数的选择

ReLu函数是一个通用的激活函数,目前在大多数情况下使用。但是,ReLU函数只能在隐藏层中使用。

用于分类器时,sigmoid函数及其组合通常效果更好。由于梯度消失问题,有时要避免使用sigmoid和tanh函数。

在神经网络层数较多的时候,最好使用ReLu函数,ReLu函数比较简单计算量少,而sigmoid和tanh函数计算量大很多。

在选择激活函数的时候可以先选用ReLu函数如果效果不理想可以尝试其他激活函数。

多层感知机的pytorch实现

import torch
from torch import nn
from torch.nn import init
import numpy as np
import sys
sys.path.append(".") 
import d2lzh_pytorch as d2l

print(torch.__version__)
1.3.1
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)
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.703, test acc 0.757
epoch 2, loss 0.0019, train acc 0.824, test acc 0.822
epoch 3, loss 0.0016, train acc 0.845, test acc 0.825
epoch 4, loss 0.0015, train acc 0.855, test acc 0.811
epoch 5, loss 0.0014, train acc 0.865, test acc 0.846
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值