神经网络的一种求解W的算法,分为信号“正向传播(FP)”求损失,“反向传播(BP)”回传误差;根据误差值修改每层的权重,继续迭代。
BP算法也叫做δ算法。以三层的感知器为例(假定现在隐层和输出层均存在相同类型的激活函数)
- 隐层 y = f(x * v)
- 输出层 o = f(f(y) * w)
- 输入层误差:
- 隐层误差:
- 输入层误差:
误差E有了,那么为了使误差越来越小,可以采用随机梯度下降的方式进行ω和υ的求解,即求得ω和υ使得误差E最小
BP算法的例子
- 初始值:w(0.1,0.15,0.2,0.25,0.3,0.35,0.4,0.45,0.5,0.55,0.6,0.65), b(0.35,0.65)
- 输出值:O=(0.01,0.99)
- 学习率:η=0.5
- 假设隐层和输出层都使用 sigmoid 激活函数
1、FP过程
先求out
同理可以得到:
同理可以得到:
输出层误差表示如下:
2、BP 过程
输出层到第二层隐层,以求 为例:
下面我们分别求上式的三个部分,其中第一部分:
第二分部因为:
第三部分,因为:
最终得到:
更新 的值:
同理可以求出:
第二层隐层到第一层隐层,以求 为例:
下面我们分别计算,第一部分:
其中:
注意:这里由于是反向传播,此时要用到之前更新后的 的值
同理计算:
接着计算第二部分:
接着计算第三部分:
最终整合起来:
于是更新 :
同理求出:
以上是第一次迭代,经过多次迭代,最终的误差会越来越小
上图可以看出,当迭代1000次时,输出为 O=(0.022971,0.977675) 和原本的 O=(0.01,0.99) 比较接近了。
python代码
https://github.com/flepeng/code/blob/master/DL/bp_demo.py
import numpy as np# 初始值
w = [0.1, 0.15, 0.2, 0.25, 0.3, 0.35, 0.4, 0.45, 0.5, 0.55, 0.6, 0.65]
# 偏置项b不进行更新
b = [0.35, 0.65]l = [5, 10]# sigmoid函数
def sigmoid(z):return 1.0 / (1 + np.exp(-z))def f1(w, b, l):# 前向传播,计算结果值h1 = sigmoid(w[0] * l[0] + w[1] * l[1] + b[0])h2 = sigmoid(w[2] * l[0] + w[3] * l[1] + b[0])h3 = sigmoid(w[4] * l[0] + w[5] * l[1] + b[0])o1 = sigmoid(w[6] * h1 + w[8] * h2 + w[10] * h3 + b[1])o2 = sigmoid(w[7] * h1 + w[9] * h2 + w[11] * h3 + b[1])# 后向传播,更新w# 输出层到第二层隐层,前两项# 公式中的第一部分-(0.01 - o1),第二部分o1 * (l - o1)t1 = -(0.01 - o1) * o1 * (l - o1)# 第二层隐层到第一层隐层,前两项t2 = -(0.99 - o2) * o2 * (l - o2)# t1*第三部分,即输出层到第二层隐层的参数梯度w[6] = w[6] - 0.5 * (t1 * h1)w[8] = w[8] - 0.5 * (t1 * h2)w[10] = w[10] - 0.5 * (t1 * h3)w[7] = w[7] - 0.5 * (t2 * h1)w[9] = w[9] - 0.5 * (t2 * h2)w[11] = w[11] - 0.5 * (t2 * h3)# (t1 * w[6] + t2 * w[7])对于公式()中的两项,h1 * (1 - h1)对于第二项,l[0]对应第三项w[0] = w[0] - 0.5 * (t1 * w[6] + t2 * w[7]) * h1 * (1 - h1) * l[0]w[1] = w[1] - 0.5 * (t1 * w[6] + t2 * w[7]) * h1 * (1 - h1) * l[1]w[2] = w[2] - 0.5 * (t1 * w[8] + t2 * w[9]) * h2 * (1 - h2) * l[0]w[3] = w[3] - 0.5 * (t1 * w[6] + t2 * w[9]) * h2 * (1 - h2) * l[1]w[4] = w[4] - 0.5 * (t1 * w[10] + t2 * w[11]) * h3 * (1 - h3) * l[0]w[5] = w[5] - 0.5 * (t1 * w[10] + t2 * w[11]) * h3 * (1 - h3) * l[1]return o1, o2, wfor i in range(1000):r1, r2, w = f1(w, b, l)print("第{}次迭代后,结果值为:({},{}),权重更新为:{}".format(i+1, r1, r2, w))