神经网络的灵活性也是它的主要缺点之一:有太多超参数可以调整。
#Number of Neurons per Hidden Layer
对于每个隐藏层的神经元数目,最佳实践是漏斗模型,即逐层减少。因为许多低级特征可以合并为更少的高级特征。 但是一般来说,通过增加层数而不是每层神经元数量,你将获得更多的收益。
#Number of Hidden Layers
对于隐藏层数目,虽然已经证明,只需一个包含足够多神经元的隐层,MLP就能以任意精度逼近任意复杂度的连续函数,但他们忽略了这样一个事实,即深度网络的训练效率要比浅层网络高得多,也就是说可以使用比浅层网络更少的神经元来模拟复杂函数,从而使它们更快地训练。
底层的隐藏层建模低级的结构(抽取低级的细粒度的更具体的特征,比如各种形状和方向的线段),中间的隐藏层结合这些低级特征组成中间级特征(比如组成方形和圆形),最高级隐藏层和输出层结合这些中级特征组成高级的粗粒度的目标特征(比如一张人脸)。
所以完全可以将DNN所提取的特征送给SVM、LR等传统机器学习模型完成分类任务(loss function使用SVM的hinge损失或者LR的对数损失即可)。
假如现在我们已经训练好了一个人脸识别的深度学习模型,现在又来了一个新的业务让我们训练一个动物识别的模型,这时我们可以重用人脸识别模型所抽取的低级特征,即使用其前面几层隐藏层的权重初始化新模型,因为低级的细粒度特征大家都一样,可以共享(而且也因为使用了其他领域的样本而使得低级特征更加多样化),我们只需要学习高级的特征而不用从头开始所有层级的特征,这就是迁移学习,它可以使训练更快并且只需少量的样本即可达到很好的效果。后面会详细讲到。
#梯度爆炸梯度消失
一般来说,网络层数越多效果越好。但是随着网络层数的增多,训练会变慢并且容易过拟合,更严重的是,会导致棘手的梯度消失和梯度爆炸问题,使得浅层神经元非常难以训练。
由上节反向传播的基本原理我们知道,根据偏误差反向传递更新参数,由于偏误差一般随着反向传递的过程变得越来越小,
由上节反向传播的基本原理我们知道,根据偏误差反向传递更新参数,由于偏误差一般随着反向传递的过程变得越来越小,从而导致浅层神经元参数几乎不变,这就是梯度消失问题;在某些情况下,偏误差会随着反向传递的过程变得越来越大,浅层神经元大幅度的更新梯度导致训练无法收敛(发散),这是梯度爆炸问题。
#激活函数
#Sigmoid
使用这种激活函数时,如果再用(0, 1)正态分布初始化参数,会导致神经网络的每一层输出的方差比输入方差大很多,因为Sigmoid不是0均值的,所以当神经网络正向计算的时候,方差不断增大,也就是说最终输出值趋近0和1两个极端,这时候回过头来看看反向传播的参数更新过程:
Oj(1-Oj)其实就是Sigmoid函数导数求解公式,当Oj趋近0和1两个极端时,权重更
新量几乎为0,所以这种情况下就导致了梯度消失。
可以通过Xavier initialization解决Sigmoid激活函数存在的梯度消失问题。这种初始化方式可以使得神经网络每一层的输出方差和输入方差相等,并且还能在BackPropagation的过程中保证流过每一层之前和之后,梯度的方差相等。
he_init = tf.contrib.layers.variance_scaling_initializer()
hidden1 = fully_connected(X, n_hidden1, weights_initializer=he_init,
scope="h1")
#tanh(hyperbolic tangent)
tanh函数图像与Sigmoid类似,所以也会偶尔出现梯度消失问题,但是由于它是0均值的,所以效果比Sigmoid激活函数稍好,但是其计算稍复杂,所以训练慢。
#ReLU(Rectified Linear Unit)
大多数情况下,我们选择使用ReLU激活函数就