BP神经网络求解异或问题(Python实现)
反向传播算法(Back Propagation)分二步进行,即正向传播和反向传播。这两个过程简述如下:
1.正向传播
输入的样本从输入层经过隐单元一层一层进行处理,传向输出层;在逐层处理的过程中。在输出层把当前输出和期望输出进行比较,如果现行输出不等于期望输出,则进入反向传播过程。
2.反向传播
反向传播时,把误差信号按原来正向传播的通路反向传回,逐层修改连接权值,以望代价函数趋向最小。
下面以单隐层的神经网络为例,进行权值调整的公式推导,其结构示意图如下:
输入层输入向量(n维):X=(x1,x2,…,xi,…,xn)T
隐层输出向量(隐层有m个结点):Y=(y1,y2,…,yj,…,ym)T
输出层输出向量(l维):O=(o1,o2,…,ok,…,ol)T
期望输出向量:d=(d1, d2,…,dk,…,dl)T
输入层到隐层之间的权值矩阵:V=(V1,V2,…,Vj,…,Vm)
隐层到输出层之间的权值矩阵用:W=(W1,W2,…,Wk,…,Wl)
对输出层第k个结点和隐含层的第j个结点有如下关系:
激活函数f(x)常用sigmoid函数(一个在生物学中常见的S型的函数,也称为S形生长曲线)或者tanh(双曲正切)函数。各种S型曲线函数如下图所示:
下面以sigmoid函数进行推导。sigmoid函数定义为:
其导函数为:
定义对单个样本输出层所有神经元的误差总能量总和为:
将以上误差定义式展开至隐层:
权值调整思路为:
上面式子中负号表示梯度下降,常数η∈(0,1)表示权值调整步长(学习速度)。推导过程中,对输出层有j=0,1,2,…,m; k=1,2,…,l;对隐层有 i=0,1,2,…,n; j=1,2,…,m
对输出层和隐层,上面式子可写为:
对输出层和隐层,定义δ:
将以上结果代入δ的表达式,并根据sigmoid函数与其导函数的关系:f'(x)=f(x)*[1-f(x)],可以计算出:
可以看出要计算隐层的δ,需要先从输出层开始计算,显然它是反向递推计算的公式。以此类推,对于多层神经网络,要先计算出最后一层(输出层)的δ,然后再递推计算前一层,直到输入层。根据上述结果,三层前馈网的BP学习算法权值调整计算公式为:
对所有输入样本(P为训练样本的个数),以总的平均误差能量作为经验损失函数(经验风险函数,代价函数)为:
最终目标是需要调整连接权使得经验损失函数最小。用BP算法训练网络时有两种训练方式:一种是顺序方式(Stochastic Learning),即每输入一个训练么样本修改一次权值;以上给出的权值修正步骤就是按顺序方式训练网络的;另一种是批处理方式(Batch Learning),即待组成一个训练周期的全部样本都一次输入网络后,以Ep为目标函数修正权值.
顺序方式所需的临时存储空间较批处理方式小,而且随机输入样本有利于权值空间的搜索具有随机性,在一定程度上可以避免学习陷入局部最小值。但是顺序方式的误差收敛条件难以建立,而批处理方式能精确地计算出梯度向量,误差收敛条件简单。
Stochastic learning is generally the preferred method for basic backpropagation for the following three reasons:
Despite the advantages of stochastic learning, there are still reasons why one might consider using batch learning:
下面采用激活函数为tanh(x)的三层网络来解决异或问题(当激活函数为奇函数时,BP 算法的学习速度要快一些,最常用的奇函数是双曲正切函数)
# -*- coding: utf-8 -*-
import numpy as np # 双曲正切函数,该函数为奇函数
def tanh(x):
return np.tanh(x) # tanh导函数性质:f'(t) = 1 - f(x)^2
def tanh_prime(x):
return 1.0 - tanh(x)**2 class NeuralNetwork:
def __init__(self, layers, activation = 'tanh'):
"""
:参数layers: 神经网络的结构(输入层-隐含层-输出层包含的结点数列表)
:参数activation: 激活函数类型
"""
if activation == 'tanh': # 也可以用其它的激活函数
self.activation = tanh
self.activation_prime = tanh_prime
else:
pass # 存储权值矩阵
self.weights = [] # range of weight values (-1,1)
# 初始化输入层和隐含层之间的权值
for i in range(1, len(layers) - 1):
r = 2*np.random.random((layers[i-1] + 1, layers[i] + 1)) -1 # add 1 for bias node
self.weights.append(r) # 初始化输出层权值
r = 2*np.random.random( (layers[i] + 1, layers[i+1])) - 1
self.weights.append(r) def fit(self, X, Y, learning_rate=0.2, epochs=10000):
# Add column of ones to X
# This is to add the bias unit to the input layer
X = np.hstack([np.ones((X.shape[0],1)),X]) for k in range(epochs): # 训练固定次数
if k % 1000 == 0: print 'epochs:', k # Return random integers from the discrete uniform distribution in the interval [0, low).
i = np.random.randint(X.shape[0],high=None)
a = [X[i]] # 从m个输入样本中随机选一组 for l in range(len(self.weights)):
dot_value = np.dot(a[l], self.weights[l]) # 权值矩阵中每一列代表该层中的一个结点与上一层所有结点之间的权值
activation = self.activation(dot_value)
a.append(activation) # 反向递推计算delta:从输出层开始,先算出该层的delta,再向前计算
error = Y[i] - a[-1] # 计算输出层delta
deltas = [error * self.activation_prime(a[-1])] # 从倒数第2层开始反向计算delta
for l in range(len(a) - 2, 0, -1):
deltas.append(deltas[-1].dot(self.weights[l].T)*self.activation_prime(a[l])) # [level3(output)->level2(hidden)] => [level2(hidden)->level3(output)]
deltas.reverse() # 逆转列表中的元素 # backpropagation
# 1. Multiply its output delta and input activation to get the gradient of the weight.
# 2. Subtract a ratio (percentage) of the gradient from the weight.
for i in range(len(self.weights)): # 逐层调整权值
layer = np.atleast_2d(a[i]) # View inputs as arrays with at least two dimensions
delta = np.atleast_2d(deltas[i])
self.weights[i] += learning_rate * np.dot(layer.T, delta) # 每输入一次样本,就更新一次权值 def predict(self, x):
a = np.concatenate((np.ones(1), np.array(x))) # a为输入向量(行向量)
for l in range(0, len(self.weights)): # 逐层计算输出
a = self.activation(np.dot(a, self.weights[l]))
return a if __name__ == '__main__':
nn = NeuralNetwork([2,2,1]) # 网络结构: 2输入1输出,1个隐含层(包含2个结点) X = np.array([[0, 0], # 输入矩阵(每行代表一个样本,每列代表一个特征)
[0, 1],
[1, 0],
[1, 1]])
Y = np.array([0, 1, 1, 0]) # 期望输出 nn.fit(X, Y) # 训练网络 print 'w:', nn.weights # 调整后的权值列表 for s in X:
print(s, nn.predict(s)) # 测试
输出为:
参考:
https://triangleinequality.wordpress.com/2014/03/31/neural-networks-part-2/
https://databoys.github.io/Feedforward/
http://www.cnblogs.com/wentingtu/archive/2012/06/05/2536425.html
《Neural Networks Tricks of the Trade》Second Edition
BP神经网络求解异或问题(Python实现)的更多相关文章
- BP神经网络及异或实现
BP神经网络是最简单的神经网络模型了,三层能够模拟非线性函数效果. 难点: 如何确定初始化参数? 如何确定隐含层节点数量? 迭代多少次?如何更快收敛? 如何获得全局最优解? ''' neural ne ...
- ANN神经网络——实现异或XOR (Python实现)
一.Introduction Perceptron can represent AND,OR,NOT 用初中的线性规划问题理解 异或的里程碑意义 想学的通透,先学历史! 据说在人工神经网络(artif ...
- BP神经网络原理及python实现
[废话外传]:终于要讲神经网络了,这个让我踏进机器学习大门,让我读研,改变我人生命运的四个字!话说那么一天,我在乱点百度,看到了这样的内容: 看到这么高大上,这么牛逼的定义,怎么能不让我这个技术宅男心 ...
- BP神经网络与Python实现
人工神经网络是一种经典的机器学习模型,随着深度学习的发展神经网络模型日益完善. 联想大家熟悉的回归问题, 神经网络模型实际上是根据训练样本创造出一个多维输入多维输出的函数, 并使用该函数进行预测, 网 ...
- 三层BP神经网络的python实现
这是一个非常漂亮的三层反向传播神经网络的python实现,下一步我准备试着将其修改为多层BP神经网络. 下面是运行演示函数的截图,你会发现预测的结果很惊人! 提示:运行演示函数的时候,可以尝试改变隐藏 ...
- Python语言编写BP神经网络
Python语言编写BP神经网络 2016年10月31日 16:42:44 ldy944758217 阅读数 3135 人工神经网络是一种经典的机器学习模型,随着深度学习的发展神经网络模型日益完善 ...
- Python实现bp神经网络识别MNIST数据集
title: "Python实现bp神经网络识别MNIST数据集" date: 2018-06-18T14:01:49+08:00 tags: [""] cat ...
- python构建bp神经网络_曲线拟合(一个隐藏层)__2.代码实现
IDE:jupyter 抽象程度可能不是那么高,以后再优化. 理论和代码实现的差距还是挺大的 数据集请查看 python构建bp神经网络(一个隐藏层)__1.数据可视化 部分代码预览 git上传.ip ...
- BP神经网络在python下的自主搭建梳理
本实验使用mnist数据集完成手写数字识别的测试.识别正确率认为是95% 完整代码如下: #!/usr/bin/env python # coding: utf-8 # In[1]: import n ...
随机推荐
- Mysql 注意细节
1.无法连接远程数据库,是因为远程服务器并没有开通权限,提供给其他机子连接: 在服务器机子 开通权限: 1)进去MySql 2)mysql>GRANT ALL PRIVILEGES ...
- InnoDB Status Output – Buffer Pool and Spin Rounds
InnoDB has a good source of information about its status which can be requested every time you need ...
- mysql字段varchar区分大小写utf8_bin、utf8_general_ci编码区别
mysql字段varchar区分大小写utf8_bin.utf8_general_ci编码区别 在mysql中存在着各种utf8编码格式:utf8_bin将字符串中的每一个字符用二进制数据存储,区分大 ...
- React Native学习笔记-1:JSC profiler is not supported.
新建React-Native工程,直接编译运行报错,控制台错误信息如下: 2016-02-22 16:49:47.317 [info][tid:com.facebook.React.JavaScrip ...
- php的header()函数之设置content-type
//定义编码 header( 'Content-Type:text/html;charset=utf-8 '); //Atom header('Content-type: application/at ...
- php header()函数设置页面Cache缓存
header()函数在php的使用很大,下面我来介绍利用它实现页面缓存的一些方法,但使用header前必须注意,在它之前不能任何输出,包括空格. 手册上,我们对于cache都是写着如何设置,以便让代码 ...
- 微信公众平台自定义菜单PHP开发
微信公众平台自定义菜单PHP开发,微信公众平台自定义菜单是如何实现的呢?其实很简单,首先在微信公众平台升级为服务号,获取appid和appsecret,然后根据这2个参数获取access_token, ...
- ReactDom.render和React.render的区别
这个是react最新版api,也就是0.14版本做出的改变.主要是为了使React能在更多的不同环境下更快.更容易构建.于是把react分成了react和react-dom两个部分.这样就为web版的 ...
- 求两个数的最大公约数(Java)
获得两个随机数(100以内),并放入数组中 public int[] getTwoRandom(){ int[] t = new int[2]; Random rand = new Random(); ...
- S3c6410 平台 Android系统的Wi-Fi调试记录
硬件平台:S3c6410 操作系统:Android 网卡芯片:GH381(SDIO接口 sdio8688) 1.SDIO驱动 因为是SDIO接口,所以请先保证mmc驱动(代码在“kernel\driv ...