BP神经网络与Python实现

人工神经网络是一种经典的机器学习模型,随着深度学习的发展神经网络模型日益完善.

联想大家熟悉的回归问题, 神经网络模型实际上是根据训练样本创造出一个多维输入多维输出的函数, 并使用该函数进行预测, 网络的训练过程即为调节该函数参数提高预测精度的过程.神经网络要解决的问题与最小二乘法回归解决的问题并无根本性区别.

回归和分类是常用神经网络处理的两类问题, 如果你已经了解了神经网络的工作原理可以在http://playground.tensorflow.org/上体验一个浅层神经网络的工作过程.

感知机(Perceptron)是一个简单的线性二分类器, 它保存着输入权重, 根据输入和内置的函数计算输出.人工神经网络中的单个神经元即是感知机.

在前馈神经网络的预测过程中, 数据流从输入到输出单向流动, 不存在循环和返回的通道.

目前大多数神经网络模型都属于前馈神经网络, 在下文中我们将详细讨论前馈过程.

多层感知机(Multi Layer Perceptron, MLP)是由多个感知机层全连接组成的前馈神经网络, 这种模型在非线性问题中表现出色.

所谓全连接是指层A上任一神经元与临近层B上的任意神经元之间都存在连接.

反向传播(Back Propagation,BP)是误差反向传播的简称,这是一种用来训练人工神经网络的常见算法, 通常与最优化方法(如梯度下降法)结合使用.

本文介绍的神经网络模型在结构上属于MLP, 因为采用BP算法进行训练, 人们也称其为BP神经网络.

BP神经网络原理

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

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

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

Ij=iWijOiIj=∑iWijOi

Oj=sigmod(Il)=11+eIlOj=sigmod(Il)=11+e−Il

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

上文中的sigmod函数称为神经元的激励函数(activation function), 除了sigmod函数11+eIl11+e−Il外, 常用还有tanh和ReLU函数.

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

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

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

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

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

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

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

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

首先计算输出层的误差:

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

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

计算隐含层误差:

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

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

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

Wij=Wij+λEjOiWij=Wij+λEjOi

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

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

Wij=Wij+λEjOi+μCijWij=Wij+λEjOi+μCij

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

Cij=EjOiCij=EjOi

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

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

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

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

L=j(TjOj)2L=∑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 + 1self.hidden_n = nhself.output_n = no# init cellsself.input_cells = [1.0] * self.input_nself.hidden_cells = [1.0] * self.hidden_nself.output_cells = [1.0] * self.output_n# init weightsself.input_weights = make_matrix(self.input_n, self.hidden_n)self.output_weights = make_matrix(self.hidden_n, self.output_n)# random activatefor i in range(self.input_n):for h in range(self.hidden_n):self.input_weights[i][h] = rand(-0.20.2)for h in range(self.hidden_n):for o in range(self.output_n):self.output_weights[h][o] = rand(-2.02.0)# init correction matrixself.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):# activate input layerfor i in range(self.input_n - 1):self.input_cells[i] = inputs[i]# activate hidden layerfor 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)# activate output layerfor 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(selfcase, label, learn, correct):# feed forwardself.predict(case)# get output layer erroroutput_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# get hidden layer errorhidden_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# update output weightsfor h in range(self.hidden_n):for o in range(self.output_n):change = output_deltas[o] * self.hidden_cells[h]self.output_weights[h][o] += learn * change + correct * self.output_correction[h][o]self.output_correction[h][o] = change# update input weightsfor i in range(self.input_n):for h in range(self.hidden_n):change = 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# get global errorerror = 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 = [[00],[01],[10],[11],]labels = [[0], [1], [1], [0]]self.setup(251)self.train(cases, labels, 100000.050.1)for case in cases:print(self.predict(case))

完整源代码参见bpnn.py

使用tensorflow实现一个神经网络可能是更简单高效的方法, 可以参见tensorflow入门指南中的第二节:实现一个简单神经网络.

Keep working, we will find a way out. This is Finley, welcome to join us.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/387307.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

《关于长沙.NET技术社区未来发展规划》问卷调查结果公布

那些开发者们对于社区的美好期待 2月,长沙.net 技术社区自从把群拉起来开始,做了一次比较正式、题目为《关于长沙.NET技术社区未来发展规划》的问卷调查,在问卷调查中,溪源写道: 随着互联网时代的到来,互联…

第一节:ASP.NET开发环境配置

第一节:ASP.NET开发环境配置 什么是ASP.NET,学这个可以做什么,学习这些有什么内容? ASP.NET是微软公司推出的WEB开发技术。 2002年,推出第一个版本,先后推出ASP.NET2.0,和ASP.NET3.5&#xff0c…

深度学习笔记之win7下TensorFlow的安装

最近要学习神经网络相关的内容,所以需要安装TensorFlow。不得不说,安装TensorFlow的感受就像是大一刚入学学习C语言时,安装vs时一样,问题一大堆,工具都装不好,还学啥呀。好在,就在昨晚&#xff…

人脸识别经典算法一:特征脸方法(Eigenface)

