07_4_随机梯度下降_反向传播算法&函数优化实战
多层感知机梯度(反向传播算法)
Chain rule
通过链式法则,转换为对 O K 1 O^1_K OK1和 O K 2 O^2_K OK2的求导,一个一个求解。
Multi-output Perception(多输出感知机)
对 w j k 1 w_{jk}^1 wjk1的导数只和
- 当前的相关联输出节点的值( O K O_K OK)(输出节点)
- 输入节点 x j 0 x^0_j xj0
有关。
Multi-Layer Perception
利用多输出感知机扩展成多层的感知机。意味着前面还有节点,蓝色部分不再是 x 0 x^0 x0层,而是中间的层,称之为 x j x^j xj层。对 x j x^j xj层前面遮挡,就和多输出感知机讲的一样,把 O j J O^J_j OjJ理解为 x 0 x^0 x0,导数解照样是先前一样:
δ E δ w j k = ( O k − t k ) O k ( 1 − O k ) O j J \frac{\delta E}{\delta w_{jk}} = (O_k - t_k)O_k (1-O_k)O^J_j δwjkδE=(Ok−tk)Ok(1−Ok)OjJ
这个是隐藏层的输出 O j J O^J_j OjJ,因为 x j J x^J_j xjJ还要 σ \sigma σ激活后才是下一层的输入。
现在开始推导最终的loss对倒数第2层的 w i j w_{ij} wij的公式的推导过程, δ E δ W i j \frac{\delta E}{\delta W_{ij}} δWijδE:
第一步(简化公式):
对于
(
O
k
−
t
k
)
O
k
(
1
−
O
k
)
(O_k - t_k)O_k (1-O_k)
(Ok−tk)Ok(1−Ok),我们设它为
δ
K
K
\delta_K^K
δKK,一共有K个,下标从0~K-1。
δ
E
δ
w
j
k
=
(
O
k
−
t
k
)
O
k
(
1
−
O
k
)
O
j
J
\frac{\delta E}{\delta w_{jk}} = (O_k - t_k)O_k (1-O_k)O^J_j
δwjkδE=(Ok−tk)Ok(1−Ok)OjJ
前面3个只跟
O
K
O_K
OK节点有关系,代表了
O
K
O_K
OK节点的某种属性,它是
O
K
O_K
OK和
t
K
t_K
tK的线性组合,就是一个多项式。将其命名为
δ
K
K
\delta ^K_K
δKK(delta K)。为了简化
δ
E
δ
w
j
k
\frac{\delta E}{\delta w_{jk}}
δwjkδE的公式。
=
δ
K
K
O
j
J
= \delta ^K_K O^J_j
=δKKOjJ
这一部分输出节点
O
k
O_k
Ok和label(
t
k
t_k
tk)的组合,多项式的运算,形成
δ
k
\delta_k
δk,因此对于这层上一共有K个节点的话,就有k个
δ
k
\delta _k
δk,即
[
δ
0
k
δ
1
k
δ
2
k
.
.
.
δ
K
−
1
k
]
\left[ \begin{matrix} \delta_0^k \\ \delta_1^k \\ \delta_2^k \\ ... \\ \delta_{K-1}^k \\ \end{matrix} \right]
⎣⎢⎢⎢⎢⎡δ0kδ1kδ2k...δK−1k⎦⎥⎥⎥⎥⎤
δ
K
K
\delta_K^K
δKK可以简化公式,并且直接可以通过前项计算得到,因为
O
k
O_k
Ok和
t
k
t_k
tk都是知道的。我们再取上一层
O
j
J
O^J_j
OjJ的变量,就可以直接得到矩阵的数组:
[
w
00
w
01
.
.
.
]
\left[ \begin{matrix} w_{00} w_{01}\\ ... \end{matrix} \right]
[w00w01...]
这个矩阵数组就代表了这一层的所有连接的偏微分(梯度信息),通过这个矩阵就可以直接更新这一层输出层的
w
j
k
w_{jk}
wjk。
第二步:
现在已经知道 δ E δ W K \frac{\delta E}{\delta W^K} δWKδE上每一个的偏微分,现在求 δ E δ W J \frac{\delta E}{\delta W^J} δWJδE也就是对倒数第2层的偏微分。如果知道倒数第2层是跟这一层有迭代关系的话,那么前面一层(假设 W I W^I WI)也有一种迭代关系,可以一次次迭代得到。
首先把E展开
E
W
i
j
=
δ
δ
W
i
j
1
2
∑
k
∈
K
(
O
k
−
t
k
)
2
\frac{E}{W_{ij}} = \frac{\delta}{\delta W_{ij}} \frac{1}{2} \sum_{k\in K} (O_k - t_k)^2
WijE=δWijδ21k∈K∑(Ok−tk)2
因为
O
k
O_k
Ok包含了ij的变量,因此,
=
∑
k
∈
K
(
O
k
−
t
k
)
δ
δ
W
i
j
O
k
= \sum_{k\in K} (O_k - t_k) \frac{\delta}{\delta W{ij}} O_k
=k∈K∑(Ok−tk)δWijδOk
然后继续把
O
k
O_k
Ok展开,它是
x
k
x_k
xk经过激活函数后的值,
=
∑
k
∈
K
(
O
k
−
t
k
)
δ
δ
W
i
j
δ
(
x
k
)
= \sum_{k\in K} (O_k - t_k) \frac{\delta}{\delta W{ij}} \delta(x_k)
=k∈K∑(Ok−tk)δWijδδ(xk)
将
σ
\sigma
σ展开,
=
∑
k
∈
K
(
O
k
−
t
k
)
δ
(
x
k
)
(
1
−
δ
(
x
k
)
)
δ
x
k
δ
W
i
j
= \sum_{k\in K} (O_k - t_k) \delta(x_k)(1-\delta(x_k)) \frac{\delta x_k}{\delta W{ij}}
=k∈K∑(Ok−tk)δ(xk)(1−δ(xk))δWijδxk
展开
δ
x
k
δ
W
i
j
\frac{\delta x_k}{\delta W{ij}}
δWijδxk,
x
k
K
x^K_k
xkK在黄色部分,
w
i
j
J
w^{J}_{ij}
wijJ为蓝色虚线部分。这里是使用链式法则的核心部分。
Wij先变成中间变量Oj,再变成xk,因此引进中间变量,
=
∑
k
∈
K
(
O
k
−
t
k
)
O
k
(
1
−
O
k
)
δ
x
k
δ
O
j
δ
O
j
δ
W
i
j
= \sum_{k\in K} (O_k - t_k) O_k(1-O_k) \frac{\delta x_k}{\delta O_j} \frac{\delta O_j}{\delta W_{ij}}
=k∈K∑(Ok−tk)Ok(1−Ok)δOjδxkδWijδOj
因此先从xk跳到Oj再跳到wij。
看图,j是k的前一行。
δ
x
k
δ
O
j
\frac{\delta x_k}{\delta O_j}
δOjδxk,
x
k
=
∑
O
i
W
i
k
i
∈
[
0
,
j
]
x_k = \sum O_i W_{ik} \quad i\in [0,j]
xk=∑OiWiki∈[0,j],只有i=j的时候,这两个链接才有直接的关系,因此
δ
x
k
δ
O
j
=
w
j
k
\frac{\delta x_k}{\delta O_j} = w_{jk}
δOjδxk=wjk
=
∑
k
∈
K
(
O
k
−
t
k
)
O
k
(
1
−
O
k
)
W
j
k
δ
O
j
δ
W
i
j
= \sum_{k\in K} (O_k - t_k) O_k(1-O_k) W_{jk} \frac{\delta O_j}{\delta W_{ij}}
=k∈K∑(Ok−tk)Ok(1−Ok)WjkδWijδOj
现在求
δ
O
j
δ
W
i
j
\frac{\delta O_j}{\delta W_{ij}}
δWijδOj,因为
O
j
O_j
Oj是
W
i
j
W_{ij}
Wij的线性求和,把
σ
\sigma
σ写出来,
把
δ
O
j
δ
W
i
j
\frac{\delta O_j}{\delta W_{ij}}
δWijδOj先提到之前来,后面的部分
∑
k
∈
K
(
O
k
−
t
k
)
O
k
(
1
−
O
k
)
W
j
k
\sum_{k\in K} (O_k - t_k) O_k(1-O_k) W_{jk}
∑k∈K(Ok−tk)Ok(1−Ok)Wjk表示前面的一些属性,也就是黄色部分的属性,
=
δ
O
j
δ
W
i
j
∑
k
∈
K
(
O
k
−
t
k
)
O
k
(
1
−
O
k
)
W
j
k
= \frac{\delta O_j}{\delta W_{ij}} \sum_{k\in K} (O_k - t_k) O_k(1-O_k) W_{jk}
=δWijδOjk∈K∑(Ok−tk)Ok(1−Ok)Wjk
求
δ
O
j
δ
W
i
j
\frac{\delta O_j}{\delta W_{ij}}
δWijδOj,因为
O
j
O_j
Oj是
W
i
j
W_{ij}
Wij的线性求和,经过了
σ
\sigma
σ激活函数,因此变成
=
O
j
(
1
−
O
j
)
δ
x
j
δ
W
i
j
∑
k
∈
K
(
O
k
−
t
k
)
O
k
(
1
−
O
k
)
W
j
k
= O_j (1-O_j) \frac{\delta x_j}{\delta W_{ij}} \sum_{k\in K} (O_k - t_k) O_k(1-O_k) W_{jk}
=Oj(1−Oj)δWijδxjk∈K∑(Ok−tk)Ok(1−Ok)Wjk
$\frac{\delta x_j}{\delta W_{ij}}
的
偏
微
分
等
于
的偏微分等于
的偏微分等于O_i$。
所以,最终会得到,
=
O
j
(
1
−
O
j
)
O
i
∑
k
∈
K
(
O
k
−
t
k
)
O
k
(
1
−
O
k
)
W
j
k
= O_j (1-O_j) \quad O_i \quad \sum_{k\in K} (O_k - t_k) O_k(1-O_k) W_{jk}
=Oj(1−Oj)Oik∈K∑(Ok−tk)Ok(1−Ok)Wjk
首先对
W
i
j
W_{ij}
Wij的求导,会跟前面的节点相关,叫
O
i
O_i
Oi;也跟后面的节点有关,叫
O
j
O_j
Oj;还有k,也就是之前的,所有的
δ
k
、
W
j
k
\delta_k 、 W_{jk}
δk、Wjk有关系。
简写:
δ
E
δ
W
i
j
=
O
i
O
j
(
1
−
O
j
)
∑
k
∈
K
δ
k
W
j
k
\frac{\delta E}{\delta W_{ij}}= O_i O_j (1-O_j) \sum_{k\in K} \delta_k W_{jk}
δWijδE=OiOj(1−Oj)k∈K∑δkWjk
把式子和前面的W、 δ k \delta_k δk关联起来:
首先,如果只有黄色的这一层的话,我们已经推导出:
δ E δ w j k = ( O k − t k ) O k ( 1 − O k ) O j J \frac{\delta E}{\delta w_{jk}} = (O_k - t_k)O_k (1-O_k)O^J_j δwjkδE=(Ok−tk)Ok(1−Ok)OjJ
δ E δ w j k = δ k K O j J \frac{\delta E}{\delta w_{jk}} = \delta^K_k O^J_j δwjkδE=δkKOjJ
也就是 W j k W_{jk} Wjk的表达式只取决于输出(也是输入) O j J O^J_j OjJ和黄色部分的 δ k \delta_k δk。
现在打出前面的层,对前面的层求导,之前已经推导了,为:
δ E δ W i j = O i O j ( 1 − O j ) ∑ k ∈ K ( O k − t k ) O k ( 1 − O k ) W j k \frac{\delta E}{\delta W_{ij}} = O_i \quad O_j (1-O_j) \quad \sum_{k\in K} (O_k - t_k) O_k(1-O_k) W_{jk} δWijδE=OiOj(1−Oj)∑k∈K(Ok−tk)Ok(1−Ok)Wjk
第1段是灰色点的输入,第2段是蓝色(中间层)的输出,第3段是 δ k \delta_k δk的求和。因为把 ( O k − t k ) O k (O_k - t_k)O_k (Ok−tk)Ok叫做 δ k \delta_k δk, W j k W_{jk} Wjk只和 O j J O^J_j OjJ和 δ k \delta_k δk有关。由 δ E δ w j k \frac{\delta E}{\delta w_{jk}} δwjkδE的类比,可以把 δ E W i j = O i O j ( 1 − O j ) ∑ k ∈ K δ k W j k \frac{\delta E}{W_{ij}} = O_i \quad O_j (1-O_j) \quad \sum_{k\in K} \delta_k W_{jk} WijδE=OiOj(1−Oj)∑k∈KδkWjk的第2、3部分看做 δ j J \delta^J_j δjJ,它代表了这个梯度推导公式所有之前的信息,也就是当前层到最后一层(往右)的信息。
δ j J = O j ( 1 − O j ) ∑ k ∈ K δ k W j k \delta^J_j =O_j (1-O_j) \sum_{k\in K} \delta_k W_{jk} δjJ=Oj(1−Oj)∑k∈KδkWjk
总结:
δ k \delta_k δk定义为从当前节点(k层节点)开始,到最终输出层的梯度的传导信息。只要拿到了 δ k \delta_k δk的信息,再获得 O j O_j Oj就可以直接 δ E δ W j k = O j ∗ δ k \frac{\delta E}{\delta W_{jk}}= O_j * \delta_k δWjkδE=Oj∗δk。
同样,计算中间层,只需要 δ j \delta_j δj,再得到上一层输出 O i O_i Oi,因此 δ E δ W i j = O i ∗ δ j \frac{\delta E}{\delta W_{ij}}= O_i * \delta_j δWijδE=Oi∗δj, δ j \delta_j δj是当前节点的输出*(乘)上一层 δ k \delta_k δk和 W j k W_{jk} Wjk的式子。
这是一个迭代的过程,对于输出层 δ k \delta_k δk可以直接求导,上一层的 δ j \delta_j δj也可以一次求出, δ j = O j ( 1 − O j ) ∑ k ∈ K δ k W j k \delta_j = O_j(1-O_j) \sum_{k\in K} \delta_k W_{jk} δj=Oj(1−Oj)∑k∈KδkWjk,参数都已知。那么,前面的 δ i \delta_i δi、 δ n \delta_n δn……都可以求出。
就是先求出k层,再往前j,再往前i,再往前……
形象表示:先看输出层 δ k \delta_k δk以及更新的梯度 w j k w_{jk} wjk……
Himmelblau函数优化(实战)
函数数学表达式:
f ( x , y ) = ( x 2 + y − 11 ) + ( x + y 2 − 7 ) 2 f(x,y) = (x^2+y-11) + (x+y^2-7)^2 f(x,y)=(x2+y−11)+(x+y2−7)2
图形如下,4个角的最小值都是0
Minima(极小值点)
测试优化算法:
- 能不能找到最小值的解
- 参数的敏感性,不同的初始点会不会影响搜索的结果
Plot(画图)
函数的绘制,
#并行地生成一系列的坐标点,tf和np的meshgrid类似
X, Y = np.meshgrid(x,y)
Gradient Descent
求极小值,
具体实现
import numpy as np
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import pyplot as plt
import tensorflow as tf
def himmelblau(x):
return (x[0] ** 2 + x[1] - 11) ** 2 + (x[0] + x[1] ** 2 -7) ** 2
x = np.arange(-6,6,0.1)
y = np.arange(-6,6,0.1)
print('x y range:',x.shape,y.shape)
#并行地生成一系列的坐标点,tf和np的meshgrid类似
X, Y = np.meshgrid(x,y)
print('X,Y maps:',X.shape,Y.shape)
Z = himmelblau([X,Y])
fig = plt.figure('himmelblau')
ax = fig.gca(projection='3d')
ax.plot_surface(X,Y,Z)
ax.view_init(60,-30)
ax.set_xlabel('x')
ax.set_ylabel('y')
plt.show()
# 参数的初始化值对优化的影响不容忽视,可以通过尝试不同的初始化值,
# 检验函数优化的极小值情况
# [1., 0.], [-4, 0.], [4, 0.]
x = tf.constant([4., 0.])
# x = tf.constant([1., 0.])
# x = tf.constant([-4., 0.])
# x = tf.constant([-2,2])
for step in range(200):# 循环优化
with tf.GradientTape() as tape: #梯度跟踪
tape.watch([x]) # 记录梯度
y = himmelblau(x) # 前向传播
# 反向传播
#这里猜测返回的应该是列表,因此要取[0]
grads = tape.gradient(y,[x])[0]
# 更新参数,0.01为学习率
x -= 0.01 * grads
# 打印优化的极小值
if step % 20 == 19:
print('step {}: x = {}, f(x) = {}'
.format(step,x.numpy(),y.numpy()))
结果
不同的初始点,会有不同的结果