参考了一些书籍和博客,整理了关于神经网络的简单发展历史,给出BP神经网的计算原理与python3源码,供对相关领域感兴趣的小伙伴学习
一、神经网络发展的沉浮
二、BP神经网络算法原理
三、BP神经网络算法python3实现
早在二十世纪四十年代M-P神经元模型、Hebb学习率等相关理论便发展起来,1949年神经心理学家Hebb出版《行为组织学》(Organization of Behavior),在该书中,Hebb提出了被后人称为“Hebb规则”的学习机制。这个规则认为如果两个细胞总是同时激活的话,它们之间就有某种关联,同时激活的概率越高,关联度也越高,这是神经网络理论较为早期的一些积淀。
误差逆传播算法(Error BackPropagation,BP)是神经网络算法中的杰出代表,它是迄今为止最成功的神经网络算法,现实任务中使用神经网络时,大多是在是在使用BP算法进行训练。BP算法不仅可以用于多层前馈网络(前馈是指网络拓扑结构上不存在环路或回路),还可以用于其他网络,但通常说到“BP网络”时,是指BP算法训练的多层前馈网络
这里首先对三层(输入层、隐层、输出层)的相关参数给出定义,给定训练集
即输入示例由d个属性描述,输出l维实例向量,现在设定一个拥有d个输入神经元、l个输出神经元、q个隐层神经元的多层前馈神经网络结构,其中输出层第j个神经元的阈值、隐层第h个神经元的阈值分别表示为
输入层第j个神经元与隐层第h个神经元之间的连接权、隐层第h个神经元与输出层第j个神经元之间的连接权分别表示为
由上可得,隐层第h个神经元接收到的输入与输出层第j个神经元接收到的输入可分别表示为
假设隐层和输出层神经元都使用下列的Sigmoid函数做为激活函数
对于一个训练样例,假定神经网络的输出为
即
BP算法基于梯度下降策略,以目标的负梯度方向对参数进行调整,现以均方差定义网络的输出误差为
上式中的1/2只是为了方便求导
在定义的网络中的所有连接权和阈值都需要在确定误差不满足要求后进行更新,更新的估计式为
下面以从隐层到输出层的连接权为例来进行推导,以目标的负梯度方向对参数进行调整,对误差求导并给定学习率,有
又有
已知Sigmoid具有如下性质
综上可得(经过网友,zhaozx19950803,的提醒gj的结果应该多一个负号)
于是可得从隐层到输出层的连接权的更新公式
同理可得
其中
python3源码
#!/usr/bin/env python3
# -*-coding: utf-8-*-
# Author : LiangjunFeng
# Blog : http://my.csdn.net/Liangjun_Feng
# GitHub : https://www.github.com/LiangjunFeng
# File : BP neural network.py
# Date : 2017/09/17 11:12
# Version: 0.1
# Description: BP neural network
import random
import math
import numpy
random.seed(0)
def rand(low,high): #随机函数
return (high-low)*random.random()+low
def sigmoid(x): #sigmoid函数
return 1.0/(1+math.exp(-x))
def vectorSigmoid(vect): #对一个向量里的所有值进行sigmoid函数处理
length = numpy.shape(vect)[1]
for i in range(length):
vect[0,i] = sigmoid(vect[0,i])
return vect
def makeMatrix(length,bordth,fill = 0.0): #创建矩阵
mat = []
for i in range(length):
mat.append([fill]*bordth)
return numpy.mat(mat)
def randfillMatrix(mat,low,high): #矩阵值的随机填充
length = numpy.shape(mat)[0]
bordth = numpy.shape(mat)[1]
for i in range(length):
for j in range(bordth):
mat[i,j] = rand(low,high)
return mat
def vectorMultiply(vect1,vect2): #向量相乘得到一个矩阵
length = numpy.shape(vect1)[1]
bordth = numpy.shape(vect2)[1]
mat = makeMatrix(length,bordth)
for i in range(length):
for j in range(bordth):
mat[i,j] = vect1[0,i]*vect2[0,j]
return mat
class BPNeuralNetwork:
def __init__(self,inputNodes,hiddenNodes,outputNodes): #初始化变量
self._inputNodes = inputNodes #输入层结点个数
self._hiddenNodes = hiddenNodes #隐藏层结点个数
self._outputNodes = outputNodes #输出层结点个数
self._inputLayer = [] #输入层数据
self._hiddenLayer = [] #隐藏层数据
self._outputLayer = [] #输出层数据
self._inputWeights = [] #输入层到隐藏层连接权
self._outputWeights = [] #隐藏层到输出层连接权
self._hiddenThreshold = [] #隐藏层激活阈值
self._outputThreshold = [] #输出层阈值
def setup(self):
self._inputLayer = makeMatrix(1,self._inputNodes,1.)
self._hiddenLayer = makeMatrix(1,self._hiddenNodes,1.)
self._outputLayer = makeMatrix(1,self._outputNodes,1.) #三层网络架构初始赋值
self._hiddenThreshold = makeMatrix(1,self._hiddenNodes,1.)
self._outputThreshold = makeMatrix(1,self._outputNodes,1.) #两层激活阈值初始赋值
self._inputWeights = makeMatrix(self._inputNodes,self._hiddenNodes)
self._outputWeights = makeMatrix(self._hiddenNodes,self._outputNodes) #创建权重矩阵
self._inputWeights = randfillMatrix(self._inputWeights,-1.,1.)
self._outputWeights = randfillMatrix(self._outputWeights,-1.,1.) #权重矩阵初始随机幅值
def getInput(self,_input): #将一个输入赋值到输入层
for i in range(self._inputNodes):
self._inputLayer[0,i] = _input[i]
def predict(self,_input): #根据输入输出预测值到输出层
self.getInput(_input)
self._hiddenLayer = vectorSigmoid(self._inputLayer*self._inputWeights - self._hiddenThreshold)
self._outputLayer = vectorSigmoid(self._hiddenLayer*self._outputWeights - self._outputThreshold)
def backPropagation(self,y,lRate): #反响传播更新激活阈值与连接权
G = numpy.multiply(numpy.multiply(self._outputLayer,1-self._outputLayer),y-self._outputLayer)
self._outputWeights = self._outputWeights + lRate*vectorMultiply(self._hiddenLayer,G)
self._outputThreshold = self._outputThreshold - lRate*G
E = numpy.multiply(numpy.multiply(self._hiddenLayer,1-self._hiddenLayer),(self._outputWeights*G.T).T)
self._inputWeights = self._inputWeights + lRate*vectorMultiply(self._inputLayer,E)
self._hiddenThreshold = self._hiddenThreshold - lRate*E
return float((y-self._outputLayer)*(y-self._outputLayer).T)
def fit(self,input_,y_,limit = 10000,accuracy = 0.001,lRate = 0.2): #拟合数据
self.setup()
num = len(input_)
error,times = num,1
while((error > accuracy) and (times < limit)):
i,error = 0,0
while(i < num):
_input = input_[i]
y = y_[i]
self.predict(_input)
error += self.backPropagation(y,lRate)
i += 1
times += 1
if __name__ == '__main__': #以异或运算举例
nn = BPNeuralNetwork(2,7,1)
cases = [[0,0],[0,1],[1,0],[1,1]]
labels = [[0],[1],[1],[0]]
nn.fit(cases,labels)
for case in cases:
nn.predict(case)
print(case,' ',nn._outputLayer)