numpy实现神经网络系列
工程地址:https://github.com/yizt/numpy_neuron_network
基础知识
0_1-全连接层、损失函数的反向传播
0_2_1-卷积层的反向传播-单通道、无padding、步长1
0_2_2-卷积层的反向传播-多通道、无padding、步长1
0_2_3-卷积层的反向传播-多通道、无padding、步长不为1
0_2_4-卷积层的反向传播-多通道、有padding、步长不为1
0_2_5-池化层的反向传播-MaxPooling、AveragePooling、GlobalAveragePooling、GlobalMaxPooling
0_3-激活函数的反向传播-ReLU、LeakyReLU、PReLU、ELU、SELU
0_4-优化方法-SGD、AdaGrad、RMSProp、Adadelta、Adam
DNN练习
1_1_1-全连接神经网络做线性回归
1_1_2-全连接神经网络做mnist手写数字识别
CNN练习
2_1-numpy卷积层实现
2_2-numpy池化层实现
2_3-numpy-cnn-mnist手写数字识别
本文目录
本文下载地址:0_1-全连接层、损失函数的反向传播
依赖知识
a) 了解神经网络的基础知识
b) 熟悉导数的链式法则及常见函数的导数
c) 熟悉常见的优化方法,梯度下降,随机梯度下降等
d) 熟悉矩阵和向量的乘加运算
约定说明
a) 对于一个
n
层神经网络,第
i
层表示为
li, 1≤i≤n
,第
i
神经元个数为
|li|
; 注意
li
是输入层,
ln
是输出层。
b) 对于神经网络的一个输入样本
x
,其维度为
(1,|l1|)
,也就是一个行向量;对应的输出
y
也是一个行向量,维度为
(1,|ln|)
。(注:也可以将
x
和
y
表示为列向量,这里预先说明好为行向量,避免后面有歧义)
c) 设神经网络中第i层的输出为
zi
,(
zi
都是行向量)则
x=z1,y=zn
; 第
i
层的权重和偏置分别为
Wi,bi
;则对于全连接层
zi+1=ziWi+bi
; 其中
Wi
和
bi
的维度分别为为
(|li|,|li+1|),(1,|li+1|)
d) 定义损失函数为
L(y,y∗)
;其中
y∗
为样本的真实
y
值
误差反向
a) 记损失函数L关于第
i
层神经元的输出
zi
的偏导为
δi=∂L∂zi (1)
b) 首先我们来看看损失函数L在最后一层参数上的偏导;也就是
∂L∂Wn−1
和
∂L∂bn−1
∂L∂Wn−1i,j =∂Lznj∗∂znj∂Wn−1i,j (2) //Wn−1i,j是第n−1层的第i个神经元和第n层的第j个神经元的连接,所以只有znj的误差经过Wn−1i,j反向传播=δnj∗∂(∑|ln−1|k=1zn−1kWn−1k,j+bn−1j)∂Wn−1i,j (3) //znj是zn−1这个行向量与权重矩阵Wn−1的第j列向量的乘积,加上偏置bn−1j=δnj∗zn−1i (4)
对等式(4)一般化的向量表示为:
∂L∂Wn−1=(zn−1)Tδnj(5)
同理可得:
∂L∂bn−1=δn(6)
c) 更一般的损失函数L关于第
l
层(这里没有用索引
i
,避免跟等式1~4中的索引名相同,引起理解障碍)的参数上的偏导,也就是
∂L∂Wl
和
∂L∂bl
∂L∂Wl=∂L∂zl+1∗∂zl+1∂Wl (7)=(zl)Tδl+1 (8)
同理可得:
∂L∂bl=δl+1(9)
d) 现在我们来看a)中定义的损失函数L关于第
l
层输出的偏导
δl=∂L∂zl
δli=∂L∂zli =∂L∂zl+1∗∂zl+1∂zli (10) //导数的链式法则=∂L∂zl+1∗∂(zlWl+bl)∂zli (11) //zl的定义=∑j=1|ll+1|∂L∂zl+1j∗∂(∑|ll|k=1zlkWlk,j+blj)∂zli (12) //第l+1层的每个节点都有梯度专递到l层的第i个节点=∑j=1|ll+1|δl+1j∗Wli,j (13) //只有k=i时有梯度=δl+1((Wl)T)i (14) //可以表示为l+1层梯度的行向量与权重Wl的转置的第i个列向量的乘积(1)(2)(3)(4)(5)(6)
一般化的表示如下:
δl=∂L∂zl=δl+1(Wl)T (15)
结论
以上的证明就是为了说明下面的结论,所以请牢记以下的结论,后续自己写神经网络的反向传播都会用到以下结论
a) 根据公式15,损失函数L关于第
l
层神经元的偏导,就是第
l+1
层的偏导乘上第l层权重矩阵的转置。我们将公式(15)递归一下,
δl=δl+1(Wl)T=δl+2(Wl+1)T(Wl)T=δn(Wn−1)T(Wn−2)T...(Wl)T (16)
也就是说,只要求得损失函数L关于最后一层(n)的偏导
δn
,其它任意层的偏导,直接用最后一层的偏导逐层乘上权重的转置即可。很简单,很对称,有木有?
b) 根据公式(8) ,损失函数L关于第
l
层权重
Wl
的偏导为,第
l
层输出的转置乘第
l+1
层的偏导
∂L∂Wl=(zl)Tδl+1 (8)
c) 根据公式(9) ,损失函数L关于第
l
层偏置
bl
的偏导,就是第
l+1
层的偏导:
∂L∂bl=δl+1 (9)
由以上可知对任意的全连接层,我们只需要只到它后一层的偏导,就可以求得当前层参数(权重、偏置)的偏导; 就可以使用梯度下降算法更新参数了
w=w−η∗∂L∂w //η为学习率(17)
b=b−η∗∂L∂b(18)
根据公式(16), 损失函数L关于任何一层的偏导,只需要求导损失函数关于最后一层的偏导
δn
即可。
δn
与损失函数的定义有关,下一节介绍常用损失函数的偏导计算。
常用损失函数
以下说明损失函数的偏导的计算
均方差损失
对于单个样本
(x,y∗)
,定义如下:
L(y,y∗)=12(y−y∗)2(19)
其中
y
是神经网络最后一层的输出
y=zn
,就是预测值
∂L∂yi=∂(12(yi−y∗i)2)∂yi=(yi−y∗i)∗∂(yi−y∗i)∂yi=(yi−y∗i) (20)(7)(8)(9)
更一般的表示为
∂L∂y=y−y∗
; 也就是
δn=∂L∂y=y−y∗=zn−y∗(21)
即使用均方误差情况下,损失函数L关于网络最后一层的导数就是预测值减实际值
交叉熵损失
交叉熵用于度量两个概率分布的差异;一般使用交叉熵损失前,会对网络输出做softmax变换进行概率归一化;所以我们这里介绍的交叉熵损失是带softmax变换的交叉熵。
softmax变换定义如下:
ai=eyi/∑keyk(22)
交叉熵损失定义如下:
L(y,y∗)=−∑iy∗ilogai(23)
a) 我们先来求
ai
关于
yj
的偏导
∂ai∂yj=∂(eyi/∑keyk)∂yj=∂eyi∂yj∗1∑keyk+eyi∗−1(∑keyk)2∗∂(∑keyk)∂yj=∂eyi∂yj∗1∑keyk−eyi(∑keyk)2∗eyj=⎧⎩⎨⎪⎪eyj∑keyk−(eyj)2(∑keyk)2−eyieyj(∑keyk)2i=ji≠ j={ai(1−ai)−aiaji=ji≠ j(24)
b) 然后我们来求L关于
yj
的偏导
∂L∂yj=−∑i∂(y∗ilogai)∂ai∗∂ai∂yj=−∑iy∗iai∗∂ai∂yj=−y∗jaj∗aj(1−aj)+∑i≠ jy∗iai∗aiaj=−y∗j(1−aj)+∑i≠ jy∗iaj=−y∗j+∑iy∗iaj=aj−y∗j//注意这里i是变量,j是固定的//所有真实标签的概率之和为1(10)(11)(12)(13)(14)(15)
更一般的表示为 :
∂L∂y=a−y∗(25)
所以使用带softmax变换的交叉熵损失函数,损失函数L关于网络最后一层的导数就是预测值经softmax变换后的值减去真实值。(是不是跟均方差损失函数很相似,注意还是有差异的噢)