BP神经网络原理

经典的BP神经网络通常由三层组成: 输入层, 隐含层与输出层.通常输入层神经元的个数与特征数相关,输出层的个数与类别数相同, 隐含层的层数与神经元数均可以自定义.

每个神经元代表对数据的一次处理:

每个隐含层和输出层神经元输出与输入的函数关系为:

其中Wij表示神经元i与神经元j之间连接的权重,Oj代表神经元j的输出, sigmod是一个特殊的函数用于将任意实数映射到(0,1)区间.

上文中的sigmod函数称为神经元的激励函数(activation function), 除了sigmod函数1/1+e^-IL外, 常用还有tanh和ReLU函数.

我们用一个完成训练的神经网络处理回归问题, 每个样本拥有n个输入.相应地,神经网络拥有n个输入神经元和1个输出神经元.

实际应用中我们通常在输入层额外增加一个偏置神经元, 提供一个可控的输入修正;或者为每个隐含层神经元设置一个偏置参数.

我们将n个特征依次送入输入神经元, 隐含层神经元获得输入层的输出并计算自己输出值, 输出层的神经元根据隐含层输出计算出回归值.

上述过程一般称为前馈(Feed-Forward)过程, 该过程中神经网络的输入输出与多维函数无异.

现在我们的问题是如何训练这个神经网络.

作为监督学习算法,BP神经网络的训练过程即是根据前馈得到的预测值和参考值比较, 根据误差调整连接权重Wij的过程.

训练过程称为反向传播过程(BackPropagation), 数据流正好与前馈过程相反.

首先我们随机初始化连接权重Wij, 对某一训练样本进行一次前馈过程得到各神经元的输出.

首先计算输出层的误差:

Ej=sigmod′(Oj)∗(Tj−Oj)=Oj(1−Oj)(Tj−Oj)

其中Ej代表神经元j的误差,Oj表示神经元j的输出, Tj表示当前训练样本的参考输出, sigmod′(x)是上文sigmod函数的一阶导数.


计算隐含层误差:

Ej=sigmod′(Oj)∗∑kEkWjk=Oj(1−Oj)∑kEkWjk

隐含层输出不存在参考值, 使用下一层误差的加权和代替(Tj−Oj).

计算完误差后就可以更新Wij和θj:

Wij=Wij+λEjOi

其中λ是一个称为学习率的参数,一般在(0,0.1)区间上取值.

实际上为了加快学习的效率我们引入称为矫正矩阵的机制, 矫正矩阵记录上一次反向传播过程中的EjOi值, 这样Wj更新公式变为:

Wij=Wij+λEjOi+μCij

μ是一个称为矫正率的参数.随后更新矫正矩阵:

Cij=EjOi

每一个训练样本都会更新一次整个网络的参数.我们需要额外设置训练终止的条件.

最简单的训练终止条件为设置最大迭代次数, 如将数据集迭代1000次后终止训练.

单纯的设置最大迭代次数不能保证训练结果的精确度, 更好的办法是使用损失函数(loss function)作为终止训练的依据.

损失函数可以选用输出层各节点的方差:

L=∑j(Tj−Oj)2

为了避免神经网络进行无意义的迭代, 我们通常在训练数据集中抽出一部分用作校验.当预测误差高于阈值时提前终止训练.

Python实现BP神经网络

首先实现几个工具函数:

def rand(a, b):return (b - a) * random.random() + adef make_matrix(m, n, fill=0.0):  # 创造一个指定大小的矩阵mat = []for i in range(m):mat.append([fill] * n)return mat

定义sigmod函数和它的导数:

def sigmoid(x):return 1.0 / (1.0 + math.exp(-x))def sigmod_derivate(x):return x * (1 - x)

定义BPNeuralNetwork类, 使用三个列表维护输入层,隐含层和输出层神经元, 列表中的元素代表对应神经元当前的输出值.使用两个二维列表以邻接矩阵的形式维护输入层与隐含层, 隐含层与输出层之间的连接权值, 通过同样的形式保存矫正矩阵.

