- 代价函数
- 反向传播算法
- 理解反向传播
- 使用注意:展开参数
- 梯度检测 Gradient Checking
- 随机初始化 random initialization
- 组合在一起
- Tensorflow 实现
代价函数本节学习目标:介绍一个学习算法,在给定训练集时,它能为神经网络拟合参数。
本部分将重点讲解神经网络在分类问题中的应用。
假设有一个如下图左上角所示的神经网络,以及右上角所示的训练集。其中,训练集有m组训练样本
(
x
(
i
)
,
y
(
i
)
)
,
i
=
1
,
2
,
3
,
…
,
m
(x_{(i)},y_{(i)}),i=1,2,3,…,m
(x(i),y(i)),i=1,2,3,…,m。用L表示神经网络总层数,**
s
l
s_l
sl**表示第l层的单元数(即神经元的个数,不包括偏差单元)。
给定两个分类问题。
- 二分类问题(左图)。k表示输出层的单元数目,为1。
- 多分类问题(右图)。有k个类别,输出层单元数目为k。输出结果为k维。(注意: 多分类问题中,只有类别大于等于3时,才需要使用一对多的方法。)
下面定义上述两类问题的代价函数。
神经网络使用的代价函数的是逻辑回归代价函数的一般形式,不同的是神经网络拥有多个逻辑回归输出单元,神经网络代价函数是k个逻辑回归代价函数“集合”。
h θ ( x ) h_theta(x) hθ(x)为k维向量, ( h θ ( x ) ) i {(h_theta(x))}_i (hθ(x))i表示神经网络第k个输出单元的结果。
神经网络的代价函数如下图,类似于逻辑回归,神经网络代价函数的正则项部分也需要除去偏差值的项目(即除去i为0的参数)(按照一般约定,不加入此部分,但其实加或不加影响不大,只不过习惯上不加)。
代价函数
学习目标:学习让代价函数最小化的算法,即反向传播算法。
神经网络的代价函数如下图。我们需要做的是找到使得
J
(
θ
)
J(theta)
J(θ)取最小值的
θ
i
j
(
l
)
theta_{ij}^{(l)}
θij(l),因此本部分主要关注点在于如何求下图的偏导项。
假设训练集只有一个样本,即(x,y)。下面实现了通过前向传播的向量化,计算每一层的激活值。
然后,为了计算导数项,我们采用反向传播(Backpropagation)算法。从直观上来说,反向传播即:对于每一个节点,我们计算它的
δ
j
(
l
)
delta_j^{(l)}
δj(l)(第l层的第j个结点的误差)。
在某种程度上,
δ
j
(
l
)
delta_j^{(l)}
δj(l)捕捉了在这个神经节点激活项
a
j
(
l
)
a_j^{(l)}
aj(l)的误差,所以我们可能希望这个节点的激活值稍微不一样。具体来说,以下图的四层神经网络为例,
δ
j
(
4
)
=
a
j
(
4
)
−
y
j
delta_j^{(4)}=a_j^{(4)}-y_j
δj(4)=aj(4)−yj,因此
δ
j
(
4
)
delta_j^{(4)}
δj(4)是假设的输出值与训练集
y
y
y值之差,
y
j
y_j
yj也就是训练集中
y
y
y向量的第j个元素值。
如果把
δ
、
a
、
y
delta、a、y
δ、a、y看成向量,有
δ
(
4
)
=
a
(
4
)
−
y
delta^{(4)}=a^{(4)}-y
δ(4)=a(4)−y。其中向量维数为输出单元的数目。
计算完第4层的误差项,接下来要做的即:计算网络前几项的误差项
sigmoid函数[
g
(
x
)
=
1
1
+
e
−
x
g(x)=frac 1{1+e^{-x}}
g(x)=1+e−x1]的导数有个性质,
g
′
(
x
)
=
g
(
x
)
∗
(
1
−
g
(
x
)
)
g'(x)=g(x)*(1-g(x))
g′(x)=g(x)∗(1−g(x))。
计算不太严谨的话(忽略
λ
lambda
λ为0的情况),可以得到下式。(待解决)
总之,我们到底如何通过实现方向传播算法,来计算这些参数的偏导数呢?
下面展示一般情况–训练集特别大,拥有m个样本。
利用方向传播算法计算神经网络参数步骤如下图,它实现了所有
θ
theta
θ的更新。
最后一步中,使用
Δ
i
j
(
l
)
Delta_{ij}^{(l)}
Δij(l)累积偏导数项
a
j
(
l
)
δ
i
j
(
l
)
a_j^{(l)}delta_{ij}^{(l)}
aj(l)δij(l)。
然后跳出循环,计算
D
i
j
(
l
)
D_{ij}^{(l)}
Dij(l)。
通过一系列复杂的计算,可以得到代价函数的偏导
∂
J
(
θ
)
∂
θ
i
j
(
l
)
=
D
i
j
(
l
)
frac {partial J(theta)}{partial{theta_{ij}^{(l)}}} = D_{ij}^{(l)}
∂θij(l)∂J(θ)=Dij(l)。
首先,我们进一步研究前向传播的过程。下面展示一个四层神经网络。
前向传播的过程如下图所示。反向传播与之类似,只不过传播反向不同。
下面展示代价函数。本处输出单元只有一个,因此
y
(
i
)
y^{(i)}
y(i)为实数(而不是向量)。此外,这里忽略正则化项,
λ
lambda
λ为0。
可以发现,此时代价函数中蓝线部分,对应第i个训练样本
(
x
(
i
)
,
y
(
i
)
)
(x^{(i)},y^{(i)})
(x(i),y(i))。于是有cost(i)等式,它扮演的一个类似于方差的角色。这个式子很复杂,因此可以把cost(i)近似看成神经网络的输出值与实际值之间的方差,也就是神经网络中输出值与实际值的接近程度。实际中,逻辑回归算法会把代价函数用cost(i)这种复杂的函数代替;为了方便理解,我们可以把这个式子看做某种方差函数。
现在再来看看反向传播的过程。
- 从直观来看,反向传播就是在计算一系列 δ j ( l ) delta_j^{(l)} δj(l)值。我们可以把它看做在第l层中,第 j j j个单元得到的激活项"误差"。
- 正式来说, δ j ( l ) delta_j^{(l)} δj(l)是代价函数 c o s t ( i ) cost(i) cost(i)关于 z j ( l ) z_j^{(l)} zj(l)的偏导数,也就是计算出的z项的加权和(或者说 代价函数)关于z项的偏导数。
- 具体来说,
c
o
s
t
(
i
)
cost(i)
cost(i)是一个关于标签
y
y
y和神经网络中
h
(
x
)
h(x)
h(x)的输出值的函数。如果分析网络内部,稍微改下
z
z
z值,最终将改变代价函数的值。
δ
j
(
l
)
delta_j^{(l)}
δj(l)衡量的是,为了影响这些中间值,我们需要改变神经网络中的权重的程度,进而影响整个神经网络的输出
h
(
x
)
h(x)
h(x)并影响所有的代价函数。
下面继续深入了解反向传播的过程。 - 首先计算输出层的 δ 1 ( 4 ) delta_1^{(4)} δ1(4)。 δ 1 ( 4 ) = y ( i ) − a 1 ( 4 ) delta_1^{(4)}= y^{(i)}-a_1^{(4)} δ1(4)=y(i)−a1(4)
- 然后可以计算
δ
1
(
3
)
、
δ
2
(
3
)
、
δ
1
(
2
)
…
…
delta_1^{(3)}、delta_2^{(3)}、delta_1^{(2)}……
δ1(3)、δ2(3)、δ1(2)……。内层的
δ
delta
δ可以通过
θ
theta
θ与后项
δ
delta
δ的加权和得到,如
δ
1
(
2
)
=
θ
12
(
2
)
δ
1
(
3
)
−
θ
22
(
2
)
δ
2
(
3
)
delta_1^{(2)}=theta_{12}^{(2)}delta_1^{(3)} -theta_{22}^{(2)} delta_2^{(3)}
δ1(2)=θ12(2)δ1(3)−θ22(2)δ2(3)需要注意的是,此处的
δ
i
j
(
l
)
delta_{ij}^{(l)}
δij(l)不包括隐藏层的偏置单元(总是1)。
学习目标:学习如何把参数从矩阵展开成向量
学习目标:反向传播的代码实现中,将出现很多bug,因此最终结果可能是bug导致。那么如何应对呢?梯度检测(Gradient Checking)能解决几乎所有这种问题,它能保证前向传播、反向传播的正确性。
假设有如下图所示的
J
(
θ
)
J(theta)
J(θ)(
θ
theta
θ为实数),
θ
theta
θ的导数即曲线在这一点的斜率。
下面从数值上逼近
θ
theta
θ的导数,也就是从数值上来求近似导数。在
θ
theta
θ的左右两边分别找到距其
ϵ
epsilon
ϵ(一般很小,如
1
0
−
4
10^{-4}
10−4)的点
θ
−
ϵ
theta-epsilon
θ−ϵ、
θ
+
ϵ
theta+epsilon
θ+ϵ。连接两点得到线段,线段斜率近似
θ
theta
θ的导数(双侧差分,结果相对于单侧差分更准确)。
ϵ
epsilon
ϵ越小,线段的斜率与
θ
theta
θ的导数越接近。但实现过程中,
ϵ
epsilon
ϵ过小容易引发一些问题,因此一般取
1
0
−
4
10^{-4}
10−4附近的值。
下面考虑**
θ
theta
θ为n维向量**的情况。类比上图方法,计算得到每个
θ
theta
θ的偏导数。
在Octave中的实现如下
然后,我们可以将通过斜率计算得到的导数gradApprox,通过反向传播得到的
D
i
j
(
l
)
D_{ij}^{(l)}
Dij(l)比较。验证它们数值上是否近似相等。近似相等时,说明反向传播代码正确。
因此,使用反向传播算法的步骤一般如下图。
需要注意的是:比较完
D
i
j
(
l
)
D_{ij}^{(l)}
Dij(l)与gradApprox后,需要关闭梯度检测。我们最终使用的导数还是反向传播得到的数据(
D
i
j
(
l
)
D_{ij}^{(l)}
Dij(l)),因为它更高效,前者会导致计算特慢。
使用梯度下降或者其他高级优化方法时,我们需要为
θ
theta
θ取一些初始值。高级优化方法默认提供
θ
theta
θ的初始值,但梯度下降需要我们自行设定
θ
theta
θ的初始值。那么如何设定呢?
一种方法是将
θ
theta
θ的初始值都设置为0。但在神经网络中,这种方法起不到任何作用。
以如下所示神经网络为例。
θ
theta
θ的初始值都设置为0,意味着
a
1
(
2
)
=
a
2
(
2
)
、
δ
1
(
2
)
=
δ
2
(
2
)
a_1^{(2)}=a_2^{(2)}、delta_1^{(2)}=delta_2^{(2)}
a1(2)=a2(2)、δ1(2)=δ2(2),它们的代价函数导数也相等。这会使得各个
θ
theta
θ对一直相等(如
θ
0
1
(
1
)
=
θ
0
2
(
1
)
theta_01^{(1)}=theta_02^{(1)}
θ01(1)=θ02(1))。最终导致一种高度冗余的现象(对称权重问题)。
为了解决这一问题,神经网络的
θ
theta
θ需要使用随机初始化的思想。Octeva中的代码实现如下
总而言之,神经网络中,
θ
theta
θ将随机初始化为一个接近于0,范围在
−
ϵ
-epsilon
−ϵ到
ϵ
epsilon
ϵ之间的数。然后进行反向传播、梯度检验、梯度下降(或其他高级优化方法),从而最小化代价函数,最终得到相应的
θ
theta
θ值(即最优值)。
学习目标:总结所学内容,探究相互间的联系、以及神经网络的总体实现过程。
神经网络训练步骤:
- 0、选择架构,即神经元的连接方式。
输入、输出单元数分别决定于特征项数、分类类别数。
对于隐藏层,默认且合理的选项为只使用单个隐藏层(较于其它,实际上是默认合理的选项。),或者选择不同隐藏层单元数相等的多层隐藏层。
对于每层的隐藏层单元数,一般来说越大越好,但越大意味着计算量越大。此外,每层的隐藏层单元数应该与输入x的维度(特征数量)相匹配,一般是它的2倍、3倍、4倍。 - 1、随机初始化权重。接近于0,范围在 − ϵ -epsilon −ϵ到 ϵ epsilon ϵ之间的数
- 2、执行前向传播算法。
- 3、计算代价函数。
- 4、执行反向传播算法,计算偏导数项。
- 5、梯度检测。将通过斜率计算得到的导数gradApprox,通过反向传播得到的 D i j ( l ) D_{ij}^{(l)} Dij(l)比较。验证反向传播代码正确性。确认正确后,需要关闭梯度检测代码。
- 6、最小化代价函数,求
θ
theta
θ。使用梯度下降算法(或其他高级优化算法),最小化代价函数,最终得到相应的
θ
theta
θ值(即最优值)。因为神经网络中的代价函数为非凸函数(non-convex),通过这种方法,仅能得到代价函数的局部最小值;但一般来说,此时的结果已经很好了。
下面,我们通过下图对梯度下降法在神经网络中的应用作进一步展示。仅考虑只有两个 θ theta θ的情况(实际则不然,但太多维度会导致可视化困难)。梯度下降的过程即:从某点开始向代价函数下降最快的方向一点点变化,最终达到局部最小值。反向传播的作用是找到梯度下降的方向,梯度下降的作用是沿着这个方向一点点下降。
默认处理数据为矩阵
参考资料
网易版 吴恩达机器学习
2021机器学习(西瓜书+李航统计学习方法)实践部分 + Python


![吴恩达机器学习[10]-神经网络参数的反向传播算法 吴恩达机器学习[10]-神经网络参数的反向传播算法](http://www.mshxw.com/aiimages/31/1026343.png)