这篇文章是撸主要介绍人脸识别经典方法的第一篇,后续会有其他方法更新。特征脸方法基本是将人脸识别推向真正可用的第一种方法,了解一下还是很有必要的。特征脸用到的理论基础PCA在另一篇博客里:特征脸(Eigenface)理论基础-PCA(主成分分析法)…

Xception

The First ColumnThe Second Columnpadding 方式:same and valid The First ColumnThe Second ColumnSame 就是 增加一列相同的数 (一般是0)valid只保留有效的转载于:https://www.cnblogs.com/hugeng007/p/10477430.html

1.苍穹外卖-day01

苍穹外卖-day01 课程内容 软件开发整体介绍 苍穹外卖项目介绍 开发环境搭建 导入接口文档 Swagger 项目整体效果展示: 管理端-外卖商家使用 用户端-点餐用户使用 当我们完成该项目的学习,可以培养以下能力: 1. 软件开发整体介绍 作为一名…

C#调用Python模块

编程:C#调用Python模块 当下,C#与Python都是比较热门的计算机编程语言,他们各有优缺点,如果能让他们互相配合工作,那是多么美好的事情,今天我来讲解一下如何利用C#来调用Python。 如果让C#支持调用Python模…

面试简单整理之克隆

61.为什么要使用克隆? 克隆获取对象的副本,直接用复制还是一个引用。 62.如何实现对象克隆? 1.被clone的类实现cloneable接口,重写object类的clone()方法 2.如果深克隆则克隆对象的引用对象也要实现接口、重…

PyCharm调试错误

JetBrains PyCharm 2017.3.2 这就说明python.exe的环境没有配,点击蓝色的configure Python Interpreter,然后选择对应的路径就可以了

Java06集合

13 集合 实现方法时,不同的数据结构会导致性能有很大差异。 13.1 集合接口 Java集合类库将接口(interface)与实现(implementation)分离。 可以使用接口类型存放集合的应用,一旦改变了想法,可…

Tensorflow验证码识别应用

简单的Tensorflow验证码识别应用,供大家参考,具体内容如下 1.Tensorflow的安装方式简单,在此就不赘述了. 2.训练集训练集以及测试及如下(纯手工打造,所以数量不多): 3.实现代码部分(参考了网上的一些实现来完成的) main.py(主要的神经网络代码) ?123456…

Linux 桌面玩家指南:09. X Window 的奥秘

Linux 桌面玩家指南:09. X Window 的奥秘 原文:Linux 桌面玩家指南:09. X Window 的奥秘特别说明:要在我的随笔后写评论的小伙伴们请注意了,我的博客开启了 MathJax 数学公式支持,MathJax 使用$标记数学公式的开始和结…

Storm教程1理论介绍

流式计算的历史: 早在7、8年前诸如UC伯克利、斯坦福等大学就开始了对流式数据处理的研究,但是由于更多的关注于金融行业的业务场景或者互联网流量监控的业务场景,以及当时互联网数据场景的限制,造成了研究多是基于对传统数据库处理的流式化&…

梯度下降原理及Python实现

梯度下降算法是一个很基本的算法,在机器学习和优化中有着非常重要的作用,本文首先介绍了梯度下降的基本概念,然后使用python实现了一个基本的梯度下降算法。梯度下降有很多的变种,本文只介绍最基础的梯度下降,也就是批…

matplotlib一些常用知识点的整理,

本文作为学习过程中对matplotlib一些常用知识点的整理,方便查找。 强烈推荐ipython 无论你工作在什么项目上,IPython都是值得推荐的。利用ipython --pylab,可以进入PyLab模式,已经导入了matplotlib库与相关软件包(例如…

Storm教程3编程接口

Spouts Spout是Stream的消息产生源,Spout组件的实现可以通过继承BaseRichSpout类或者其他Spout类来完成,也可以通过实现IRichSpout接口来实现。 需要根据情况实现Spout类中重要的几个方法有: open方法 当一个Task被初始化的时候会调用此…

梳理操作系统概论

1、用一张图总结操作系统的结构、功能特征、采用的技术和提供服务方式等。 2、用一张图描述CPU的工作原理。 3、用一张图描述系统程序与应用程序、特权指令与非特权指令、CPU状态、PSW及中断是如何协同工作的? 转载于:https://www.cnblogs.com/ljgljg/p/10503190.ht…

位置指纹法的实现(KNN)

基本原理 位置指纹法可以看作是分类或回归问题(特征是RSS向量,标签是位置),监督式机器学习方法可以从数据中训练出一个从特征到标签的映射关系模型。kNN是一种很简单的监督式机器学习算法,可以用来做分类或回归。 对于…

室内定位系列 ——WiFi位置指纹(译)

摘要 GPS难以解决室内环境下的一些定位问题,大部分室内环境下都存在WiFi,因此利用WiFi进行定位无需额外部署硬件设备,是一个非常节省成本的方法。然而WiFi并不是专门为定位而设计的,传统的基于时间和角度的定位方法并不适用于WiFi…

机器学习02线性回归、多项式回归、正规方程

单变量线性回归(Linear Regression with One Variable) 预测器表达式: 选择合适的参数(parameters)θ0 和 θ1,其决定了直线相对于训练集的准确程度。 建模误差(modeling error)&a…