定义setup方法初始化神经网络:

    def setup(self, ni, nh, no):self.input_n = ni + 1  # 因为需要多加一个偏置神经元,提供一个可控的输入修正self.hidden_n = nhself.output_n = no# 初始化神经元self.input_cells = self.input_n * [1.0]self.hidden_cells = self.hidden_n * [1.0]self.output_cells = self.output_n * [1.0]# 初始化权重矩阵self.input_weights = make_matrix(self.input_n, self.hidden_n)self.output_weights = make_matrix(self.hidden_n, self.output_n)# 权重矩阵随机激活for i in range(self.input_n):for h in range(self.hidden_n):self.input_weights[i][h] = rand(-0.2, 0.2)for h in range(self.hidden_n):for o in range(self.output_n):self.output_weights[h][o] = rand(-0.2, 0.2)# 初始化矫正矩阵self.input_correction = make_matrix(self.input_n, self.hidden_n)self.output_correction = make_matrix(self.hidden_n, self.output_n)

定义predict方法进行一次前馈, 并返回输出:

    def predict(self, inputs):# 激活输入层for i in range(self.input_n - 1):self.input_cells[i] = inputs[i]# 激活隐藏层for j in range(self.hidden_n):total = 0.0for i in range(self.input_n):total += self.input_cells[i] * self.input_weights[i][j]self.hidden_cells[j] = sigmoid(total)for k in range(self.output_n):total = 0.0for j in range(self.hidden_n):total += self.hidden_cells[j] * self.output_weights[j][k]self.output_cells[k] = sigmoid(total)return self.output_cells[:]

定义back_propagate方法定义一次反向传播和更新权值的过程, 并返回最终预测误差:

    def back_propagate(self, case, label, learn, correct):# 前馈self.predict(case)# 获取输出层误差output_deltas = [0.0] * self.output_nfor o in range(self.output_n):error = label[o] - self.output_cells[o]output_deltas[o] = sigmod_derivate(self.output_cells[o]) * error# 获取隐藏层误差hidden_deltas = [0.0] * self.hidden_nfor h in range(self.hidden_n):error = 0.0for o in range(self.output_n):error += output_deltas[o] * self.output_weights[h][o]hidden_deltas[h] = sigmod_derivate(self.hidden_cells[h]) * error# 更新输出权重for h in range(self.hidden_n):for o in range(self.output_n):# Wij=Wij+λEjOi+μCijchange = output_deltas[o] * self.hidden_cells[h]self.output_weights[h][o] += learn * change + correct * self.output_correction[h][o]# 更新输入权重for i in range(self.input_n):for h in range(self.hidden_n):# Wij=Wij+λEjOi+μCijchange = hidden_deltas[h] * self.input_cells[i]self.input_weights[i][h] += learn * change + correct * self.input_correction[i][h]self.input_correction[i][h] = change# 获取全局误差error = 0.0for o in range(len(label)):error += 0.5 * (label[o] - self.output_cells[o]) ** 2return error

定义train方法控制迭代, 该方法可以修改最大迭代次数, 学习率λ, 矫正率μ三个参数.

    def train(self, cases, labels, limit=10000, learn=0.05, correct=0.1):for i in range(limit):error = 0.0for i in range(len(cases)):label = labels[i]case = cases[i]error += self.back_propagate(case, label, learn, correct)

编写test方法,演示如何使用神经网络学习异或逻辑:

def test(self):cases = [[0, 0],[0, 1],[1, 0],[1, 1],]labels = [[0], [1], [1], [0]]self.setup(2, 5, 1)  # 设置各层的神经元数量self.train(cases, labels, 10000, 0.5, 0.1)for case in cases:print(self.predict(case))

运行结果:

总结

BP神经网络的理解主要难点在于各层误差和权重的更新上面,涉及到一系列数学公式,只要把数学公式弄懂就会理解代码为什么这样做.

