1 引言
如图所示,我们建立了一个四层的神经网络,相对于前文所描述的神经网络,他是一个深层神经网络,接下来,我们将推导这个神经网络建立的过程。
深层神经网络
2 符号定义
上图是一个四层的神经网络,有三个隐藏层。我们可以看到,第一层(即左边数过去第二层,因为输入层是第0 层)有 5 5 5个神经元数目,第二层 5 5 5 个,第三层 3 3 3 个。
我们 L L L表示层数,上图: 𝐿 = 4 𝐿 = 4 L=4,输入层的索引为 “ 0 ” “0” “0”,第一个隐藏层 n [ 1 ] = 5 n^{[1]} = 5 n[1]=5 ,表示有 5 5 5个隐藏神经元,同理 n [ 2 ] = 5 n^{[2]} = 5 n[2]=5, n [ 3 ] = 3 n^{[3]} = 3 n[3]=3, n [ 4 ] = n [ L ] = 1 n^{[4]} = n^{[L]} = 1 n[4]=n[L]=1(输出单元为 1)。而输入层, 𝑛 [ 0 ] = 3 𝑛^{[0]} = 3 n[0]=3。
在不同层所拥有的神经元的数目,对于每层都用 𝑎 [ 𝑙 ] 𝑎^{[𝑙]} a[l]来记作 l l l层激活后结果,我们会在后面看到在正向传播时,你会计算出 𝑎 [ 1 ] 𝑎^{[1]} a[1]。
通过用激活函数 g g g计算 z [ l ] z^{[l]} z[l],激活函数也被索引为层数 l l l,然后我们用 w [ l ] w^{[l]} w[l]来记作在 l l l层计算 z [ l ] z^{[l]} z[l]值的权重。类似的, z [ l ] z^{[l]} z[l]里的方程 b [ l ] b^{[l]} b[l]也一样。
最后总结下符号约定:
输入的特征记作 x x x,但是 x x x同样也是 0 层的激活函数,所以 x = a [ 0 ] x = a^{[0]} x=a[0]。
最后一层的激活函数,所以 𝑎 [ 𝐿 ] 𝑎^{[𝐿]} a[L]是等于这个神经网络所预测的输出结果。
3 传播过程
3.1 前向传播
首先明确目的,我们进行前向传播是为了得到样本在当前神经网络下计算出的预测值。
第一层需要计算 z [ 1 ] = w [ 1 ] x + b [ 1 ] , a [ 1 ] = g [ 1 ] ( z [ 1 ] ) z^{[1]}= w^{[1]}x + b^{[1]},a^{[1]} = g^{[1]}(z^{[1]}) z[1]=w[1]x+b[1],a[1]=g[1](z[1])( x x x可以看做 a [ 0 ] a^{[0]} a[0]);
第二层需要计算 z [ 2 ] = w [ 2 ] x + b [ 2 ] , a [ 2 ] = g [ 2 ] ( z [ 2 ] ) z^{[2]}= w^{[2]}x + b^{[2]},a^{[2]} = g^{[2]}(z^{[2]}) z[2]=w[2]x+b[2],a[2]=g[2](z[2]);
以此类推,第四层为 z [ 4 ] = w [ 4 ] x + b [ 4 ] , a [ 4 ] = g [ 4 ] ( z [ 4 ] ) z^{[4]}= w^{[4]}x + b^{[4]},a^{[4]} = g^{[4]}(z^{[4]}) z[4]=w[4]x+b[4],a[4]=g[4](z[4]);
前向传播可以归纳为多次迭代 z [ l ] = w [ l ] x [ l − 1 ] + b [ l ] , a [ l ] = g [ l ] ( z [ l ] ) z^{[l]}= w^{[l]}x^{[l-1]} + b^{[l]},a^{[l]} = g^{[l]}(z^{[l]}) z[l]=w[l]x[l−1]+b[l],a[l]=g[l](z[l])。
向量化实现过程可以写成: Z [ l ] = W [ l ] A [ l − 1 ] + b [ l ] , A [ l ] = g [ l ] ( Z [ l ] ) ( 𝐴 [ 0 ] = 𝑋 ) Z^{[l]}= W^{[l]}A^{[l-1]} + b^{[l]},A^{[l]} = g^{[l]} (Z^{[l]})(𝐴^{[0]} = 𝑋) Z[l]=W[l]A[l−1]+b[l],A[l]=g[l](Z[l])(A[0]=X)
从输入值开始, 𝐴 [ 0 ] = 𝑋 𝐴^{[0]} = 𝑋 A[0]=X,历经前向传播,我们得到了输出值(预测值) 𝐴 [ L ] 𝐴^{[L]} A[L]。
3.2 反向传播
反向传播是为了什么,是为了迭代优化神经元中的矩阵值,我们选择了梯度下降法优化,而使用这个方法需要求得一些导数。
回想一下Logistic回归的反向传播,我们先利用损失函数 L L L求 a a a的导数 d a da da,接着利用 d a da da求出了 d z dz dz,又利用 d z dz dz求出了 d w dw dw与 d b db db。
而对于深层神经网络,我们仅仅求出 d w [ l ] dw^{[l]} dw[l]与 d b [ l ] db^{[l]} db[l]是无法将传播继续推进求出 d w [ l − 1 ] dw^{[l-1]} dw[l−1]与 d b [ l − 1 ] db^{[l-1]} db[l−1]的,因为前一层的 d w [ l − 1 ] dw^{[l-1]} dw[l−1]与 d b [ l − 1 ] db^{[l-1]} db[l−1]需要先求 d z [ l − 1 ] dz^{[l-1]} dz[l−1],而 d z [ l − 1 ] dz^{[l-1]} dz[l−1]的求解是需要 d a [ l − 1 ] da^{[l-1]} da[l−1]的,因此在上一层,我们还需要求出 d a [ l − 1 ] da^{[l-1]} da[l−1]。
按照Logistic回归的计算方法,我们知道 d z = a − y dz=a-y dz=a−y,在深层神经网络的反向传播中,输出层我们这样计算无妨,但是继续往下推进呢?我们发现 a a a与 y y y的值都变得难以确定,或者说把 a a a也放进了迭代中。
原因出现在
d
z
dz
dz公式的推导中,
dz公式的推导
我们选择的激活函数为 s i g o i d sigoid sigoid函数,即 a = 1 1 + e − z a = \cfrac{1}{1+e^{-z}} a=1+e−z1,对 z z z求导 d z d z = e − z ( 1 + e − z ) 2 \cfrac{dz}{dz} = \cfrac{e^{-z}}{(1+e^{-z})^{2}} dzdz=(1+e−z)2e−z,我们用 e − z = 1 a − 1 e^{-z} = \cfrac{1}{a-1} e−z=a−11代替,最后得到了 d a d z = a × ( 1 − a ) \cfrac{da}{dz} = a\times(1-a) dzda=a×(1−a)。避免了显式的使用 e e e,但是激活函数的选择要根据输出值来确定,且每一个神经元的激活函数都可以有各自的选择,并不一定都要用 s i g m o i d sigmoid sigmoid函数,因此,在深层神经网络中,我们去掉激活函数求导的显式过程,以 g ’ ( z ) {g}’(z) g’(z)代替,这样,我们就无需在计算时纠结 y y y值选什么, a a a值选什么了。这也是我们缓存 z z z值的原因,方便运算。
反向传播,我们输入为 d a [ l ] da^{[l]} da[l],输出为 d a [ l − 1 ] , d w [ l ] , d b [ l ] da^{[l-1]},dw^{[l]},db^{[l]} da[l−1],dw[l],db[l]。
所以反向传播的步骤可以写成:
(1) 𝑑 𝑧 [ 𝑙 ] = 𝑑 𝑎 [ 𝑙 ] × 𝑔 [ 𝑙 ] ’ ( 𝑧 [ 𝑙 ] ) 𝑑𝑧^{[𝑙]} = 𝑑𝑎^{[𝑙]} \times {𝑔^{[𝑙]}}’(𝑧^{[𝑙]}) dz[l]=da[l]×g[l]’(z[l])
( 2) 𝑑 𝑤 [ 𝑙 ] = 𝑑 𝑧 [ 𝑙 ] ⋅ 𝑎 [ 𝑙 − 1 ] 𝑑𝑤^{[𝑙]} = 𝑑𝑧^{[𝑙]} ⋅ 𝑎^{[𝑙-1]} dw[l]=dz[l]⋅a[l−1]
( 3) 𝑑 𝑏 [ 𝑙 ] = 𝑑 𝑧 [ 𝑙 ] 𝑑𝑏^{[𝑙]} = 𝑑𝑧^{[𝑙]} db[l]=dz[l]
( 4) 𝑑 𝑎 [ 𝑙 − 1 ] = 𝑤 [ 𝑙 ] 𝑇 𝑑 𝑧 [ 𝑙 ] 𝑑𝑎^{[𝑙-1]} = 𝑤^{[𝑙]𝑇} 𝑑𝑧^{[𝑙]} da[l−1]=w[l]Tdz[l]
( 5) 𝑑 𝑧 [ 𝑙 ] = 𝑤 [ 𝑙 + 1 ] 𝑇 𝑑 𝑧 [ 𝑙 + 1 ] 𝑔 [ 𝑙 ] ’ ( 𝑧 [ 𝑙 ] ) 𝑑𝑧^{[𝑙]} = 𝑤^{[𝑙+1]𝑇}𝑑𝑧^{[𝑙+1]} 𝑔^{[𝑙]}’(𝑧^{[𝑙]}) dz[l]=w[l+1]Tdz[l+1]g[l]’(z[l])
式子( 5)由式子( 4)带入式子( 1)得到,前四个式子就可实现反向函数。
向量化实现过程可以写成:
(6) 𝑑 𝑍 [ 𝑙 ] = 𝑑 𝐴 [ 𝑙 ] 𝑔 [ 𝑙 ] ’ ( 𝑍 [ 𝑙 ] ) 𝑑𝑍^{[𝑙]} = 𝑑𝐴^{[𝑙]}𝑔^{[𝑙]}’(𝑍^{[𝑙]}) dZ[l]=dA[l]g[l]’(Z[l])
( 7) 𝑑 𝑊 [ 𝑙 ] = 1 m 𝑑 𝑍 [ 𝑙 ] ⋅ 𝐴 [ 𝑙 − 1 ] 𝑇 𝑑𝑊^{[𝑙]} = \cfrac{1}{m}𝑑𝑍^{[𝑙]} ⋅ 𝐴^{[𝑙-1]𝑇} dW[l]=m1dZ[l]⋅A[l−1]T
( 8) 𝑑 𝑏 [ 𝑙 ] = 1 m 𝑛 𝑝 . 𝑠 𝑢 𝑚 ( 𝑑 𝑧 [ 𝑙 ] , 𝑎 𝑥 𝑖 𝑠 = 1 , 𝑘 𝑒 𝑒 𝑝 𝑑 𝑖 𝑚 𝑠 = 𝑇 𝑟 𝑢 𝑒 ) 𝑑𝑏^{[𝑙]} = \cfrac{1}{m}𝑛𝑝. 𝑠𝑢𝑚(𝑑𝑧^{[𝑙]}, 𝑎𝑥𝑖𝑠 = 1, 𝑘𝑒𝑒𝑝𝑑𝑖𝑚𝑠 = 𝑇𝑟𝑢𝑒) db[l]=m1np.sum(dz[l],axis=1,keepdims=True)
( 9) 𝑑 𝐴 [ 𝑙 − 1 ] = 𝑊 [ 𝑙 ] 𝑇 d 𝑍 [ 𝑙 ] 𝑑𝐴^{[𝑙-1]}= 𝑊^{[𝑙]𝑇}d𝑍^{[𝑙]} dA[l−1]=W[l]TdZ[l]
完成这些导数的求值,最后就可以进行梯度下降,完成一次迭代了。
4 为什么要使用深层神经网络
如前文的公司开会情景,如果公司很大呢,这个老板只是一个分公司老板呢?他还需要继续往上级汇报工作,上级还有上级,一层套一层,因此我们发现,对于现实生活实际应用来说,往往一个浅层神经网络是很难把事情描述清楚的,因此需要深层神经网络。
那如果我们坚持使用浅层神经网络来解决呢?我们知道,一个神经元理论上学习能力是无限的,只需要给他足够的学习空间即可,但实际上,学习能力是有限的,输出层只有一个神经元,隐藏层的神经元相对较多,当隐藏层神经元多到一定程度,输出层就没用这么大的学习能力了,无法汇总所有隐藏层神经元的激活值,就会造成隐藏层神经元资源的溢出或者说浪费。
我们很容易就想到了当前职场普遍存在的扁平化管理制度,管理者通过末位淘汰制度,使得下属人数产生微妙的平衡,不需要的就踢出队伍,因此各个下属为了留在这个神经网络中,不停学习,优化自己的 w w w。结合了这个例子,深层神经网络想明白了,但是一想到以后要打工,也要进入这个职场神经网络中,总觉得有一丝淡淡的忧伤。
5 总结与思考
至此,神经网络已有理解,但是有一些问题依然存在,比如梯度下降这个迭代过程要经过几次?学习率应当如何控制?深层神经网络层数如何选择?这些都是除了参数 w 、 b w、b w、b之外的超参数,一个很自然的想法就是,不断尝试,积累经验直至有直觉。