深度学习:卷积神经网络技术与实践
上QQ阅读APP看书,第一时间看更新

3.2 多层神经网络

从结构上划分,神经网络由3部分组成,分别是输入层(Input Layer)、隐藏层(Hidden Layer)、输出层(Output Layer)。以如图3-2所示的神经网络结构为例,该神经网络有1个输入层、3个隐藏层、1个输出层。

3.2.1 隐藏层

在一个完整的神经网络中,除去第1层的输入层和最后一层的输出层以外,二者之间的所有网络层都称为隐藏层。隐藏的含义可以理解为,这些网络层既不从外界直接接收数据,也不向外界直接发送数据,处于网络的内部。隐藏层的作用是对于输入层传递进来的数据进行特定的处理,并将处理后的数据传递给输出层。

图3-2 神经网络结构

如图3-3所示是单个神经元工作方式示意图。当神经元有输入到来时,神经网络会给输入数据分配两个线性分量:权重(weight)和偏置(bias)。

图3-3 单个神经元工作方式示意图

对于神经元的每个输入xi,都会被分配与之相对应的权重wi,则该神经元的输入为:

偏置b则被加到输入与权重相乘的结果中,目的是改变结果的范围。经过偏置b后产生的值为:

对输入的线性分量变换结束后,此时的神经网络是一个线性模型。在实际应用中,神经网络模型所要解决的问题往往都是复杂的、非线性的。为了弥补线性模型表达能力不足的缺点,需要在线性分量变换后增加一个非线性函数,称为激活函数(activation function)。假设激活函数为f,则最终从神经元得到的输出为:

从图3-3的例子可知,每个神经元只有一个输出。但从图3-2可以看出,每个神经元可以有多个输入和多个输出,实际上这并不矛盾。图3-2的网络层采用了全连接方式,即每个神经元的输入都是上一层所有神经元的输出的加权,每个神经元的输出都与下一层中的每个神经元相连,作为下一层中每个神经元的输入。也就是说,一个神经元的输出可以作为下一个网络层中多个神经元的输入,故可以理解为一个神经元有多个相同的输出。

当神经网络中网络层之间采用全连接方式时,往往会再采用Dropout来防止神经网络过拟合的现象。

不同复杂程度的神经网络拥有不同数量的隐藏层,每个隐藏层所拥有的神经元个数也不尽相同。隐藏层的层数与每个隐藏层中神经元个数的设定都可由神经网络搭建者自行完成,但不同的参数数值对所搭建的神经网络整体性能都有着不同程度的影响。关于如何确定隐藏层层数与神经元个数的问题,目前并无完善的理论支撑,往往需要根据经验而定。寻找合适数值的过程也是一个试错的过程,进而得到一个较为合适的网络层数和神经元个数。

3.2.2 输入层与输出层

输入层又称可视层,是神经网络暴露在外部的网络层。输入层由若干个神经元组成,这些神经元的作用是从外部数据集中获取数据并输入神经网络,将输入值传递给隐藏层。因此,输入层的神经元个数也需要与输入数据的维度相对应。

神经网络的最后一层即为输出层,输出层的神经元个数由具体问题所决定。若神经网络用于解决回归类问题或二分类问题,输出层的神经元个数可能为一个;若神经网络用于解决多分类问题,输出层的神经元个数则由所分类的类别个数决定。例如,手写体数据集(MNIST)分类问题共分10类(数字0~9),则输出层的神经元个数为10个。

通常输出层会结合激活函数完成输出任务。当神经网络用于解决回归问题时,可能没有激活函数;当神经网络用于解决二分类问题时,可以使用激活函数Sigmoid;当神经网络用于解决多分类问题时,可以使用激活函数Softmax。

基于Keras搭建神经网络,可以选择函数API模型和序贯Sequential模型。函数API模型较为复杂和灵活,可以分阶段输入和分阶段输出,层与层之间可任意连接,编译速度较慢;序贯Sequential模型是函数API模型的一个特例,单输入、单输出,层与层之间不能跨层连接,只能相邻层连接,编译速度较快。

全连接方式将通过Dense神经网络层实现。为方便后续直接调用Dense,先对Dense做详细介绍。代码及注释如下:


keras.layers.Dense(
                  units,           #该层神经元个数,也是该层输出神经元个数
                  activation=None, #选择激活函数
                  use_bias=True,   #是否添加偏置
                  kernel_initializer='glorot_uniform', #权重初始化方法
                  bias_initializer='zeros', #偏置初始化方法
                  kernel_regularizer=None,   #对权重施加正则项
                  bias_regularizer=None,     #对偏置施加正则项
                  activity_regularizer=None, #对输出施加正则项
                  kernel_constraint=None,    #对权重施加约束项
                  bias_constraint=None       #对偏置施加约束项
)

下面以一个简单的神经网络结构为例,即网络结构中包含一个输入层、一个隐藏层、一个输出层,隐藏层激活函数选取Relu函数,输出层激活函数选取Softmax函数。

选择函数API模型搭建该网络,主要语句如下:


from keras.models import Model
from keras.layers import Input,Dense
#建立输入层,M为输入数据维度
inputs = Input(shape=(M,))
#建立隐藏层,隐藏层神经元个数为units,激活函数为activation
hidden1= Dense(units, activation= activation)(inputs)
#建立输出层,N为输出层神经元个数,即分类个数
predictions = Dense(N, activation= activation)( hidden1)
#通过Model定义网络模型的输入为inputs,输出为predictions,得到神经网络模型model
model = Model(inputs=inputs, outputs=predictions)

选择序贯Sequential模型搭建该网络,通过model.add()来添加所需的神经网络层。主要语句如下:


from keras.models import Sequential
from keras.layers.core import Dense, Activation
model = Sequential()
#建立输入层与隐藏层,M为输入数据维度
model.add(Dense(units,input_dim=M)) 
#激活函数选择Relu函数
model.add(Activation('relu'))
#建立输出层,N为输出层神经元个数,该层的输入神经元个数默认为上一层神经元的输出,不需要额外设置
model.add(Dense(N))
#激活函数选择Softmax函数
model.add(Activation('softmax'))