2022.01.20开始新的一章
2022.01.21加油干,提高效率
2022.01.22争取明天拿下
2022.01.23好难,还要一天
2022.01.24今天弄完了
以 z1(3) 的计算为例:
z
1
(
3
)
=
Θ
10
(
2
)
×
1
+
Θ
11
(
2
)
×
a
1
(
2
)
+
Θ
12
(
2
)
×
a
2
(
2
)
z^{(3)}_1=\Theta^{(2)}_{10}\times 1+\Theta^{(2)}_{11}\times a_1^{(2)}+\Theta^{(2)}_{12}\times a_2^{(2)}
z1(3)=Θ10(2)×1+Θ11(2)×a1(2)+Θ12(2)×a2(2)
反向传播的过程实际上和前向传播相似,只是方向不同。
对于只有一个输出单元的情况,对应的代价函数如下:
J
(
Θ
)
=
−
1
m
[
∑
i
=
1
m
(
y
(
i
)
l
o
g
(
h
Θ
(
x
(
i
)
)
)
+
(
1
−
y
(
i
)
)
l
o
g
(
1
−
h
Θ
(
x
(
i
)
)
)
)
]
+
λ
2
m
∑
l
=
1
L
−
1
∑
i
=
1
s
l
∑
j
=
1
s
l
+
1
(
Θ
j
i
(
l
)
)
2
\begin{aligned} &J(\Theta)=-\frac{1}{m}[\sum_{i=1}^m(y^{(i)}log(h_\Theta(x^{(i)}))+(1-y^{(i)})log(1-h_\Theta(x^{(i)})))]\\&\qquad\quad+\frac{λ}{2m}{\sum_{l=1}^{L-1}\sum_{i=1}^{s_l}\sum_{j=1}^{s_l+1}(\Theta^{(l)}_{ji})^2} \end{aligned}
J(Θ)=−m1[i=1∑m(y(i)log(hΘ(x(i)))+(1−y(i))log(1−hΘ(x(i))))]+2mλl=1∑L−1i=1∑slj=1∑sl+1(Θji(l))2
同一组样本中,同时使用了前向传播和反向传播算法。关注只有一个输出单元的情况((x(i),y(i)),其中 x(i) 为实数),同时忽略正则化(λ = 0),此时以上代价函数表达式中的最后一项就没有了。
观察括号中的求和项,发现代价函数对应第 i 个训练样本,即代价函数对应的训练样本 (x(i),y(i)),是由下面的表达式给出的:
c
o
s
t
(
i
)
=
y
(
i
)
l
o
g
h
Θ
(
x
(
i
)
)
+
(
1
−
y
(
i
)
)
l
o
g
(
1
−
h
Θ
(
x
(
i
)
)
)
\begin{aligned} cost(i)=y^{(i)}log\ h_\Theta(x^{(i)})+(1-y^{(i)})log(1-h_\Theta(x^{(i)})) \end{aligned}
cost(i)=y(i)log hΘ(x(i))+(1−y(i))log(1−hΘ(x(i)))
这个代价函数起到了一个类似方差的作用,也可以把这个表达式近似地当成是神经网络输出值与实际值的方差:
c
o
s
t
(
i
)
≈
(
h
Θ
(
x
(
i
)
)
−
y
(
i
)
)
2
\begin{aligned} cost(i)\approx(h_\Theta(x^{(i)})-y^{(i)})^2 \end{aligned}
cost(i)≈(hΘ(x(i))−y(i))2
就像逻辑回归中,实际中会偏向于选择比较复杂的带对数形式的代价函数,但是为了方便理解,可以把这个代价函数看做是某种方差函数,因此 cost(i) 表示了神经网络预测样本值的准确程度,也就是网络的输出值和实际观测值 y(i) 的接近程度。
一种直观的理解是:反向传播算法就是在计算这些 δ 项,可以把它看做是在第 l 层中,第 j 个单元中得到的激活项的“误差”。
δ 项实际上是代价函数 cost(i) 关于 zj(l) 的偏导数,也就是计算出的 z 项的加权和,或者说代价函数关于 z 项的偏导数。具体来说,这个代价函数是一个关于标签 y 和神经网络中 h(x) 的输出值的函数。
如果在神经网络的内部稍微把 zj(l) 改一下,就会影响到神经网络中 y(i)、hΘ(x(i)) 的值,最终将改变代价函数的值。
δ
j
(
l
)
=
“error”
of
cost
for
a
j
(
l
)
(unit
j
in
layer
l
).
Formally,
δ
j
(
l
)
=
∂
∂
z
j
(
l
)
c
o
s
t
(
i
)
(for
j
≥
0
)
,
where
c
o
s
t
(
i
)
=
y
(
i
)
l
o
g
h
Θ
(
x
(
i
)
)
+
(
1
−
y
(
i
)
)
l
o
g
(
1
−
h
Θ
(
x
(
i
)
)
)
\begin{aligned} &\delta^{(l)}_j=\textbf{“error”\ \ of\ \ cost\ \ for\ \ }a^{(l)}_j\ \ \textbf{(unit\ \ }j\ \ \textbf{in\ \ layer}\ \ l\textbf{).}\\ &\textbf{Formally,}\ \ \delta^{(l)}_j=\frac{\partial}{\partial z^{(l)}_j}cost(i)\quad \textbf{(for\ \ }j\ge0),\textbf{where}\\ &cost(i)=y^{(i)}log\ h_\Theta(x^{(i)})+(1-y^{(i)})log(1-h_\Theta(x^{(i)})) \end{aligned}
δj(l)=“error” of cost for aj(l) (unit j in layer l).Formally, δj(l)=∂zj(l)∂cost(i)(for j≥0),wherecost(i)=y(i)log hΘ(x(i))+(1−y(i))log(1−hΘ(x(i)))
这些 δ 项实际上是代价函数关于这些所计算出的中间项的偏导数,他们衡量的是为了影响这些中间值,想要改变神经网络中的权重的程度,进而影响整个神经网络的输出 h(x),并影响所有的代价函数。
以上图中 a2(2)、a1(4) 神经元计算的 δ 项为例:
δ
1
(
4
)
=
y
(
i
)
−
a
1
(
4
)
δ
2
(
2
)
=
Θ
12
(
2
)
δ
1
(
3
)
+
Θ
22
(
2
)
δ
2
(
3
)
\begin{aligned} &\delta^{(4)}_1=y^{(i)}-a^{(4)}_1\\ &\delta^{(2)}_2=\Theta^{(2)}_{12}\delta^{(3)}_1+\Theta^{(2)}_{22}\delta^{(3)}_2 \end{aligned}
δ1(4)=y(i)−a1(4)δ2(2)=Θ12(2)δ1(3)+Θ22(2)δ2(3)
注意:最终计算 δ 项的隐藏单元中不包含偏置单元。
function [jVal, gradient] = costFunction(theta) ... optTheta = fminunc(@costFunction, initialTheta, options)
% 矩阵展开成为长向量 thetaVec = [ Theta1(:); Theta2(:); Theta3(:)]; DVec = [D1(:); D2(:); D3(:)]; % 从向量表达式返回到矩阵表达式 % reshape 用于改变矩阵大小 Theta1 = reshape(thetaVec(1:110),10,11); Theta2 = reshape(thetaVec(111:220),10,11); Theta3 = reshape(thetaVec(221:231),1,11);
gradApprox = (J(theta + EPSILON) – J(theta – EPSILON)) /(2*EPSILON)
for i = 1:n, thetaPlus = theta; thetaPlus(i) = thetaPlus(i) + EPSILON; thetaMinus = theta; thetaMinus(i) = thetaMinus(i) – EPSILON; gradApprox(i) = (J(thetaPlus) – J(thetaMinus)) /(2*EPSILON); end; % Check that gradApprox ≈ DVec
I m p l e m e n t a t i o n N o t e : − I m p l e m e n t b a c k p r o p t o c o m p u t e D V e c ( u n r o l l e d D ( 1 ) , D ( 2 ) , D ( 3 ) ) . − I m p l e m e n t n u m e r i c a l g r a d i e n t c h e c k t o c o m p u t e g r a d A p p r o x . − M a k e s u r e t h e y g i v e s i m i l a r v a l u e s . − T u r n o f f g r a d i e n t c h e c k i n g . U s i n g b a c k p r o p c o d e f o r l e a r n i n g . I m p o r t a n t : − B e s u r e t o d i s a b l e y o u r g r a d i e n t c h e c k i n g c o d e b e f o r e t r a i n i n g y o u r c l a s s i f i e r . I f y o u r u n n u m e r i c a l g r a d i e n t c o m p u t a 5 o n o n e v e r y i t e r a 5 o n o f g r a d i e n t d e s c e n t ( o r i n t h e i n n e r l o o p o f c o s t F u n c t i o n ( … ) ) y o u r c o d e w i l l b e v e r y ‾ s l o w . \begin{aligned} &Implementation\ \ Note\ \ :\\ &\qquad - Implement\ \ backprop\ \ to\ \ compute\ \ \blue{DVec}\ \ (unrolled\ \ D^{(1)},D^{(2)},D^{(3)}).\\ &\qquad - Implement\ \ numerical\ \ gradient\ \ check\ \ to\ \ compute\ \ \blue{gradApprox}.\\ &\qquad - Make\ \ sure\ \ they\ \ give\ \ similar\ \ values.\\ &\qquad - Turn\ \ off\ \ gradient\ \ checking.\ \ Using\ \ backprop\ \ code\ \ for\ \ learning.\\ &Important:\\ &\qquad - Be\ \ sure\ \ to\ \ disable\ \ your\ \ gradient\ \ checking\ \ code\ \ before\ \ training\\ &\qquad \quad your\ \ classifier.\ \ If\ \ you\ \ run\ \ numerical\ \ gradient\ \ computa5on\ \ on\\ &\qquad \quad every\ \ itera5on\ \ of\ \ gradient\ \ descent\ \ (or\ \ in\ \ the\ \ inner\ \ loop\ \ of\\ &\qquad \quad \blue{costFunction(…)})your\ \ code\ \ will\ \ be\ \ \underline{very}\ \ slow.\\ \end{aligned} Implementation Note :−Implement backprop to compute DVec (unrolled D(1),D(2),D(3)).−Implement numerical gradient check to compute gradApprox.−Make sure they give similar values.−Turn off gradient checking. Using backprop code for learning.Important:−Be sure to disable your gradient checking code before trainingyour classifier. If you run numerical gradient computa5on onevery itera5on of gradient descent (or in the inner loop ofcostFunction(…))your code will be very slow.
optTheta = fminunc(@costFunction, initialTheta, options)
initialTheta = zeros(n,1)
虽然在逻辑回归中这样做是没有问题的,但实际上在训练网络时,将所有的参数都初始化为 0 起不到任何作用,以下面的神经网络训练为例:
假如将神经网络中所有参数都初始化为 0,这就意味着从输入层到第一个隐藏层中的每一条边的权值均为 0,对于训练集中的每一个样本,最后都能得到:
a
1
(
2
)
=
a
2
(
2
)
δ
1
(
2
)
=
δ
2
(
2
)
\begin{aligned} a_1^{(2)}&=a_2^{(2)}\\ \delta_1^{(2)}&=\delta_2^{(2)}\\ \end{aligned}
a1(2)δ1(2)=a2(2)=δ2(2)
这就意味着,在梯度下降的更新过程中,虽然数值会发生变化不为 0,但最后二者仍然会是相等的:
∂
∂
Θ
01
(
1
)
J
(
Θ
)
=
∂
∂
Θ
02
(
1
)
J
(
Θ
)
Θ
01
(
1
)
=
Θ
02
(
1
)
\begin{aligned} \frac{\partial}{\partial\Theta_{01}^{(1)}}J(\Theta)&=\frac{\partial}{\partial\Theta_{02}^{(1)}}J(\Theta)\\\ \\ \Theta_{01}^{(1)}&=\Theta_{02}^{(1)}\\ \end{aligned}
∂Θ01(1)∂J(Θ) Θ01(1)=∂Θ02(1)∂J(Θ)=Θ02(1)
也就是说,所有的隐藏单元都在计算同一个特征。这是一种高度冗余的现象,这就意味着,最后的逻辑回归单元只能得到一个特征,因为所有的单元都一样,神经网络也就学习不到任何有趣的东西。
为了解决这一问题,在神经网络中对参数进行初始化时,要使用随机初始化的思想。
Theta1 = rand(10,11)*(2*INIT_EPSILON) - INIT_EPSILON; Theta2 = rand( 1,11)*(2*INIT_EPSILON) - INIT_EPSILON;
Training a neural network 1. R a n d o m l y i n i t i a l i z e w e i g h t s 2. I m p l e m e n t f o r w a r d p r o p a g a t i o n t o g e t h Θ ( x ( i ) ) f o r a n y x ( i ) 3. I m p l e m e n t c o d e t o c o m p u t e c o s t f u n c t i o n J ( Θ ) 4. I m p l e m e n t b a c k p r o p t o c o m p u t e p a r t i a l d e r i v a t i v e s ∂ ∂ Θ j k ( l ) J ( Θ ) f o r i = 1 : m P e r f o r m f o r w a r d p r o p a g a t i o n a n d b a c k p r o p a g a t i o n u s i n g e x a m p l e ( x ( i ) , y ( i ) ) ( G e t a c t i v a t i o n s a ( l ) a n d d e l t a t e r m s δ ( l ) f o r l = 2 , . . . , L ) . 5. U s e g r a d i e n t c h e c k i n g t o c o m p a r e ∂ ∂ Θ j k ( l ) J ( Θ ) c o m p u t e d u s i n g b a c k p r o p a g a t i o n v s . u s i n g n u m e r i c a l e s t i m a t e o f g r a d i e n t o f J ( Θ ) . T h e n d i s a b l e g r a d i e n t c h e c k i n g c o d e . 6. U s e g r a d i e n t d e s c e n t o r a d v a n c e d o p t i m i z a t i o n m e t h o d w i t h b a c k p r o p a g a t i o n t o t r y t o m i n i m i z e J ( Θ ) a s a f u n c t i o n o f p a r a m e t e r s \begin{aligned} &\textbf{Training \ \ a\ \ neural\ \ network}\\ &1. Randomly\ \ initialize\ \ weights\\ &2. Implement\ \ forward\ \ propagation\ \ to\ \ get\ \ h_\Theta(x^{(i)})\ \ for\ \ any\ \ x^{(i)}\\ &3. Implement\ \ code\ \ to\ \ compute\ \ cost\ \ function\ \ J(\Theta)\\ &4. Implement\ \ backprop\ \ to\ \ compute\ \ partial\ \ derivatives\ \ \ \ \frac{\partial}{\partial\Theta_{jk}^{(l)}}J(\Theta)\\ &\quad for \ \ i = 1:m \\ &\quad\qquad Perform\ \ forward\ \ propagation\ \ and\ \ backpropagation\ \ using\\ &\quad\qquad example\ \ (x^{(i)},y^{(i)})\\ &\quad\qquad(Get\ \ activations\ \ a^{(l)}and\ \ delta\ \ terms\ \ \delta^{(l)}\ \ for \ \ l=2,...,L).\\ &5. Use\ \ gradient\ \ checking\ \ to\ \ compare\ \ \frac{\partial}{\partial\Theta_{jk}^{(l)}}J(\Theta)\ \ computed\ \ using\\ &\quad\qquad backpropagation\ \ vs.\ \ using\ \ \ \ numerical\ \ estimate\ \ of\ \ gradient\ \ of\ \ J(\Theta).\\ &\quad\qquad Then\ \ disable\ \ gradient\ \ checking\ \ code.\\ &6. Use\ \ gradient\ \ descent\ \ or\ \ advanced\ \ optimization\ \ method\ \ with\\ &\quad\qquad backpropagation\ \ to\ \ try\ \ to\ \ \ \ minimize\ \ J(\Theta)\ \ as\ \ a\ \ function\ \ of\\ &\quad\qquad parameters\\ \end{aligned} Training a neural network1.Randomly initialize weights2.Implement forward propagation to get hΘ(x(i)) for any x(i)3.Implement code to compute cost function J(Θ)4.Implement backprop to compute partial derivatives ∂Θjk(l)∂J(Θ)for i=1:mPerform forward propagation and backpropagation usingexample (x(i),y(i))(Get activations a(l)and delta terms δ(l) for l=2,...,L).5.Use gradient checking to compare ∂Θjk(l)∂J(Θ) computed usingbackpropagation vs. using numerical estimate of gradient of J(Θ).Then disable gradient checking code.6.Use gradient descent or advanced optimization method withbackpropagation to try to minimize J(Θ) as a function ofparameters
本节将介绍一个神经网络学习的例子,就是通过神经网络来实现自动驾驶(汽车通过学习来自己驾驶)。
起初初始化后算法对应的横线是一段比较均匀的白线,随着学习的进行,白色部分逐渐集中在一小部分区域。