多层感知机

目录:1.多层感知机的基础知识

            2.多层感知机的pytorch代码实现与讲解

多层感知机的基础知识

1.基础知识:多层感知机(MLP,Multilayer Perceptron)也叫人工神经网络(ANN,Artificial Neural Network),除了输入输出层,它中间可以有多个隐层,最简单的MLP只含一个隐层,即三层的结构,如下图:

                                                     

从上图可以看到,多层感知机层与层之间是全连接的。多层感知机最底层是输入层,中间是隐藏层,最后是输出层。 

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

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

                                                                    H = XW_{h} \dotplus b _{h}

                                                                    O = HW_{o} \dotplus b _{o}

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

                                            O = W_{o}\left ( XW_{h} \dotplus b _{h} \right ) \dotplus b _{o} = XW_{o}W_{h} \dotplus W_{o}b_{h} \dotplus b_{o} 

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

 

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

1):为何使用激活函数?

     a:不使用激活函数,每一层输出都是上层输入的线性函数,无论神经网络有多少层,输出都是输入的线性组合。

     b:使用激活函数,能够给神经元引入非线性因素,使得神经网络可以任意逼近任何非线性函数,这样神经网络就可以利用到更多的非线性模型中。

2):激活函数需要具备以下几点性质:

   a:连续并可导(允许少数点上不可导)的非线性函数。可导的激活函数可以直接利用数值优化的方法来学习网络参数。

    b:激活函数及其导函数要尽可能的简单,有利于提高网络计算效率。

    c:激活函数的导函数的值域要在一个合适的区间内,不能太大也不能太小,否则会影响训练的效率和稳定性。 

3):常见的激活函数及其优缺点:

   a:Sigmoid函数表达式

                                                     f\left ( z \right ) = \frac{1}{1\dotplus e^{-z}}

    b:特点:它能够把输入的连续实值变换为0和1之间的输出,特别的,如果是非常大的负数,那么输出就是0;如果是非常大的正数,输出就是1.

    c:优缺点:sigmoid函数曾经被使用的很多,不过近年来,用它的人越来越少了。主要是因为它固有的一些 缺点。1:在深度神经网络中梯度反向传递时导致梯度爆炸和梯度消失,其中梯度爆炸发生的概率非常小,而梯度消失发生的概率比较大。2:Sigmoid 的 output 不是0均值(即zero-centered)。3:其解析式中含有幂运算,计算机求解时相对来讲比较耗时。

 

   a:tanh函数表达式

                                                         tanh\left ( x \right ) = \frac{(e^{x} - e^{-x}) }{(e^{x} \dotplus e^{-x}) }

   b:它解决了Sigmoid函数的不是zero-centered输出问题,然而,梯度消失(gradient vanishing)的问题和幂运算的问题仍然存在。

 

    a:Relu函数解析式

                                                  ReLU = max\left ( 0, x \right )

     b:特点:ReLU函数其实就是一个取最大值函数,注意这并不是全区间可导的,但是我们可以取sub-gradient。

     c:优缺点:1.解决了gradient vanishing问题 (在正区间)。2.计算速度非常快,只需要判断输入是否大于0。3.收敛速度远快于sigmoid和tanh。4.ReLU的输出不是zero-centered。5.Dead ReLU Problem,指的是某些神经元可能永远不会被激活,导致相应的参数永远不能被更新。有两个主要原因可能导致这种情况产生: (1) 非常不幸的参数初始化,这种情况比较少见 (2) learning rate太高导致在训练过程中参数更新太大,不幸使网络进入这种状态。解决方法是可以采用Xavier初始化方法,以及避免将learning rate设置太大或使用adagrad等自动调节learning rate的算法。

4):关于激活函数的选择?

 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("/home/kesci/input")
import d2lzh1981 as d2l

#此代码实现三层感知机

num_inputs, num_outputs, num_hiddens = 784, 10, 256   # 输入层、隐藏层和输出层节点个数

# 定义感知机的网络结构    
net = nn.Sequential(
        d2l.FlattenLayer(),   # size:batch_size, 784
        nn.Linear(num_inputs, num_hiddens),  # size:784, 10  输出:batch_size, 10
        nn.ReLU(),   # 激活函数 筛选有效特征
        nn.Linear(num_hiddens, num_outputs),  # size:10, 256 输出:batch_size, 256 
        )
    
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)

 

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