如果对这篇简明的博客存在理解上的困难,你可以看第四周关于神经网络模型的博客或者再看一遍Andrew Ng的课程视频
代价函数
相比逻辑回归代价函数,大概八成新
J ( Θ ) = − 1 m ∑ i = 1 m ∑ k = 1 K [ y k ( i ) log ( ( h Θ ( x ( i ) ) ) k ) + ( 1 − y k ( i ) ) log ( 1 − ( h Θ ( x ( i ) ) ) k ) ] + λ 2 m ∑ l = 1 L − 1 ∑ i = 1 s l ∑ j = 1 s l + 1 ( Θ j , i ( l ) ) 2 J(\Theta) = - \frac{1}{m} \sum_{i=1}^m \sum_{k=1}^K \left[y^{(i)}_k \log ((h_\Theta (x^{(i)}))_k) + (1 - y^{(i)}_k)\log (1 - (h_\Theta(x^{(i)}))_k)\right] + \frac{\lambda}{2m}\sum_{l=1}^{L-1} \sum_{i=1}^{s_l} \sum_{j=1}^{s_{l+1}} ( \Theta_{j,i}^{(l)})^2 J(Θ)=−m1i=1∑mk=1∑K[yk(i)log((hΘ(x(i)))k)+(1−yk(i))log(1−(hΘ(x(i)))k)]+2mλl=1∑L−1i=1∑slj=1∑sl+1(Θj,i(l))2
参考回顾逻辑回归公式:
J
(
Θ
)
=
−
1
m
∑
i
=
1
m
[
y
(
i
)
+
log
(
h
θ
(
x
(
i
)
)
)
+
(
1
−
y
(
i
)
)
log
(
1
−
h
θ
(
x
(
i
)
)
]
+
λ
2
m
∑
j
=
1
n
θ
j
2
J(\Theta)=-\dfrac{1}{m}\sum_{i=1}^m[y^{(i)} + \log (h_{\theta}(x^{(i)}))+(1-y^{(i)})\log (1-h_{\theta}(x^{(i)})]+\dfrac{\lambda}{2m}\sum_{j=1}{n}\theta^2_j
J(Θ)=−m1i=1∑m[y(i)+log(hθ(x(i)))+(1−y(i))log(1−hθ(x(i))]+2mλj=1∑nθj2
主要区别:
- 此时被累加项不再是矩阵。观察神经网络中的 x ( i ) x^{(i)} x(i),不是样本的特征向量而是单个特征的值,i也不指代样本序号,而是单个样本的特征值序号
- 非正则项添加了输出单元/种类数的累加计算
- 正则项的累加项改写为与层数和其相邻项的累加
- 非正则项只是累加输出层的逻辑回归误差值
- 正则项累加了整个神经网络的所有权重的平方值
参数分析
- L = 包括输出层,输入层和中间层的总层数
- s l s_l sl = 第 l l l层不包括偏置项(bias)在内的单元数
- K = 输出单元/种类
- l = 层数序号
-
δ
j
(
l
)
\delta^{(l)}_j
δj(l) = 第l层第j个节点的误差(error),其实就是第l层代价函数的偏导项,
- Δ \Delta Δ = 权重矩阵,包括了偏置项,最终目的是通过向后传播
- D i j ( l ) D^{(l)}_{ij} Dij(l) = 第l层前一层第i节点对该层第j节点的权重代价函数的求偏导值,知道是怎么算出来的
- g ′ ( z ( l ) ) g^{'}(z^{(l)}) g′(z(l)) = 第l层激活函数的偏导项
反向传播
反向传播是神经网络中的“梯度下降”,即计算 m i n Θ J ( Θ ) min_{\Theta}J(\Theta) minΘJ(Θ),这是极关键且必须掌握的概念
对全体训练集 X X X
-
初始化,设置 Δ i , j ( l ) : = 0 \Delta^{(l)}_{i,j}:=0 Δi,j(l):=0,(l-第l层,i-传播层特征序号,j-接收层特征序号),得到全0矩阵
-
对 t = 1 … m 项训练样本(循环以下五步):
- 设置 a ( 1 ) : = x ( t ) a^{(1)}:=x^{(t)} a(1):=x(t)
- 整个神经网络进行依次完整的向前传播
梯度下降
3. 计算输出层误差:
δ
(
L
)
=
a
(
L
)
−
y
(
t
)
\delta^{(L)}=a^{(L)}-y^{(t)}
δ(L)=a(L)−y(t),L为总层数,代表输出层
4. 从输出层开始,依次向后递推每层的误差,使用公式:
δ
(
l
)
=
(
(
Θ
(
l
)
)
T
δ
(
l
+
1
)
)
.
∗
a
(
l
)
.
∗
(
1
−
a
(
l
)
)
\delta^{(l)} = ((\Theta^{(l)})^T \delta^{(l+1)})\ .*\ a^{(l)}\ .*\ (1 - a^{(l)})
δ(l)=((Θ(l))Tδ(l+1)) .∗ a(l) .∗ (1−a(l))计算所有中间层的
δ
\delta
δ,其中
g
′
(
z
(
l
)
)
=
a
(
l
)
.
∗
(
1
−
a
(
l
)
)
g^{'}(z^{(l)})=a^{(l)}\ .*\ (1 - a^{(l)})
g′(z(l))=a(l) .∗ (1−a(l)),即激活函数的偏导项
5. 利用求得的误差项更新
Δ
{\Delta}
Δ,完成一次梯度下降:
可以逐层更新:
Δ
i
,
j
(
l
)
:
=
Δ
i
,
j
(
l
)
+
a
j
(
l
)
δ
i
(
l
+
1
)
\Delta^{(l)}_{i,j}:=\Delta^{(l)}_{i,j} + a^{(l)}_j\delta^{(l+1)}_i
Δi,j(l):=Δi,j(l)+aj(l)δi(l+1)
也可以一步更新全体矩阵公式:
Δ
(
l
)
:
=
Δ
(
l
)
+
δ
(
l
+
1
)
(
a
(
l
)
)
T
\Delta^{(l)}:=\Delta^{(l)}+\delta^{(l+1)}(a^{(l)})^T
Δ(l):=Δ(l)+δ(l+1)(a(l))T
- D是一个累加器,最终值满足
∂
∂
Θ
i
j
(
l
)
J
(
Θ
)
=
D
i
j
(
l
)
\frac \partial {\partial \Theta_{ij}^{(l)}} J(\Theta)=D^{(l)}_{ij}
∂Θij(l)∂J(Θ)=Dij(l)
具体而言:
D i , j ( l ) : = 1 m ( Δ i , j ( l ) + λ Θ i , j ( l ) ) , j ! = 0 D^{(l)}_{i,j} := \dfrac{1}{m}(\Delta^{(l)}_{i,j} + \lambda\Theta^{(l)}_{i,j}) ,j != 0 Di,j(l):=m1(Δi,j(l)+λΘi,j(l)),j!=0 D i , j ( l ) : = 1 m ( Δ i , j ( l ) ) , j = 0 D^{(l)}_{i,j} := \dfrac{1}{m}(\Delta^{(l)}_{i,j}),j=0 Di,j(l):=m1(Δi,j(l)),j=0
其中j为某层特征单元序号,j=0代表偏置项
反向传播实现原理
反向传播主要就是误差的反向传播,由输出层的误差开始,根据每一层的权重逐层向后推导该层产生的误差值(这个误差值的大小反映了错误的程度和稍后优化更新权重的力度),当获得神经网络的误差矩阵后,根据误差对每一层权重进行一次更新
这一块能够掌握神经网络的前后传播算法就已经够了,实在想弄明白看十分种的课程视频也就够了,所以又到了一图解千愁的时候
图中有两个地方需加注意
- 误差项 δ j ( l ) = ∂ ∂ z j ( l ) c o s t ( t ) \delta_j^{(l)} = \dfrac{\partial}{\partial z_j^{(l)}} cost(t) δj(l)=∂zj(l)∂cost(t),其中t代表的是样本序号(如同i),且有 c o s t ( t ) = y ( t ) log ( h Θ ( x ( t ) ) ) + ( 1 − y ( t ) ) log ( 1 − h Θ ( x ( t ) ) ) cost(t) =y^{(t)} \ \log (h_\Theta (x^{(t)})) + (1 - y^{(t)})\ \log (1 - h_\Theta(x^{(t)})) cost(t)=y(t) log(hΘ(x(t)))+(1−y(t)) log(1−hΘ(x(t))) cost(t)为总的代价函数的非正则项的一次累加项(对比代价函数,i换成了t)
- 误差的传递也与权重有关,看图中右上角的公式,能否推断出
δ
2
(
3
)
\delta^{(3)}_2
δ2(3)?
最终,权重的更新就是通过以上两方面的两个公式列等式获得的,具体的数学计算不做介绍
算法优化
了解神经网络算法模型并不代表能够将神经网络应用于实践,为此,我们需要进行一些重要的优化过程
展开参数
为了能够使用fminunc()等算法对神经网络进行处理,对参数进行以下处理
- 需展开各层矩阵参数: Θ ( 1 ) , Θ ( 2 ) , Θ ( 3 ) , … D ( 1 ) , D ( 2 ) , D ( 3 ) , … \Theta^{(1)}, \Theta^{(2)}, \Theta^{(3)}, \dots \newline D^{(1)}, D^{(2)}, D^{(3)}, \dots Θ(1),Θ(2),Θ(3),…D(1),D(2),D(3),…以权重矩阵为例
- 参数预处理,比如Theta1 是 10x11,Theta2 是 10x11,Theta3 是 1x11,那么再Octave中
Theta1 = reshape(thetaVector(1:110),10,11) Theta2 = reshape(thetaVector(111:220),10,11) Theta3 = reshape(thetaVector(221:231),1,11)
- 将参数合并,如在Octave中:
thetaVector = [ Theta1(:); Theta2(:); Theta3(:); ] deltaVector = [ D1(:); D2(:); D3(:) ]
- 代入fminunc()方程,获取更新后的权重矩阵:(对D使用原理相同,得到梯度矩阵)
梯度检验
由于向后传播算法的复杂性,我们在应用神经网络时并不能够获得正确的结果,梯度检验用于确保向后传播正常运行,即代价函数值逐步减小,这一步是必要的
- 选择合适的检验参数 ϵ \epsilon ϵ,一般选择 ϵ = 1 0 − 4 \epsilon = 10^{-4} ϵ=10−4能够实现准确检验
- 带入估值公式:
∂
∂
Θ
J
(
Θ
)
≈
J
(
Θ
+
ϵ
)
−
J
(
Θ
−
ϵ
)
2
ϵ
\dfrac{\partial}{\partial\Theta}J(\Theta) \approx \dfrac{J(\Theta + \epsilon) - J(\Theta - \epsilon)}{2\epsilon}
∂Θ∂J(Θ)≈2ϵJ(Θ+ϵ)−J(Θ−ϵ)当然
∂
∂
Θ
j
J
(
Θ
)
≈
J
(
Θ
1
,
…
,
Θ
j
+
ϵ
,
…
,
Θ
n
)
−
J
(
Θ
1
,
…
,
Θ
j
−
ϵ
,
…
,
Θ
n
)
2
ϵ
\dfrac{\partial}{\partial\Theta_j}J(\Theta) \approx \dfrac{J(\Theta_1, \dots, \Theta_j + \epsilon, \dots, \Theta_n) - J(\Theta_1, \dots, \Theta_j - \epsilon, \dots, \Theta_n)}{2\epsilon}
∂Θj∂J(Θ)≈2ϵJ(Θ1,…,Θj+ϵ,…,Θn)−J(Θ1,…,Θj−ϵ,…,Θn)而对于编程实现,在Octave中有:
epsilon = 1e-4; for i = 1:n, thetaPlus = theta; thetaPlus(i) += epsilon; thetaMinus = theta; thetaMinus(i) -= epsilon; gradApprox(i) = (J(thetaPlus) - J(thetaMinus))/(2*epsilon) end;
- 比较梯度估值和向后传播误差,做出判断
gradApprox ≈ deltaVector
注意事项:
使用梯度检验验证验证向后传播正常情况下,在应用神经网络到训练集时就要关闭
随机初始化
将所有的权重初始化为0会使得神经网络无法正常工作
因此随机初始化也是必要的
以上算法将产生所有元素值在
−
ϵ
→
ϵ
-\epsilon \rightarrow \epsilon
−ϵ→ϵ内的权重矩阵,此中epsilon与梯度检验无关
Octave矩阵编程实现:
If the dimensions of Theta1 is 10x11, Theta2 is 10x11 and Theta3 is 1x11.
Theta1 = rand(10,11) * (2 * INIT_EPSILON) - INIT_EPSILON;
Theta2 = rand(10,11) * (2 * INIT_EPSILON) - INIT_EPSILON;
Theta3 = rand(1,11) * (2 * INIT_EPSILON) - INIT_EPSILON;
算法应用综析
选择合适的神经网络结构
- 输入层节点数 = x ( i ) x^{(i)} x(i)特征数
- 输出层节点数 = 分类问题分类类别
- 在综合平衡算力的情况下,中间层(隐藏层)越多越好
- 默认情况下一层中间层,如果采用多层中间层,最好每层节点数都一样
训练神经网络算法
- 随机初始化权重
- 实现向前传播算法,运行向前传播,获得所有训练样本的估计值 h Θ ( x ( i ) ) h_\Theta(x^{(i)}) hΘ(x(i))
- 带入运算代价函数
- 实现向后传播算法,计算代价函数偏导项Dvec
- 使用梯度检验。确保向后传播正常运行后,关闭梯度检验
- 使用梯度下降算法或者其它后话方法获得代价函数全局最小值
注意在前后传播中,我们需要遍历每一个训练样本,且对每个样本分别进行前后传播后再遍历下一个样本:
for i = 1:m,
Perform forward propagation and backpropagation using example (x(i),y(i))
(Get activations a(l) and delta terms d(l) for l = 2,...,L
最终结果示意图:
h
Θ
(
x
(
i
)
)
≈
y
(
i
)
h_\Theta(x^{(i)})\approx y^{(i)}
hΘ(x(i))≈y(i)为理想结果,但由于代价函数不是一个凸函数,我们仍可能会滞留在局部最小值
能更好地解决这个问题吗?