以mnist手写数字图片分类为例,识别图片上的数字。图片大小28*28*1 , 数字0-9之间。
输入:
将每一个图片用一个一维数组来表示,即长度为28*28*1的一维数组。
有m条数据,每一行表示一张图片,这样就组成了一个矩阵。
本文是以一行为一个样本,与tensorflow官方例子的表示法一致。(与吴恩达老师的表示法不一致,吴老师是用一列表示一个样本)
X=⎡⎣⎢⎢⎢⎢x1,1x2,1...xm,1x1,2.....................x1,n......xm,n⎤⎦⎥⎥⎥⎥ X = [ x 1 , 1 x 1 , 2 . . . x 1 , n x 2 , 1 . . . . . . . . . . . . . . . . . . . . . x m , 1 . . . . . . x m , n ]
DNN
- 有L层网络
- 每一层的激活函数可以是RELU
- 第L层(最后一层)的激活函数是SOFTMAX
- 第L层(最后一层)的神经元数为分类的数目,10
- 采用交叉熵损失函数
第 l l 层网络:
- Ll L l 代表第 l l 层网络
- nl n l 代表第 l l 层网络输出的特征值数目(神经元数目)。
- Wl W l 代表该层的权重矩阵。 Wl W l .shape = [ nl−1 n l − 1 , nl n l ]
- Bl B l 代表盖层的bias矩阵。 Bl B l .shape=[1, nl n l ]
- Zl Z l 代表线性输出(激活函数前)。 Zl Z l .shape=[m, nl n l ]
- Al A l 代表输出(激活函数后)。 Al A l .shape=[m, nl n l ]
数学符号
后续式子中会用到很多通用的符号:
- 大写字母表示矩阵,如X,Y
- 小写字母表示矩阵中的元素,如 ai,j a i , j
- i i 表示第 i i 个样本
- j j 表示该样本的第 j j 个特征值。一般用来表示当前层的第j个特征。
- k k 表示该样本的第 k k 个特征值,与 j j 类似。一般用来表示前一层的第k个特征。
前向公式推导:
线性部分
将输入X看做是第0层网络的输出。即 A0 A 0 = X。
第 l−1 l − 1 层的输出 Al−1 A l − 1 ,经过第 l l 层网络 Ll L l ,得到了输出 Al A l 。
∑k=1nl−1(al−1i,k∗wlk,j)+bj=zli,j ∑ k = 1 n l − 1 ( a i , k l − 1 ∗ w k , j l ) + b j = z i , j l
⎡⎣⎢⎢⎢al−11,1al−12,1...al−11,2...............⎤⎦⎥⎥⎥∙⎡⎣⎢⎢⎢wl1,1wl2,1...wl1,2...............⎤⎦⎥⎥⎥+[bl1bl2...]=[∑nl−1k=1(al−1i,k∗wlk,j)+bj.........]=[zli,j.........] [ a 1 , 1 l − 1 a 1 , 2 l − 1 . . . a 2 , 1 l − 1 . . . . . . . . . . . . . . . ] ∙ [ w 1 , 1 l w 1 , 2 l . . . w 2 , 1 l . . . . . . . . . . . . . . . ] + [ b 1 l b 2 l . . . ] = [ ∑ k = 1 n l − 1 ( a i , k l − 1 ∗ w k , j l ) + b j . . . . . . . . . ] = [ z i , j l . . . . . . . . . ]
Al−1∙Wl=Zl(1) (1) A l − 1 ∙ W l = Z l
公式中
∙ ∙ 表示矩阵点积。
[acbd]∙[egfh]=[ae+bgce+dgaf+bhcf+dh] [ a b c d ] ∙ [ e f g h ] = [ a e + b g a f + b h c e + d g c f + d h ]
上式中各矩阵的shape:
- Al−1.Shape=[m,nl−1] A l − 1 . S h a p e = [ m , n l − 1 ]
- Wl.Shape=[nl−1,nl] W l . S h a p e = [ n l − 1 , n l ]
- Al−1.Shape=[m,nl] A l − 1 . S h a p e = [ m , n l ]
al−1i,j a i , j l − 1 符号说明:
- 第 l−1 l − 1 层网络的输出,也就是第 l l 层的输入。
- 第 i i 个样本
- 第 j j 个特征
wlk,j w k , j l 符号说明:
- 第 l l 层网络的Weight
- 与前一层网络的第 k k 个特征值相乘
- 汇总于当前网络的第 j j 个神经元
blj b j l 符号说明:
- 第 l l 层网络的bias
- 第 j j 神经元的bias
激活函数
σ(Zl)=Al(2) (2) σ ( Z l ) = A l
最后一层的激活函数采用SOFTMAX。其他的层激活函数用RELU
RELU
Al=MAX(Zl,0)(3) (3) A l = M A X ( Z l , 0 )
SOFTMAX
ali,j=ezj∑nlk=1ezk(4) (4) a i , j l = e z j ∑ k = 1 n l e z k
Al=[ali,j.........] A l = [ a i , j l . . . . . . . . . ]
神经网络的最后一层输出 AL A L
AL.shape=[m,nl] A L . s h a p e = [ m , n l ]
损失函数
采用交叉熵损失函数,公式如下
J=−1m∑i=1m∑j=1nl(yi,jlnaLi,j)(5) (5) J = − 1 m ∑ i = 1 m ∑ j = 1 n l ( y i , j l n a i , j L )
学习的任务就是通过调整W,B的值不断减少J。
bp反向传播算法的思路是从梯度的反方向调整参数,这样J下降最快。
所以,后面的任务就是计算梯度。
后向公式推导
根据导数的链式法则,可以一层一层的推导。
对A求导
∂J∂aLi,j=−yi,jaLi,j(6) (6) ∂ J ∂ a i , j L = − y i , j a i , j L
∂J∂AL=[−yi,jaLi,j.........] ∂ J ∂ A L = [ − y i , j a i , j L . . . . . . . . . ]
我们用
dAL d A L 来表示
∂J∂AL ∂ J ∂ A L ,即
dAL=[−yi,jaLi,j.........](7) (7) d A L = [ − y i , j a i , j L . . . . . . . . . ]
已知 dAl d A l ,求 dZl d Z l
这里需要根据激活函数的不同,区分对待。
激活函数是SOFTMAX
SOFTMAX公式如下
aj=ezj∑nlo=1ezo a j = e z j ∑ o = 1 n l e z o
zj z j 参与到了每一个a的计算,所以:
∂J∂zj=∑p=1nl(∂J∂ap∂ap∂zj)(8) (8) ∂ J ∂ z j = ∑ p = 1 n l ( ∂ J ∂ a p ∂ a p ∂ z j )
∂J∂ap ∂ J ∂ a p 上一步已经求出来了,接下来要求 ∂ap∂zj ∂ a p ∂ z j 。这里要分 p=j p = j ,和 p≠j p ≠ j 两种情况。
p=j p = j
∂aj∂zj=ezj∗∑ezo−ezj∗ezj(∑ezo)2=ezj∑ezo∗(1−ezj∑ezk)=aj∗(1−aj) ∂ a j ∂ z j = e z j ∗ ∑ e z o − e z j ∗ e z j ( ∑ e z o ) 2 = e z j ∑ e z o ∗ ( 1 − e z j ∑ e z k ) = a j ∗ ( 1 − a j )
p≠j p ≠ j
∂ap∂zj=−ezp∗1(∑ezo)2∗ezj=−ap∗aj ∂ a p ∂ z j = − e z p ∗ 1 ( ∑ e z o ) 2 ∗ e z j = − a p ∗ a j
合起来,即可得到
∂J∂zj=∑p=1nl(∂J∂ap∂ap∂zj)=∑p=1nl(dap∂ap∂zj)=aj(1−aj)daj+∑p≠j(−ap∗aj∗dap)=aj∗daj−∑p=1nl(apajdap)(9) (9) ∂ J ∂ z j = ∑ p = 1 n l ( ∂ J ∂ a p ∂ a p ∂ z j ) = ∑ p = 1 n l ( d a p ∂ a p ∂ z j ) = a j ( 1 − a j ) d a j + ∑ p ≠ j ( − a p ∗ a j ∗ d a p ) = a j ∗ d a j − ∑ p = 1 n l ( a p a j d a p )
矩阵化:
dZl=Al×dAl−Al×SUM(Al×dAl,axis=1)(10) (10) d Z l = A l × d A l − A l × S U M ( A l × d A l , a x i s = 1 )
公式说明:
- × × 表示矩阵对应元素相乘(非点积)
- SUM(Al×dAl,axis=1) S U M ( A l × d A l , a x i s = 1 ) 表示矩阵求和, [m,nl] [ m , n l ] 求和后变为 [m,1] [ m , 1 ]
- 这里用到了numpy广播的概念。 [acbd]×[ef]=[aecfbedf] [ a b c d ] × [ e f ] = [ a e b e c f d f ]
激活函数是RELU
RELU公式:
a=max(z,0) a = m a x ( z , 0 )
导数公式:
dadz=1(z>0)dadz=0(z<=0) d a d z = 1 ( z > 0 ) d a d z = 0 ( z <= 0 )
dAldZl=σ′(Zl) d A l d Z l = σ ′ ( Z l )
dZl=σ′(Zl)×dAl(11) (11) d Z l = σ ′ ( Z l ) × d A l
线性部分求导
线性部分公式如下:
∑k=1nl−1(al−1k∗wk,j)+blj=zlj ∑ k = 1 n l − 1 ( a k l − 1 ∗ w k , j ) + b j l = z j l
已知dZ^l,求dB^l
∂zlj∂blj=1 ∂ z j l ∂ b j l = 1
所以:
dBl=dZl d B l = d Z l
已知dZ^l,求dW^l
∂zlj∂wlk,j=al−1k(k=1...nl−1,j=1...nl)dwlk,j=dzj∗al−1k ∂ z j l ∂ w k , j l = a k l − 1 ( k = 1 . . . n l − 1 , j = 1 . . . n l ) d w k , j l = d z j ∗ a k l − 1
对于单个样本, ∂Zl∂Wl.shape=[nl−1,nl] ∂ Z l ∂ W l . s h a p e = [ n l − 1 , n l ]
对于m个样本, ∂Zl∂Wl.shape=[m,nl−1,nl] ∂ Z l ∂ W l . s h a p e = [ m , n l − 1 , n l ]
dWl=Al−1.reshape(m,nl−1,1)×dZl.reshape(m,1,nl) d W l = A l − 1 . r e s h a p e ( m , n l − 1 , 1 ) × d Z l . r e s h a p e ( m , 1 , n l )
公式说明:
- reshape是矩阵维度重组,参考 numpy.reshape
- 矩阵乘法应用了numpy的广播的概念,即
[ab]×[cd]=[acadbcbd] [ a b ] × [ c d ] = [ a c b c a d b d ]
已知 dZl d Z l ,求 dAl−1 d A l − 1
∂zlj∂al−1k=wlk,j(k=1...nl−1,j=1...nl)dal−1k=∑j=1nldzlj∗∂zlj∂al−1k=∑j=1nldzlj∗wlk,j ∂ z j l ∂ a k l − 1 = w k , j l ( k = 1 . . . n l − 1 , j = 1 . . . n l ) d a k l − 1 = ∑ j = 1 n l d z j l ∗ ∂ z j l ∂ a k l − 1 = ∑ j = 1 n l d z j l ∗ w k , j l
矩阵化:
dAl−1=dZl∙(Wl)T d A l − 1 = d Z l ∙ ( W l ) T
这里已经求得了
dAl−1 d A l − 1 ,根据之前的公式,可以继续一层一层向前传播,最终求得所有的导数。
学习过程(调整参数)
公式如下:
Wl=Wl−η∗dWlBl=Bl−η∗dBl W l = W l − η ∗ d W l B l = B l − η ∗ d B l
但是之前求得的dW,dB与W,B的尺寸不一致
Wl.shape=[nl−1,nl]dWl.shape=[m,nl−1,nl]Bl.shape=[1,nl]dBl.shape=[m,nl] W l . s h a p e = [ n l − 1 , n l ] d W l . s h a p e = [ m , n l − 1 , n l ] B l . s h a p e = [ 1 , n l ] d B l . s h a p e = [ m , n l ]
这是因为有m个样本,即m组导数,我们需要先求导数的平均值。
dWl=MEAN(dWl,axis=0)dBl=MEAN(dBl,axis=0) d W l = M E A N ( d W l , a x i s = 0 ) d B l = M E A N ( d B l , a x i s = 0 )
交叉熵与SOFTMAX 化简
TensorFlow中有一个函数 tf.softmax_cross_entropy_with_logits 。这个函数就是softmax+交叉熵。
为什么要提供这一个函数呢?这是因为反向传播时,softmax与交叉熵一起可以化简。
将前面的公式拿下来:
daj=−yjaj∂J∂zj=aj∗daj−∑p=1nl(apajdap) d a j = − y j a j ∂ J ∂ z j = a j ∗ d a j − ∑ p = 1 n l ( a p a j d a p )
两个公式合起来:
dzj=aj−yj d z j = a j − y j
矩阵化:
dZL=AL−Y d Z L = A L − Y
可以看到公式化简了很多,最重要的是,
没有分母,避免了除0问题。
参考:
导数链式法则
RELU求导0处如何处理?