BP神经网络原理及实现相关推荐

  1. 深度学习(神经网络) —— BP神经网络原理推导及python实现

    深度学习(神经网络) -- BP神经网络原理推导及python实现 摘要 (一)BP神经网络简介 1.神经网络权值调整的一般形式为: 2.BP神经网络中关于学习信号的求取方法: (二)BP神经网络原理 ...

  2. BP神经网络原理简单介绍以及公式推导(矩阵形式和分量形式)

    BP神经网络原理简单介绍以及公式推导 标签(空格分隔): 神经网络 \def\net(#1){net^{(#1)}} \def\Y(#1){Y^{(#1)}} \def\part(#1){\parti ...

  3. bp神经网络原理 实现过程,BP神经网络的实现包括

    1.BP神经网络原理 人工神经网络有很多模型,但是日前应用最广.基本思想最直观.最容易被理解的是多层前馈神经网络及误差逆传播学习算法(Error Back-Prooaeation),简称为BP网络. ...

  4. BP神经网络原理及Matlab实现(Back Propagation Neural Networks,BPNN)

    BP神经网络原理及matlab实现 一.简介 1.BP 神经网络的信息处理方式的特点 2.BP神经网络的主要功能 二.神经网络的训练 1.神经网络拓扑结构(隐含层)的确定 2.网络的初始连接权值 3. ...

  5. BP神经网络原理分析及c++代码实现(下)

    本部分主要是BP神经网络的C++代码部分,在这里简单的介绍下代码的头文件,具体代码的实现以及测试数据,请在csdn资源里下载:http://download.csdn.net/detail/hjkhj ...

  6. BP神经网络原理及其应用,bp神经网络的工作原理

    1.BP神经网络的工作原理 人工神经网络就是模拟人思维的第二种方式.这是一个非线性动力学系统,其特色在于信息的分布式存储和并行协同处理.虽然单个神经元的结构极其简单,功能有限,但大量神经元构成的网络系 ...

  7. BP神经网络原理与异或实例分析

    文章目录 BP神经网络原理介绍 一.BP神经网络算法原理是什么? 二.激活函数 1.激活函数作用 三.BP神经网络异或实例分析 1.问题: 2.分析: 3.代码 总结 BP神经网络原理介绍 BP神经网 ...

  8. bp神经网络原理 实现过程,BP神经网络的基本思想

    BP神经网络原理 人工神经网络有很多模型,但是日前应用最广.基本思想最直观.最容易被理解的是多层前馈神经网络及误差逆传播学习算法(ErrorBack-Prooaeation),简称为BP网络. 在19 ...

  9. BP神经网络原理(附实验程序)

    1. 人工神经网络 1.1 原理 人工神经网络(Artificial Neural Networks,ANN)也简称为神经网络(NN),它是一种模仿动物神经网络行为特征,进行分布式并行信息处理的算法数 ...

最新文章

  1. 疯狂kotlin讲义连载之运算符和表达式——区间运算符
  2. 测试opencv-CUDA是否安装成功简单程序
  3. GPU编程语言选择(OpenCL、CUDA 与C++ AMP)
  4. Android 使用自带的HttpClient进行https请求出现403的解决过程记录
  5. 【软考】 2019年上半年软件设计师考试上午真题(专业解析+参考答案)
  6. GridView的 使用
  7. Adding Applications for JavaScript Storefronts in SAP 电商云
  8. E06-libcrypto.so.10 遗失的解决办法
  9. perl hash array 嵌套 push
  10. Spring技术原理之Bean生命周期
  11. 构建jQuery对象(转)
  12. Android.mk小结
  13. Halcon教程系列/启蒙----(1)初识Halcon
  14. 因为计算机中丢失lua.dll,lua51.dll丢失修复
  15. java叠加两张png带透明图片
  16. 【Python3语法】两个一维list列表合并为一个二维list
  17. 两条直线的交点(叉积)
  18. fushare(python3)
  19. hpcmpmgr.exe
  20. waves效果器_硬核科普 | 三根弹簧让你链接宇宙的混响效果器?!

热门文章

  1. Spark安全威胁及建模方法
  2. python日常工作_如何用 Python 简化你的日常工作
  3. 女性移动用户的现状和特征
  4. 如何将html转换为wmv,[转]Html中添加.wmv视频文件-Windows Media Player
  5. html分辨率的适配方法,pc端px转换为rem针对屏幕分辨率进行页面适配
  6. 单臂路由实现VLAN间通信(不同VLAN,不同网段互访)
  7. 【程序员自我修养】运行库
  8. 2020年中国休闲食品行业发展现状分析,安全、健康是行业发展主要趋势「图」
  9. SDR学习之——跟踪飞机轨迹
  10. Unity3D深入浅出 - 新版动画系统(Mecanim)