BP算法为深度学习中参数更新的重要角色,一般基于loss对参数的偏导进行更新。

一些根据均方误差,每层默认激活函数sigmoid(不同激活函数,则更新公式不一样)

假设网络如图所示:

则更新公式为:

以上列举了最后2层的参数更新方式,第一层的更新公式类似,即上一层的误差来自于下一层所有的神经元,e的更新就是不断建立在旧的e上(这里g可以当做初始的e)

下面上代码:

1,BP算法

# 手写BP算法
import numpy as np # 先更新参数,再继续传播
# layers:包括从输入层到输出层,每层参数为:连接权重w,阈值b,输出y。类型为np.array
# 对于输入层,w和b随便是啥,反正不用,只需y即原始输入
# 基于激活函数sigmoid
# loss为均方误差
def bp(layers,labels,lr=0.001):
# 翻转layers,反向传播
reversed_layers=layers[::-1]
# 输出层
output_w,output_b,output_y=reversed_layers[0]
g=np.array([output_y[j]*(1-output_y[j])*(labels[j]-output_y[j]) for j in range(len(labels))])
# 最后一层更新较为特殊,先进行更新
delta_w=np.empty(shape=(output_w.shape[0],output_w.shape[1]))
# 上一层输出y
last_y=reversed_layers[1][2]
for h in range(output_w.shape[0]):
for j in range(output_w.shape[1]):
delta_w[h,j]=lr*g[j]*last_y[h]
delta_b=-lr*g
new_w=output_w+delta_w
new_b=output_b+delta_b
reversed_layers[0][0]=new_w
reversed_layers[0][1]=new_b # 从倒数第二层到第二层进行更新,每次取3层进行计算,由公式知,需用到上一层输出即下一层权重
for i in range(1,len(reversed_layers)-1):
# 下一层w
next_w=reversed_layers[i-1][0]
out_w,out_b,out_y=reversed_layers[i]
# 上一层y
last_y=reversed_layers[i+1][2]
# 更新辅助量,意思即上一层每个神经元的误差都由下一层所有神经元的误差反向传播,体现在这里内循环
e=np.empty(shape=(len(out_b),1))
for h in range(len(out_b)):
temp=0
for j in range(next_w.shape[1]):
temp+=next_w[h,j]*g[j]
e[h]=out_y[h]*(1-out_y[h])*temp
delta_w=np.empty(shape=(out_w.shape[0],out_w.shape[1]))
for h in range(out_w.shape[0]):
for j in range(out_w.shape[1]):
delta_w[h,j]=lr*e[j]*last_y[h]
delta_b=-lr*e
out_new_w=out_w+delta_w
out_new_b=out_b+delta_b
reversed_layers[i][0]=out_new_w
reversed_layers[i][1]=out_new_b
g=np.copy(e)
return layers

以上假设每个神经元的输出为一个实数y值

2,构建测试

构建平面上的点(x,y),将y是否大于0作为划分,进行训练。只使用了一层网络,sigmoid激活

X=[]
Y=[]
for i in range(-100,100):
for j in range(-100,100):
X.append([[i],[j]])
if j>=0:
Y.append([1])
else:
Y.append([0])
X=np.array(X)
Y=np.array(Y)

3,划分训练,验证集

indexs=np.random.choice(range(40000),size=30000)

