理解具有全连接层的神经网络的一个方式是:可以认为它们定义了一个由一系列函数组成的函数族,网络的权重就是每个函数的参数。如此产生的问题是:该函数族的表达能力如何?存在不能被神经网络表达的函数吗?
现在看来,拥有至少一个隐层的神经网络是一个通用的近似器。在研究(例如1989年的论文Approximation by Superpositions of Sigmoidal Function,或者Michael Nielsen的这个直观解释。)中已经证明,给出任意连续函数 f ( x ) f(x) f(x) 和任意 ϵ > 0 \epsilon>0 ϵ>0 ,均存在一个至少含1个隐层的神经网络 g ( x ) g(x) g(x) (并且网络中有合理选择的非线性激活函数,比如sigmoid等),对于 ∀ x \forall x ∀x,使得 ∣ f ( x ) − g ( x ) ∣ < ϵ |f(x)-g(x)|<\epsilon ∣f(x)−g(x)∣<ϵ。换句话说,神经网络可以近似任何连续函数。
之前已经说过神经网络的结构了,在这不重复叙述。假设我们有如下结构的网络
对于这个网络我们建立一个简单的图示?我们对第一个隐藏层记为[1],输出层为[2]。如下图
计算图如下
每个神经元的计算分解步骤如下
第一层中的第一个神经元
第一层中的第二个神经元
将上述网络的隐层激活函数修改为tanh,最后一层同样还是二分类,所以最后一层激活函数依然选择sigmoid函数
前向传播:
Z [ 1 ] = W [ 1 ] X + b [ 1 ] Z^{[1]} = W^{[1]}X+b^{[1]} Z[1]=W[1]X+b[1]
A [ 1 ] = t a n h ( Z [ 1 ] {A}^{[1]}=tanh(Z^{[1]} A[1]=tanh(Z[1]
Z [ 2 ] = W [ 2 ] A [ 1 ] + b [ 2 ] Z^{[2]} = W^{[2]}A^{[1]}+b^{[2]} Z[2]=W[2]A[1]+b[2]
A [ 2 ] = σ ( Z [ 2 ] ) A^{[2]}=\sigma(Z^{[2]}) A[2]=σ(Z[2])
反向梯度下降:
那么通过这个计算图来理解这个过程,单个样本的计算图:
由于网络已经存在两层,所以我们需要从后往前得到导数结果,并且多个样本的情况下改写成
最后一个输出层的参数的导数:
d Z [ 2 ] = A [ 2 ] − Y dZ^{[2]}=A^{[2]}-Y dZ[2]=A[2]−Y
d W [ 2 ] = 1 m d Z [ 2 ] A [ 1 ] T dW^{[2]}=\frac{1}{m}dZ^{[2]}{A^{[1]}}^{T} dW[2]=m1dZ[2]A[1]T
d b [ 2 ] = 1 m n p . s u m ( d Z [ 2 ] , a x i s = 1 ) db^{[2]}=\frac{1}{m}np.sum(dZ^{[2]}, axis=1) db[2]=m1np.sum(dZ[2],axis=1)
隐藏层的导数计算:
d Z [ 1 ] = W [ 2 ] T d Z [ 2 ] ∗ g ′ ( Z [ 1 ] ) = W [ 2 ] T d Z [ 2 ] ∗ ( 1 − g 2 ( Z [ 1 ] ) ) = W [ 2 ] T d Z [ 2 ] ∗ ( 1 − ( A [ 1 ] ) 2 ) dZ^{[1]} = {W^{[2]}}^{T}dZ^{[2]}*g'(Z^{[1]})={W^{[2]}}^{T}dZ^{[2]}*{ \Big( 1-g^{2}(Z^{[1]})} \Big) = {W^{[2]}}^{T}dZ^{[2]}*{(1-(A^{[1]})^{2})} dZ[1]=W[2]TdZ[2]∗g′(Z[1])=W[2]TdZ[2]∗(1−g2(Z[1]))=W[2]TdZ[2]∗(1−(A[1])2)
d W [ 1 ] = 1 m d Z [ 1 ] X T dW^{[1]}=\frac{1}{m}dZ^{[1]}X^{T} dW[1]=m1dZ[1]XT
d b [ 1 ] = 1 m n p . s u m ( d Z [ 1 ] , a x i s = 1 ) db^{[1]} = \frac{1}{m}np.sum(dZ^{[1]}, axis=1) db[1]=m1np.sum(dZ[1],axis=1)
注: f ( x ) = t a n h ( x ) f(x) = tanh(x) f(x)=tanh(x) 的导数 f ′ ( x ) = 1 − f 2 ( x ) f'(x) = 1-f^{2}(x) f′(x)=1−f2(x)
涉及到网络的优化时候,会有不同的激活函数选择有一个问题是神经网络的隐藏层和输出单元用什么激活函数。之前我们都是选用 sigmoid 函数,但有时其他函数的效果会好得多,大多数通过实践得来,没有很好的解释性。
可供选用的激活函数有:
tanh 函数(the hyperbolic tangent function,双曲正切函数):
效果比 sigmoid 函数好,因为函数输出介于 -1 和 1 之间。
注 : tanh 函数存在和 sigmoid 函数一样的缺点:当 z 趋紧无穷大(或无穷小),导数的梯度(即函数的斜率)就趋紧于 0,这使得梯度算法的速度会减慢。
ReLU 函数(the rectified linear unit,修正线性单元)
当 z > 0 时,梯度始终为 1,从而提高神经网络基于梯度算法的运算速度,收敛速度远大于 sigmoid 和 tanh。然而当 z < 0 时,梯度一直为 0,但是实际的运用中,该缺陷的影响不是很大。
Leaky ReLU(带泄漏的 ReLU):
Leaky ReLU 保证在 z < 0 的时候,梯度仍然不为 0。理论上来说,Leaky ReLU 有 ReLU 的所有优点,但在实际操作中没有证明总是好于 ReLU,因此不常用。
使用非线性激活函数和不使用激活函数、直接使用 Logistic 回归没有区别,那么无论神经网络有多少层,输出都是输入的线性组合,与没有隐藏层效果相当,就成了最原始的感知器了。
a [ 1 ] = z [ 1 ] = W [ 1 ] x + b [ 1 ] {a}^{[1]}=z^{[1]} = W^{[1]}x+b^{[1]} a[1]=z[1]=W[1]x+b[1]
a [ 2 ] = z [ 2 ] = W [ 2 ] a [ 1 ] + b [ 2 ] {a}^{[2]}=z^{[2]} = W^{[2]}a^{[1]}+b^{[2]} a[2]=z[2]=W[2]a[1]+b[2]
那么这样的话相当于
a [ 2 ] = z [ 2 ] = W [ 2 ] ( W [ 1 ] x + b [ 1 ] ) + b [ 2 ] = ( W [ 2 ] W [ 1 ] ) x + ( W [ 2 ] b [ 1 ] + b [ 2 ] ) = w x + b {a}^{[2]}=z^{[2]} = W^{[2]}(W^{[1]}x+b^{[1]})+b^{[2]}=(W^{[2]}W^{[1]})x+(W^{[2]}b^{[1]}+b^{[2]})=wx+b a[2]=z[2]=W[2](W[1]x+b[1])+b[2]=(W[2]W[1])x+(W[2]b[1]+b[2])=wx+b
Sigmoid函数饱和使梯度消失。sigmoid神经元有一个不好的特性,就是当神经元的激活在接近0或1处时会饱和:在这些区域,梯度几乎为0。
Tanh:和sigmoid神经元一样,它也存在饱和问题,但是和sigmoid神经元不同的是,它的输出是零中心的(sigmoid为0.5)。
Relu:
优点:
缺点:在训练的时候,ReLU单元比较脆弱并且可能“死掉”。
Leaky ReLU:
总结:“那么该用那种呢?”用ReLU非线性函数。注意设置好学习率,或许可以监控你的网络中死亡的神经元占的比例。如果单元死亡问题困扰你,就试试Leaky ReLU,不要再用sigmoid了。
1、神经网络在实践中非常好用,是因为它们表达出的函数不仅平滑,而且对于数据的统计特性有很好的拟合。同时,网络通过最优化算法(例如梯度下降)能比较容易地学习到这个函数。类似的,虽然在理论上深层网络(使用了多个隐层)和单层网络的表达能力是一样的,但是就实践经验而言,深度网络效果比单层网络好。
2、对于人脸识别等应用,神经网络的第一层从原始图片中提取人脸的轮廓和边缘,每个神经元学习到不同边缘的信息;网络的第二层将第一层学得的边缘信息组合起来,形成人脸的一些局部的特征,例如眼睛、嘴巴等;后面的几层逐步将上一层的特征组合起来,形成人脸的模样。随着神经网络层数的增加,特征也从原来的边缘逐步扩展为人脸的整体,由整体到局部,由简单到复杂。层数越多,那么模型学习的效果也就越精确。
通过例子可以看到,随着神经网络的深度加深,模型能学习到更加复杂的问题,功能也更加强大。
使用浅层网络的时候很多分类等问题得不到很好的解决,所以需要深层的网络。
在这里首先对每层的符号进行一个确定,我们设置L为第几层,n为每一层的个数,L=[L1,L2,L3,L4],n=[5,5,3,1]
首先还是以单个样本来进行表示,每层经过线性计算和激活函数两步计算
z [ 1 ] = W [ 1 ] x + b [ 1 ] , a [ 1 ] = g [ 1 ] ( z [ 1 ] ) , 输 入 x , 输 出 a [ 1 ] z^{[1]} = W^{[1]}x+b^{[1]}, a^{[1]}=g^{[1]}(z^{[1]}),输入x, 输出a^{[1]} z[1]=W[1]x+b[1],a[1]=g[1](z[1]),输入x,输出a[1]
z [ 2 ] = W [ 2 ] a [ 1 ] + b [ 2 ] , a [ 2 ] = g [ 2 ] ( z [ 2 ] ) , 输 入 a [ 1 ] , 输 出 a [ 2 ] z^{[2]} = W^{[2]}a^{[1]}+b^{[2]}, a^{[2]}=g^{[2]}(z^{[2]}),输入a^{[1]}, 输出a^{[2]} z[2]=W[2]a[1]+b[2],a[2]=g[2](z[2]),输入a[1],输出a[2]
z [ 3 ] = W [ 3 ] a [ 2 ] + b [ 3 ] , a [ 3 ] = g [ 3 ] ( z [ 3 ] ) , 输 入 a [ 2 ] , 输 出 a [ 3 ] z^{[3]} = W^{[3]}a^{[2]}+b^{[3]},a^{[3]}=g^{[3]}(z^{[3]}), 输入a^{[2]} , 输出a^{[3]} z[3]=W[3]a[2]+b[3],a[3]=g[3](z[3]),输入a[2],输出a[3]
z [ 4 ] = W [ 4 ] a [ 3 ] + b [ 4 ] , a [ 4 ] = σ ( z [ 4 ] ) , 输 入 a [ 3 ] , 输 出 a [ 4 ] z^{[4]} = W^{[4]}a^{[3]}+b^{[4]},a^{[4]}=\sigma(z^{[4]}), 输入a^{[3]}, 输出a^{[4]} z[4]=W[4]a[3]+b[4],a[4]=σ(z[4]),输入a[3],输出a[4]
我们将上式简单的用通用公式表达出来, x = a [ 0 ] x = a^{[0]} x=a[0]
z [ L ] = W [ L ] a [ L − 1 ] + b [ L ] , a [ L ] = g [ L ] ( z [ L ] ) , 输 入 a [ L − 1 ] , 输 出 a [ L ] z^{[L]} = W^{[L]}a^{[L-1]}+b^{[L]},a^{[L]}=g^{[L]}(z^{[L]}), 输入a^{[L-1]} , 输出a^{[L]} z[L]=W[L]a[L−1]+b[L],a[L]=g[L](z[L]),输入a[L−1],输出a[L]
m个样本的向量表示
Z [ L ] = W [ L ] A [ L − 1 ] + b [ L ] Z^{[L]} = W^{[L]}A^{[L-1]} + b^{[L]} Z[L]=W[L]A[L−1]+b[L]
A [ L ] = g [ L ] ( Z [ L ] ) A^{[L]}=g^{[L]}(Z^{[L]}) A[L]=g[L](Z[L])
输 入 A [ L − 1 ] , 输 出 A [ L ] 输入A^{[L-1]}, 输出A^{[L]} 输入A[L−1],输出A[L]
因为涉及到的层数较多,所以我们通过一个图来表示反向的过程
反向传播的结果(理解)
单个样本的反向传播:
d Z [ l ] = d J d a [ l ] d a [ l ] d Z [ l ] = d a [ l ] ∗ g ′ [ l ] ( Z [ l ] ) dZ^{[l]} = \frac{dJ}{da^{[l]}}\frac{da^{[l]}}{dZ^{[l]}}=da^{[l]}*g'^{[l]}(Z^{[l]}) dZ[l]=da[l]dJdZ[l]da[l]=da[l]∗g′[l](Z[l])
d W [ l ] = d J d Z [ l ] d Z [ l ] d W [ l ] = d Z [ l ] ⋅ a [ l − 1 ] dW^{[l]}=\frac{dJ}{dZ^{[l]}}\frac{dZ^{[l]}}{dW^{[l]}}=dZ^{[l]}\cdot a^{[l-1]} dW[l]=dZ[l]dJdW[l]dZ[l]=dZ[l]⋅a[l−1]
d b [ l ] = d J d Z [ l ] d Z [ l ] d b [ l ] = d Z [ l ] db^{[l]}=\frac{dJ}{dZ^{[l]}}\frac{dZ^{[l]}}{db^{[l]}}=dZ^{[l]} db[l]=dZ[l]dJdb[l]dZ[l]=dZ[l]
d a [ l − 1 ] = W [ l ] T ⋅ d Z [ l ] da^{[l-1]}=W^{[l]T}\cdot dZ^{[l]} da[l−1]=W[l]T⋅dZ[l]
多个样本的反向传播:
d Z [ l ] = d A [ l ] ∗ g ′ [ l ] ( Z [ l ] ) dZ^{[l]}=dA^{[l]}* g'^{[l]}(Z^{[l]}) dZ[l]=dA[l]∗g′[l](Z[l])
d W [ l ] = 1 m d Z [ l ] ⋅ A [ l − 1 ] T dW^{[l]}=\frac{1}{m}dZ^{[l]}\cdot {A^{[l-1]}}^{T} dW[l]=m1dZ[l]⋅A[l−1]T
d b [ l ] = 1 m n p . s u m ( d Z [ l ] , a x i s = 1 ) db^{[l]}=\frac{1}{m}np.sum(dZ^{[l]},axis=1) db[l]=m1np.sum(dZ[l],axis=1)
d A [ l ] = W [ l + 1 ] T ⋅ d Z [ l + 1 ] dA^{[l]}=W^{[l+1]T}\cdot dZ^{[l+1]} dA[l]=W[l+1]T⋅dZ[l+1]
参数即是我们在过程中想要模型学习到的信息(模型自己能计算出来的),例如 W [ l ] , b [ l ] W[l],b[l] W[l],b[l]。而超参数(hyper parameters) 即为控制参数的输出值的一些网络信息(需要人经验判断)。超参数的改变会导致最终得到的参数 W [ l ] , b [ l ] W[l],b[l] W[l],b[l] 的改变。
典型的超参数有:
当开发新应用时,预先很难准确知道超参数的最优值应该是什么。因此,通常需要尝试很多不同的值。应用深度学习领域是一个很大程度基于经验的过程。
1.为什么要随机初始化权重
如果在初始时将两个隐藏神经元的参数设置为相同的大小,那么两个隐藏神经元对输出单元的影响也是相同的,通过反向梯度下降去进行计算的时候,会得到同样的梯度大小,所以在经过多次迭代后,两个隐藏层单位仍然是对称的。无论设置多少个隐藏单元,其最终的影响都是相同的,那么多个隐藏神经元就没有了意义。
在初始化的时候,W 参数要进行随机初始化,不可以设置为 0。b 因为不存在上述问题,可以设置为 0。
以 2 个输入,2 个隐藏神经元为例:
W = np.random.rand(2,2)* 0.01
b = np.zeros((2,1))
2.初始化权重的值选择
这里将 W 的值乘以 0.01(或者其他的常数值)的原因是为了使得权重 W 初始化为较小的值,这是因为使用 sigmoid 函数或者 tanh 函数作为激活函数时,W 比较小,则 Z=WX+b 所得的值趋近于 0,梯度较大,能够提高算法的更新速度。而如果 W 设置的太大的话,得到的梯度较小,训练过程因此会变得很慢。
ReLU 和 Leaky ReLU 作为激活函数时不存在这种问题,因为在大于 0 的时候,梯度均为 1。
在面对一个具体问题的时候该确定网络结构呢?到底是不用隐层呢?还是一个隐层?两个隐层或更多?每个层的尺寸该多大?
首先,要知道当我们增加层的数量和尺寸时,网络的容量上升了。即神经元们可以合作表达许多复杂函数,所以表达函数的空间增加。例如,如果有一个在二维平面上的二分类问题。可以训练3个不同的神经网络,每个网络都只有一个隐层,但是每层的神经元数目不同,更大的神经网络可以表达更复杂的函数。数据是用不同颜色的圆点表示他们的不同类别,决策边界是由训练过的神经网络做出的。
举例来说,有20个神经元隐层的网络拟合了所有的训练数据,但是其代价是把决策边界变成了许多不相连的红绿区域。而有3个神经元的模型的表达能力只能用比较宽泛的方式去分类数据。它将数据看做是两个大块,并把个别在绿色区域内的红色点看做噪声。在实际中,这样可以在测试数据中获得更好的泛化(generalization)能力。
总结:
1、看起来如果数据不是足够复杂,则似乎小一点的网络更好,因为可以防止过拟合。然而并非如此,防止神经网络的过拟合有很多方法(L2正则化,dropout和输入噪音等),后面会详细讨论。
2、不要减少网络神经元数目的主要原因在于小网络更难使用梯度下降等局部方法来进行训练:虽然小型网络的损失函数的局部极小值更少,也比较容易收敛到这些局部极小值,但是这些最小值一般都很差,损失值很高。相反,大网络拥有更多的局部极小值,但就实际损失值来看,这些局部极小值表现更好,损失更小。因为神经网络是非凸的,就很难从数学上研究这些特性。