1. BP算法的提出
BP算法最初是由Paul Werbos在1974其博士论文中首次论证。 David E. Rumelhart 、Geoffrey Hinton、Ronald J. Wlilliams 三人在1986年再次发表在了1986年10月9日的Nature上,(原始论文地址这个要收费,文末有免费的paper地址,整个paper篇幅不长,有兴趣的可以下来读一读。) 目前我们通常说的BP算法多指86年提出的算法。
2. BP算法的理解
BP算法的理解可以拆解成三部分:
- 反向传播
- 梯度下降
- 链式法则
下面我们简单的说下各部分的细节
2.1 反向传播
何为反向传播?就是使用预测值与实际值的差异来反向更新网络的参数。这里的差异指通过损失函数计算出的 l o s s loss loss,举例,如: l o s s = 1 2 ∑ i = 1 n ( y i − y i ∗ ) 2 loss=\frac{1}{2}\sum_{i=1}^{n}{(y_i-y_i^*)^2} loss=21∑i=1n(yi−yi∗)2,这个总体的 l o s s loss loss就是我们要更新参数的依据。
2.2 梯度下降
我们现在想使用 l o s s loss loss来更新参数,怎么更新呢?我们先从简单的入手,如下这个网络。(偏置项没有画)
我们是怎么计算出loss的?根据公式
l
o
s
s
=
1
2
∑
i
=
1
n
(
y
i
−
y
i
∗
)
2
loss=\frac{1}{2}\sum_{i=1}^{n}{(y_i-y_i^*)^2}
loss=21∑i=1n(yi−yi∗)2
l
o
s
s
=
1
2
(
y
−
o
1
)
2
+
1
2
(
y
−
o
2
)
2
o
1
=
s
i
g
m
o
i
d
(
h
1
∗
w
5
+
h
2
∗
w
6
+
b
2
)
o
2
=
s
i
g
m
o
i
d
(
h
1
∗
w
7
+
h
2
∗
w
8
+
b
2
)
h
1
=
s
i
g
m
o
i
d
(
x
1
∗
w
1
+
x
2
∗
w
2
+
b
1
)
h
2
=
s
i
g
m
o
i
d
(
x
1
∗
w
3
+
x
2
∗
w
4
+
b
1
)
loss=\frac{1}{2}(y-o_1)^2 + \frac{1}{2}(y-o_2)^2\\ o_1=sigmoid(h_1*w_5+h_2*w_6 +b_2)\\ o_2=sigmoid(h_1*w_7+h_2*w_8 +b_2)\\ h_1=sigmoid(x_1*w_1+x_2*w_2 +b_1)\\ h_2=sigmoid(x_1*w_3+x_2*w_4 +b_1)
loss=21(y−o1)2+21(y−o2)2o1=sigmoid(h1∗w5+h2∗w6+b2)o2=sigmoid(h1∗w7+h2∗w8+b2)h1=sigmoid(x1∗w1+x2∗w2+b1)h2=sigmoid(x1∗w3+x2∗w4+b1)
这里我们把
h
1
h_1
h1、
h
2
h_2
h2代入
o
1
o_1
o1、
o
2
o_2
o2,再把
o
1
o_1
o1、
o
2
o_2
o2代入
l
o
s
s
的
公
式
loss的公式
loss的公式,最后我们会得到一个关于
x
x
x的式子
L
(
x
)
L(x)
L(x)(这个式子太长了,不写了),我们的
l
o
s
s
loss
loss就是把
x
x
x输入到这个式子计算得到的。说了这么多,其实我只是想表达一件事儿,就是神经网络看起来很复杂,但用数学描述后,就是一个很大的复合函数。把输入变量输进来,就能得到
l
o
s
s
loss
loss(网络的输出当然是
y
∗
y*
y∗),之后就好办了,更新一个函数的参数我们可以用梯度下降法:
w
∗
=
w
−
α
∂
f
∂
w
w^* = w - \alpha\frac{{\partial}f}{ {\partial}w}
w∗=w−α∂w∂f
2.3 链式求导
问题转化为怎么求导
∂
f
∂
w
\frac{{\partial}f}{ {\partial}w}
∂w∂f,这里我们以更新参数
w
5
w_5
w5来举例说明:
我们看看
w
5
w_5
w5是从哪里开始影响
l
o
s
s
loss
loss的
l
o
s
s
=
1
2
(
y
−
o
1
)
2
+
1
2
(
y
−
o
2
)
2
o
1
=
s
i
g
m
o
i
d
(
h
1
∗
w
5
+
h
2
∗
w
6
+
b
2
)
o
2
=
s
i
g
m
o
i
d
(
h
1
∗
w
7
+
h
2
∗
w
8
+
b
2
)
loss=\frac{1}{2}(y-o_1)^2 + \frac{1}{2}(y-o_2)^2\\ o_1=sigmoid(h_1*w_5+h_2*w_6 +b_2)\\ o_2=sigmoid(h_1*w_7+h_2*w_8 +b_2)\\
loss=21(y−o1)2+21(y−o2)2o1=sigmoid(h1∗w5+h2∗w6+b2)o2=sigmoid(h1∗w7+h2∗w8+b2)
我们定义sigmoid函数为
g
(
x
)
=
1
1
+
e
x
g(x) = \frac{1}{1+e^x}
g(x)=1+ex1 , sigmoid函数内的式子定义为
f
(
x
,
w
)
=
x
⃗
∗
w
⃗
f(x,w) = \vec{x} * \vec{w}
f(x,w)=x∗w(偏置项可以理解为
1
∗
b
1*b
1∗b,
w
w
w为参数), 损失函数定义为
L
(
y
)
=
1
2
∑
i
=
1
n
(
y
i
−
y
i
∗
)
2
L(y)=\frac{1}{2}\sum_{i=1}^{n}{(y_i-y_i^*)^2}
L(y)=21∑i=1n(yi−yi∗)2,则:
l
o
s
s
=
L
(
o
)
=
L
(
g
(
f
(
h
)
)
)
o
1
=
g
1
(
f
1
(
h
1
,
2
,
w
5
,
6
)
)
o
2
=
g
2
(
f
2
(
h
1
,
2
,
w
7
,
8
)
)
\begin{aligned} loss&=L(o)=L(g(f(h)))\\ o_1 &= g_1(f_1(h_{1,2},w_{5,6}))\\ o_2 &= g_2(f_2(h_{1,2},w_{7,8}))\\ \end{aligned}
losso1o2=L(o)=L(g(f(h)))=g1(f1(h1,2,w5,6))=g2(f2(h1,2,w7,8))
这个式子就是我上面说的超长的式子
L
(
x
)
L(x)
L(x)(这里没有展开,所以看着不长),当然这个式子的输入是
h
1
h_1
h1、
h
2
h_2
h2。我们计算
L
(
x
)
L(x)
L(x)关于
w
w
w的偏导,这里用到了数学中的链式法则,即:
∂
L
∂
w
=
∂
L
∂
g
∗
∂
g
∂
f
∗
∂
f
∂
w
\frac{{\partial}L}{ {\partial}w}=\frac{{\partial}L}{ {\partial}g}*\frac{{\partial}g}{ {\partial}f}*\frac{{\partial}f}{ {\partial}w}
∂w∂L=∂g∂L∗∂f∂g∗∂w∂f
因为只有
g
1
g_1
g1包含
w
5
w_5
w5 所以
∂
L
∂
g
=
∂
L
∂
g
1
=
∂
(
1
2
(
y
−
g
1
)
2
+
1
2
(
y
−
g
2
)
2
)
∂
g
1
=
−
(
y
−
g
1
)
=
−
(
y
−
o
1
)
∂
g
∂
f
=
∂
1
1
+
e
f
∂
f
=
1
1
+
e
f
(
1
−
1
1
+
e
f
)
=
o
1
(
1
−
o
1
)
∂
f
∂
w
=
∂
(
h
1
∗
w
5
+
h
2
∗
w
6
)
∂
w
=
h
1
\begin{aligned} \frac{{\partial}L}{ {\partial}g} &= \frac{{\partial}L}{ {\partial}g_1}=\frac{\partial{(\frac{1}{2}(y-g_1)^2 + \frac{1}{2}(y-g_2)^2})}{\partial{g_1}}=-(y-g_1)=-(y-o_1)\\ \frac{\partial{g}}{\partial{f}} &= \frac{\partial{\frac{1}{1+e^f}}}{\partial{f}}=\frac{1}{1+e^f}(1- \frac{1}{1+e^f})=o_1(1-o_1)\\ \frac{\partial{f}}{\partial{w}} &= \frac{\partial{(h_1*w_5+h_2*w_6)}}{\partial{w}}=h_1 \end{aligned}
∂g∂L∂f∂g∂w∂f=∂g1∂L=∂g1∂(21(y−g1)2+21(y−g2)2)=−(y−g1)=−(y−o1)=∂f∂1+ef1=1+ef1(1−1+ef1)=o1(1−o1)=∂w∂(h1∗w5+h2∗w6)=h1
所以
∂
L
∂
w
=
−
(
y
−
o
1
)
∗
o
1
(
1
−
o
1
)
∗
h
1
\frac{{\partial}L}{ {\partial}w}=-(y-o_1) * o_1(1-o_1) * h_1
∂w∂L=−(y−o1)∗o1(1−o1)∗h1
而
y
、
o
1
、
h
1
y、o_1、h_1
y、o1、h1这三个变量在正向传播时已经计算出了,也就是说算到这步,我们就求出
∂
L
∂
w
\frac{\partial{L}}{\partial{w}}
∂w∂L了,然后我们把结果代到
w
∗
=
w
−
α
∂
f
∂
w
w^* = w - \alpha\frac{{\partial}f}{ {\partial}w}
w∗=w−α∂w∂f中就可以更新参数了。
3. 再谈反向传播
现在有很多人一聊起BP算法就提链式法则,忽略了反向传播的基本思想,原因可能是现在的各种神经网络参数更新都使用这种方法,但殊不知,在这个简单的思想提出前,多层感知机的参数学习一直是一个很大的问题。这个思想统治了近35年的神经网络参数更新方式。但有意思的是,前两年,做为这个算法的提出者Hinton大神,亲自提出了要推翻BP算法的想法,用Hinton的说法是(下面不是原话哈,我的理解),BP算法是不符合人脑学习规律的,人脑是从前向后一边接收信息,一边学习的,而不是到最后看到结果了才学习(更新参数),而我们的神经网络其实是模拟人脑结构的(基于神经元),但学习方法确与人脑的不符,之后如果神经网络要有大的发展,必定是舍弃BP算法,寻找到一种从前向后的学习方法。