x_train=np.array([X[i] for i in indexs])
y_train=np.array([Y[i] for i in indexs]) x_val=np.array([X[i] for i in np.setdiff1d(range(40000),indexs))
y_val=np.array([Y[i] for i in np.setdiff1d(range(40000),indexs))

4,训练。这里只对所有样本训练了一轮。使用随机初始化的w和b,每个样本都会改变w和b

# 使用sigmoid激活函数
def output(input_x,w,b):
res=0
t=np.matmul(np.transpose(w),input_x)-b
return 1./(1+np.power(np.e,-t)) w1=np.random.normal(size=(2,1))
b1=np.array([[0]])
for i in range(len(x_train)):
y0=x_train[i]
l=y_train[i]
input_layers=[]
w0,b0=(0,0)
input_layers.append([w0,b0,y0])
input_layers.append([w1,b1,output(y0,w1,b1)])
input_layers=bp(input_layers,l)
w1=input_layers[1][0]
b1=input_layers[1][1] # w: [[0.11213777]
# [1.67425498]]
# b: [[0.0001581]]
print('w: ',w1)
print('b: ',b1)

5,验证。从分出的验证集选取部分验证即可

for xx in x_val[:50]:
print(xx.reshape((2,)),output(xx,w1,b1).reshape((1,)))

验证结果如下:

[63 68] [1.]
[-100 -99] [1.39636722e-77]
[-100 -98] [7.44936654e-77]
[63 69] [1.]
[-100 -96] [2.12011171e-75]
[-100 -94] [6.03390049e-74]
[-100 -93] [3.21897678e-73]
[63 74] [1.]
[-100 -91] [9.16130293e-72]
[63 75] [1.]
[63 76] [1.]
[63 77] [1.]
[63 78] [1.]
[-100 -86] [3.95872874e-68]
[-100 -85] [2.11191018e-67]
[63 79] [1.]
[-100 -83] [6.01055872e-66]
[-100 -82] [3.20652436e-65]
[63 82] [1.]
[-100 -80] [9.12586299e-64]
[-100 -79] [4.86848285e-63]
[63 83] [1.]
[-100 -77] [1.38558459e-61]
[-100 -76] [7.39184317e-61]
[63 89] [1.]
[-100 -74] [2.10374039e-59]
[63 91] [1.]
[-100 -72] [5.98730724e-58]
[-100 -71] [3.19412012e-57]
[-100 -70] [1.70400531e-56]
[-100 -69] [9.09056014e-56]
[-100 -68] [4.84964942e-55]
[-100 -67] [2.58720025e-54]
[-100 -66] [1.38022454e-53]
[63 99] [1.]
[-100 -64] [3.92815978e-52]
[-100 -63] [2.09560219e-51]
[ 64 -100] [2.53988133e-70]
[-100 -61] [5.9641457e-50]
[ 64 -97] [3.85631522e-68]
[ 64 -96] [2.05727442e-67]
[-100 -58] [9.05539386e-48]
[ 64 -90] [4.74253371e-63]
[ 64 -89] [2.53005596e-62]
[ 64 -87] [7.20061393e-61]
[-100 -52] [2.08749548e-43]
[ 64 -84] [1.09327301e-58]
[-100 -50] [5.94107377e-42]
[ 95 -13] [1.49260907e-05]
[-100 -45] [2.56722211e-38]

6,总结:可以看出,这50个验证样本上都没问题,虽然想到的测试方案有点low,但一时找不到啥好数据。由此验证BP算法的正确性。如有可疑或不足之处,敬请告知。

手写BP(反向传播)算法的更多相关文章

  1. 机器学习 —— 基础整理(七)前馈神经网络的BP反向传播算法步骤整理

    这里把按 [1] 推导的BP算法(Backpropagation)步骤整理一下.突然想整理这个的原因是知乎上看到了一个帅呆了的求矩阵微分的方法(也就是 [2]),不得不感叹作者的功力.[1] 中直接使 ...

  2. 【深度学习】BP反向传播算法Python简单实现

    转载:火烫火烫的 个人觉得BP反向传播是深度学习的一个基础,所以很有必要把反向传播算法好好学一下 得益于一步一步弄懂反向传播的例子这篇文章,给出一个例子来说明反向传播 不过是英文的,如果你感觉不好阅读 ...

  3. 手推机器学习公式(一) —— BP 反向传播算法

    方便起见,本文仅以三层的神经网络举例. f(⋅):表示激励函数 xi:表示输入层: yj:表示中间的隐层: yj=f(netj) netj=∑i=0nvijxi ok:表示输出层,dk 则表示期望输出 ...

  4. BP反向传播算法的工作原理How the backpropagation algorithm works

    In the last chapter we saw how neural networks can learn their weights and biases using the gradient ...

  5. 神经网络训练中的Tricks之高效BP(反向传播算法)

    神经网络训练中的Tricks之高效BP(反向传播算法) 神经网络训练中的Tricks之高效BP(反向传播算法) zouxy09@qq.com http://blog.csdn.net/zouxy09 ...

  6. 深度神经网络(DNN)反向传播算法(BP)

    在深度神经网络(DNN)模型与前向传播算法中,我们对DNN的模型和前向传播算法做了总结,这里我们更进一步,对DNN的反向传播算法(Back Propagation,BP)做一个总结. 1. DNN反向 ...

  7. 神经网络之反向传播算法(BP)公式推导(超详细)

    反向传播算法详细推导 反向传播(英语:Backpropagation,缩写为BP)是"误差反向传播"的简称,是一种与最优化方法(如梯度下降法)结合使用的,用来训练人工神经网络的常见 ...

  8. 稀疏自动编码之反向传播算法(BP)

    假设给定m个训练样本的训练集,用梯度下降法训练一个神经网络,对于单个训练样本(x,y),定义该样本的损失函数: 那么整个训练集的损失函数定义如下: 第一项是所有样本的方差的均值.第二项是一个归一化项( ...

  9. 【机器学习】反向传播算法 BP

    知识回顾 1:首先引入一些便于稍后讨论的新标记方法: 假设神经网络的训练样本有m个,每个包含一组输入x和一组输出信号y,L表示神经网络的层数,S表示每层输入的神经元的个数,SL代表最后一层中处理的单元 ...

随机推荐

  1. graphviz 决策树绘图中文乱码解决方法

    1.修改graphviz配置文件 <dir>C:\WINDOWS\Fonts</dir> 更改为 <dir>~/.fonts</dir> 2.将决策树d ...

  2. 关于python-selenium-chromedriver提示

    问题一:AttributeError: module 'selenium.webdriver' has no attribute 'Chromedriver' 配置selenium环境时,执行代码 f ...

  3. Java基础-自增自减运算符练习题

    我们用一个简单的例子分析下边的运行结果: package demo; public class ZiZeng { int i = 0; test(i); // i = i++; i = ++i; Sy ...

  4. maven项目创建3 (依赖版本冲突)

    调节原则 1 路径近者优先原则 自己添加一个想要依赖的版本 2第一声明者优先原则 谁排在前面就用谁的 以上两种统称为 调节原则 排除原则 排除自己的不想要的版本 版本锁定 谁能够提供锁定的版本,就用谁 ...

  5. [VIJOS2053][SDOI2019]世界地图:最小生成树+虚树

    分析 可以发现第一列和最后一列永远不会被删除,于是我们可以想到维护前后缀最小生成树,但是直接维护的话显然时间空间两爆炸.(通过上网找题解)可以发现我们关心的只是最左边和最右边两列,而不关心内部的连边情 ...

  6. 原生Js_制作简易日历

    javascript制作简易日历,月份信息已经放在一个数组中,在<script>...</script>中编写代码实现其功能 实现步骤 a) 获取需要操作的dom对象 b) 在 ...

  7. 分布式-网络通信-NIO

    目录:一.java NIO 和阻塞I/O的区别     1. 阻塞I/O通信模型     2. java NIO原理及通信模型二.java NIO服务端和客户端代码实现 一.java NIO 和阻塞I ...

  8. Concurrent包里的其他东西:ArrayBlockingQueue、CountDownLatch等等。

    1:本例介绍一个特殊的队列:BlockingQueue,如果BlockingQueue是空的,从BlockingQueue取东西的操作将会被阻断进入等待状态,直到BlockingQueue进了东西才会 ...

  9. 套接字之send系统调用

    send系统调用只是对sendto系统调用进行了封装,传递的参数不包含目的地址信息,数据会发送到已经建立连接的另一端的地址: /* * Send a datagram down a socket. * ...

  10. 布尔 kotlin(4)

    布尔布尔用 Boolean 类型表示,它有两个值: true 和 false .若需要可空引用布尔会被装箱.内置的布尔运算有:||       – 短路逻辑或&&     – 短路逻辑 ...