需要源码请点赞关注收藏后评论区留言私信~~~
多层网络的学习能力比单层感知机强很多,要训练多层网络,简单的感知机学习规则显然不够,需要更强大的学习算法。误差逆传播(Error BackPropagation)算法就是学习算法中的杰出代表。现实任务中使用神经网络时,大多是使用BP算法进行训练。需要注意的是,BP算法不仅可以用于多层前馈神经网络,还可以用于其他类型的神经网络。通常说BP网络时,常指利用BP算法训练的多层前馈神经网络。神经网络可以用于分类(预测给定元组的类标号)和数值预测(预测连续值输出)等
多层前馈神经网络由一个输入层、一个或多个隐层和一个输出层组成,如图9-5所示。它利用后向传播算法迭代地学习用于元组类标号预测的一组权重
网络中 每层由一些单元组成,网格的输入对应于对每个训练元组的观测属性,输入同时提供给构成输入层的单元,这些输入通过输入层加权求和后提供给称为隐藏层的类神经元的第二层,该隐藏层单元的输出输入到下一个隐藏层,隐藏层的数量是任意的,最后一个隐藏层的权重输出作为构成输出层的单元输入,输出层发布给定元组的网络预测,前馈网络中的权重都不回送到输入单元或者前一层的输出单元,网络是全连接的,即每个单元都向下一层的每个单元提供输入
对于最好的隐藏层单元数,没有明确的规则确定,网络设计是一个反复试验的过程,并可能影响结果训练网络的准确性,权重的初值也可能影响结果的准确性
后向传播通过迭代地处理训练元组数据集,把每个元组的网络预测与实际已知的目标值相比较进行学习。对于每个训练样本,修改权重使得网络预测和实际目标值之间的均方误差最小。这种修改“后向”进行,即由输出层,经由每个隐层到第一个隐藏层。BP算法的主要思想是把训练过程分为两个阶段
1. 第一阶段(正向传播过程)
2. 第二阶段(反向传播过程)
若在输出层不能得到期望的输出值,那么逐层递归地计算实际输出与期望输出的差值,以便根据差值调节权值。BP算法基于梯度下降(Gradient Descent)策略,以目标的负梯度方向对参数进行调整
误差反向传播的过程就是将误差分摊给各层所有单元,从而获得各层单元的误差信号,进而修正各单元的权值,即权值调整的过程,每处理一个样本,就更新权重和偏置,称为实例更新,如果处理完训练集中的所有元组之后再更新权重和偏置,称为周期更新,理论上,反向传播算法的数据推导使用周期更新,但是在实践中,实例更新通常产生更加准确的结果
BP算法流程图描述如下
BP算法具有简单易行,计算量小和并行性强等优点,是神经网络训练采用最多也最成熟的训练算法之一,算法的实质是求解误差函数的最小值问题,由于它采用非线性规划中的最速下降,按误差的函数的负梯度方向修改权值,因而通常存在学习效率低,收敛速度慢,和容易陷入局部极小状态的缺点
输出结果如下 由输入层权重映射到输出层权重
部分代码如下
import numpy as np
import math
import random
import string
import matplotlib as mpl
import matplotlib.pyplot as plt
#random.seed(0)
#生成区间[a,b]内的随机数
def random_number(a,b):
return (b-a)*random.random()+a
#生成一个矩阵,大小为m*n,并且设置默认零矩阵
def makematrix(m, n, fill=0.0):
a = []
for i in range(m):
a.append([fill]*n)
return a
#函数sigmoid(),这里采用tanh
def sigmoid(x):
return math.tanh(x)
#函数sigmoid的派生函数
def derived_sigmoid(x):
return 1.0 - x**2
#构造三层BP网络架构
class BPNN:
def __init__(self, num_in, num_hidden, num_out):
#输入层,隐藏层,输出层的结点数
self.num_in = num_in + 1 #增加一个偏置结点
self.num_hidden = num_hidden + 1 #增加一个偏置结点
self.num_out = num_out
#激活神经网络的所有结点(向量)
self.active_in = [1.0]*self.num_in
self.active_hidden = [1.0]*self.num_hidden
self.active_out = [1.0]*self.num_out
#创建权重矩阵
self.wight_in = makematrix(self.num_in, self.num_hidden)
self.wight_out = makematrix(self.num_hidden, self.num_out)
#对权值矩阵赋初值
for i in range(self.num_in):
for j in range(self.num_hidden):
self.wight_in[i][j] = random_number(-0.2, 0.2)
for i in range(self.num_hidden):
for j in range(self.num_out):
self.wight_out[i][j] = random_number(-0.2, 0.2)
#最后建立动量因子(矩阵)
self.ci = makematrix(self.num_in, self.num_hidden)
self.co = makematrix(self.num_hidden, self.num_out)
#信号正向传播
def update(self, inputs):
if len(inputs) != self.num_in-1:
raise ValueError('与输入层结点数不符')
#数据输入输入层
for i in range(self.num_in - 1):
#self.active_in[i] = sigmoid(inputs[i])
#或者先在输入层进行数据处理
self.active_in[i] = inputs[i] #active_in[]是输入数据的矩阵
#数据在隐藏层的处理
for i in range(self.num_hidden - 1):
sum = 0.0
for j in range(self.num_in):
sum = sum + self.active_in[i] * self.wight_in[j][i]
self.active_hidden[i] = sigmoid(sum)
#数据在输出层的处理
for i in range(self.num_out):
sum = 0.0
for j in range(self.num_hidden):
sum = sum + self.active_hidden[j]*self.wight_out[j][i]
self.active_out[i] = sigmoid(sum) #与上同理
return self.active_out[:]
#误差反向传播
def errorbackpropagate(self, targets, lr, m):
#lr是学习率, m是动量因子
if len(targets) != self.num_out:
raise ValueError('与输出层结点数不符!')
#首先计算输出层的误差
out_deltas = [0.0]*self.num_out
for i in range(self.num_out):
error = targets[i] - self.active_out[i]
out_deltas[i] = derived_sigmoid(self.active_out[i])*error
#然后计算隐藏层误差
hidden_deltas = [0.0]*self.num_hidden
for i in range(self.num_hidden):
error = 0.0
for j in range(self.num_out):
error = error + out_deltas[j]* self.wight_out[i][j]
hidden_deltas[i] = derived_sigmoid(self.active_hidden[i])*error
#首先更新输出层权值
for i in range(self.num_hidden):
for j in range(self.num_out):
change = out_deltas[j]*self.active_hidden[i]
self.wight_out[i][j] = self.wight_out[i][j] +lr*change + m*self.co[i][j]
self.co[i][j] = change
#然后更新输入层权值
for i in range(self.num_in):
for i in range(self.num_hidden):
change = hidden_deltas[j]*self.active_in[i]
self.wight_in[i][j] = self.wight_in[i][j] +lr*change + m* self.ci[i][j]
self.ci[i][j] = change
#计算总误差
error = 0.0
for i in range(len(targets)):
error = error + 0.5*(targets[i] - self.active_out[i])**2
return error
#测试
def test(self, patterns):
for i in patterns:
print(i[0], '->', self.update(i[0]))
#权重
def weights(self):
print("输入层权重")
for i in range(self.num_in):
print(self.wight_in[i])
print("输出层权重")
for i in range(self.num_hidden):
print(selfitera):
error[1]],
[[1,6,2],[1]],
[[1,5,1],[0]],
[[1,8,4],[1]]
]
#创建神经网络,3个输入结点,3个隐藏层结点,1个输出层结点
n = BPNN(3, 3, 1)
n.train(patt)#训练神经网络
n.test(patt) #测试神经网络
n.weights() #查阅权重值
if __name__ == '__main__':
demo()
创作不易 觉得有帮助请点赞关注收藏~~~