本系列是机器学习课程的系列课程,主要介绍基于python实现神经网络。
本文来源原文链接:https://blog.csdn.net/weixin_66845445/article/details/133828686
python神经网络编程代码https://gitee.com/iamyoyo/makeyourownneuralnetwork.git
完成一个特定行业的算法应用全过程:
懂业务+会选择合适的算法+数据处理+算法训练+算法调优+算法融合 +算法评估+持续调优+工程化接口实现
关于机器学习的定义,Tom Michael Mitchell的这段话被广泛引用: 对于某类任务T和性能度量P,如果一个计算机程序在T上其性能P随着经验E而自我完善,那么我们称这个计算机程序从经验E中学习。
BP算法实现流程图
激活函数采用双曲正切函数tanh:
#? 激活函数sigmoid(x)、及其导数DS(x)
import numpy as np
# 双曲正切函数tanh
def sigmoid(x):
return np.tanh(x)
def DS(x):
return 1 - (np.tanh(x)) ** 2
# 第90次迭代 误差0.00005
神经网络类架构
#? 构造3层BP神经网络架构
class BP:
#? 初始化函数:各层结点数、激活结点、权重矩阵、偏差、动量因子
def __init__(self,num_in,num_hidden,num_out):
pass
#? 信号正向传播
def update(self,inputs):
pass
#? 误差反向传播
def errorbackpropagate(self,targets,lr,m): # lr 学习效率
pass
#? 测试
def test(self,patterns):
pass
#? 权值
def weights(self):
pass
# 训练
def train(self,pattern,itera=100,lr=0.2,m=0.1):
pass
4.2.1 BP神经网络初始化
#? 构造3层BP神经网络架构
class BP:
#? 初始化函数:各层结点数、激活结点、权重矩阵、偏差、动量因子
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 # 输出层结点数
# 激活BP神经网络的所有结点(向量)
self.active_in=np.array([-1.0]*self.num_in)
self.active_hidden=np.array([-1.0]*self.num_hidden)
self.active_out=np.array([1.0]*self.num_out)
# 创建权重矩阵
self.weight_in=makematrix(self.num_in,self.num_hidden) # in*hidden 的0矩阵
self.weight_out=makematrix(self.num_hidden,self.num_out) # hidden*out的0矩阵
# 对权重矩阵weight赋初值
for i in range(self.num_in): # 对weight_in矩阵赋初值
for j in range(self.num_hidden):
self.weight_in[i][j]=random_number(0.1,0.1)
for i in range(self.num_hidden): # 对weight_out矩阵赋初值
for j in range(self.num_out):
self.weight_out[i][j]=random_number(0.1,0.1)
# 偏差
for j in range(self.num_hidden):
self.weight_in[0][j]=0.1
for j in range(self.num_out):
self.weight_out[0][j]=0.1
# 建立动量因子(矩阵)
self.ci=makematrix(self.num_in,self.num_hidden) # num_in*num_hidden 矩阵
self.co=makematrix(self.num_hidden,self.num_out) # num_hidden*num_out矩阵
图解:初始化后各个变量的存在形式:
4.2.2 前向传播
#? 构造3层BP神经网络架构
class BP:
#? 信号正向传播
def update(self,inputs):
if len(inputs)!=(self.num_in-1):
raise ValueError("与输入层结点数不符")
# 数据输入 输入层
self.active_in[1:self.num_in]=inputs
# 数据在隐藏层处理
self.sum_hidden=np.dot(self.weight_in.T,self.active_in.reshape(-1,1)) # 叉乘
# .T操作是对于array操作后的数组进行转置操作
# .reshape(x,y)操作是对于array操作后的数组进行重新排列成一个x*y的矩阵,参数为负数表示无限制,如(-1,1)转换成一列的矩阵
self.active_hidden=sigmoid(self.sum_hidden) # active_hidden[]是处理完输入数据之后处理,作为输出层的输入数据
self.active_hidden[0]=-1
# 数据在输出层处理
self.sum_out=np.dot(self.weight_out.T,self.active_hidden)
self.active_out=sigmoid(self.sum_out)
# 返回输出层结果
return self.active_out
图解:正向传播的过程:计算出active_in、active_hidden、active_out:
4.2.3 反向传播
#? 构造3层BP神经网络架构
class BP:
#? 误差反向传播
def errorbackpropagate(self,targets,lr,m): # lr 学习效率
if self.num_out==1:
targets=[targets]
if len(targets)!=self.num_out:
raise ValueError("与输出层结点数不符")
# 误差
error=(1/2)*np.dot((targets.reshape(-1,1)-self.active_out).T,
(targets.reshape(-1,1)-self.active_out))
# 输出层 误差信号
self.error_out=(targets.reshape(-1,1)-self.active_out)*DS(self.sum_out) # DS(self.active_out)
# 隐层 误差信号
self.error_hidden=np.dot(self.weight_out,self.error_out)*DS(self.sum_hidden) # DS(self.active_hidden)
# 更新权值
# 隐层
self.weight_out=self.weight_out+lr*np.dot(self.error_out,self.active_hidden.reshape(1,-1)).T+m*self.co
self.co=lr*np.dot(self.error_out,self.active_hidden.reshape(1,-1)).T
# 输入层
self.weight_in=self.weight_in+lr*np.dot(self.error_hidden,self.active_in.reshape(1,-1)).T+m*self.ci
self.ci=lr*np.dot(self.error_hidden,self.active_in.reshape(1,-1)).T
return error
图解:反向传播计算出error_hidden(即eh)、error_out(即gj):
反向传播更新权值,计算出weight_in、weight_out:
4.2.4 迭代训练
#? 构造3层BP神经网络架构
class BP:
def train(self,pattern,itera=100,lr=0.2,m=0.1):
for i in range(itera):
error=0.0 # 每一次迭代将error置0
for j in pattern: # j为传入数组的第一维数据 #! *2?(1次迭代里面重复两次?)
inputs=j[0:self.num_in-1] # 根据输入层结点的个数确定传入结点值的个数
targets=j[self.num_in-1:] # 剩下的结点值作为输出层的值
self.update(inputs) # 正向传播 更新了active_out
error=error+self.errorbackpropagate(targets,lr,m) # 误差反向传播 计算总误差
if i%10==0:
print("########################误差 %-.5f ######################第%d次迭代" %(error, i))
默认迭代训练100次。
#? 算法检验——预测数据D
# X 输入数据;D 目标数据
X = list(np.arange(-1, 1.1, 0.1)) # -1~1.1 步长0.1增加
D = [-0.96, -0.577, -0.0729, 0.017, -0.641, -0.66, -0.11, 0.1336, -0.201, -0.434, -0.5,
-0.393, -0.1647, 0.0988, 0.3072,0.396, 0.3449, 0.1816, -0.0312, -0.2183, -0.3201]
A = X + D # 数据合并 方便处理
patt = np.array([A] * 2) # 2*42矩阵
# 创建神经网络,21个输入节点,13个隐藏层节点,21个输出层节点
bp = BP(21, 13, 21)
# 训练神经网络
bp.train(patt)
# 测试神经网络
d = bp.test(patt)
# 查阅权重值
bp.weights()
import matplotlib.pyplot as plt
fig,ax=plt.subplots(1,3)
ax[0].plot(X, D, label="source data",color='red') # D为真实值
# plt.subplots(212)
ax[1].plot(X, d, label="predict data",color='green') # d为预测值
ax[2].plot(X, D, label="source data",color='red') # D为真实值
# plt.subplots(212)
ax[2].plot(X, d, label="predict data",color='green') # d为预测值
plt.legend()
plt.show()
输入数据为X数据集、预测目标数据为D数据集,经过BP网络后输出的预测数据为d数据集。
最后结果输出形式为终端数据呈现、与可视化图像呈现。
综上图解,各个变量的存在形式如下:
1、权值矩阵:
2、激活矩阵:
3、动量矩阵:
1、运行后在终端输出的一部分结果:
“->”左侧为输入的数据xi,“->”右侧为这些数据经过三层感知机后的输出结果yj;
[-1.00000000e+00 -9.00000000e-01 -8.00000000e-01 -7.00000000e-01 -6.00000000e-01 -5.00000000e-01 -4.00000000e-01 -3.00000000e-01 -2.00000000e-01 -1.00000000e-01 -2.22044605e-16 1.00000000e-01 2.00000000e-01 3.00000000e-01 4.00000000e-01 5.00000000e-01 6.00000000e-01 7.00000000e-01 8.00000000e-01 9.00000000e-01 1.00000000e+00] -> [[-0.95393255] [-0.57714037] [-0.07292908] [ 0.01697976] [-0.64118266] [-0.66019917] [-0.11003299] [ 0.13359081] [-0.20104368] [-0.43408624] [-0.50010661] [-0.39307616] [-0.16473919] [ 0.09878749] [ 0.30720978] [ 0.39602303] [ 0.34491495] [ 0.18159555] [-0.03122489] [-0.21834595] [-0.32016156]] [-1.00000000e+00 -9.00000000e-01 -8.00000000e-01 -7.00000000e-01 -6.00000000e-01 -5.00000000e-01 -4.00000000e-01 -3.00000000e-01 -2.00000000e-01 -1.00000000e-01 -2.22044605e-16 1.00000000e-01 2.00000000e-01 3.00000000e-01 4.00000000e-01 5.00000000e-01 6.00000000e-01 7.00000000e-01 8.00000000e-01 9.00000000e-01 1.00000000e+00] -> [[-0.95393255] [-0.57714037] [-0.07292908] [ 0.01697976] [-0.64118266] [-0.66019917] [-0.11003299] [ 0.13359081] [-0.20104368] [-0.43408624] [-0.50010661] [-0.39307616] [-0.16473919] [ 0.09878749] [ 0.30720978] [ 0.39602303] [ 0.34491495] [ 0.18159555] [-0.03122489] [-0.21834595] [-0.32016156]]
集合D为标准值,可以看到“->”右侧的预测结果和真实值相差很小,说明预测效果较好; 2、下面看一下一些迭代后的误差数据:
########################误差 2.52401 ######################第0次迭代 ########################误差 0.00616 ######################第10次迭代 ########################误差 0.00194 ######################第20次迭代 ########################误差 0.00089 ######################第30次迭代 ########################误差 0.00048 ######################第40次迭代 ########################误差 0.00028 ######################第50次迭代 ########################误差 0.00018 ######################第60次迭代 ########################误差 0.00011 ######################第70次迭代 ########################误差 0.00008 ######################第80次迭代 ########################误差 0.00005 ######################第90次迭代
我们一共迭代训练了100次,可以看到当训练到90次后,误差已经减小到0.00005,误差极小,也说明预测效果较好;比较这些误差数据发现误差减小的速度很快,说明我们使用改进后的BP算法比较不错; 3、输入层的权值
输入层的权值: [[ 0.31234583 0.13989135 0.13989135 0.13989135 0.13989135 0.13989135 0.13989135 0.13989135 0.13989135 0.13989135 0.13989135 0.13989135 0.13989135 0.13989135] [ 0.31234583 0.13989135 0.13989135 0.13989135 0.13989135 0.13989135 0.13989135 0.13989135 0.13989135 0.13989135 0.13989135 0.13989135 0.13989135 0.13989135] [ 0.29111125 0.13590221 0.13590221 0.13590221 0.13590221 0.13590221 0.13590221 0.13590221 0.13590221 0.13590221 0.13590221 0.13590221 0.13590221 0.13590221] [ 0.26987666 0.13191308 0.13191308 0.13191308 0.13191308 0.13191308 0.13191308 0.13191308 0.13191308 0.13191308 0.13191308 0.13191308 0.13191308 0.13191308] [ 0.24864208 0.12792394 0.12792394 0.12792394 0.12792394 0.12792394 0.12792394 0.12792394 0.12792394 0.12792394 0.12792394 0.12792394 0.12792394 0.12792394] [ 0.2274075 0.12393481 0.12393481 0.12393481 0.12393481 0.12393481 0.12393481 0.12393481 0.12393481 0.12393481 0.12393481 0.12393481 0.12393481 0.12393481] [ 0.20617292 0.11994567 0.11994567 0.11994567 0.11994567 0.11994567 0.11994567 0.11994567 0.11994567 0.11994567 0.11994567 0.11994567 0.11994567 0.11994567] [ 0.18493833 0.11595654 0.11595654 0.11595654 0.11595654 0.11595654 0.11595654 0.11595654 0.11595654 0.11595654 0.11595654 0.11595654 0.11595654 0.11595654] [ 0.16370375 0.1119674 0.1119674 0.1119674 0.1119674 0.1119674 0.1119674 0.1119674 0.1119674 0.1119674 0.1119674 0.1119674 0.1119674 0.1119674 ] [ 0.14246917 0.10797827 0.10797827 0.10797827 0.10797827 0.10797827 0.10797827 0.10797827 0.10797827 0.10797827 0.10797827 0.10797827 0.10797827 0.10797827] [ 0.12123458 0.10398913 0.10398913 0.10398913 0.10398913 0.10398913 0.10398913 0.10398913 0.10398913 0.10398913 0.10398913 0.10398913 0.10398913 0.10398913] [ 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 ] [ 0.07876542 0.09601087 0.09601087 0.09601087 0.09601087 0.09601087 0.09601087 0.09601087 0.09601087 0.09601087 0.09601087 0.09601087 0.09601087 0.09601087] [ 0.05753083 0.09202173 0.09202173 0.09202173 0.09202173 0.09202173 0.09202173 0.09202173 0.09202173 0.09202173 0.09202173 0.09202173 0.09202173 0.09202173] [ 0.03629625 0.0880326 0.0880326 0.0880326 0.0880326 0.0880326 0.0880326 0.0880326 0.0880326 0.0880326 0.0880326 0.0880326 0.0880326 0.0880326 ] [ 0.01506167 0.08404346 0.08404346 0.08404346 0.08404346 0.08404346 0.08404346 0.08404346 0.08404346 0.08404346 0.08404346 0.08404346 0.08404346 0.08404346] [-0.00617292 0.08005433 0.08005433 0.08005433 0.08005433 0.08005433 0.08005433 0.08005433 0.08005433 0.08005433 0.08005433 0.08005433 0.08005433 0.08005433] [-0.0274075 0.07606519 0.07606519 0.07606519 0.07606519 0.07606519 0.07606519 0.07606519 0.07606519 0.07606519 0.07606519 0.07606519 0.07606519 0.07606519] [-0.04864208 0.07207606 0.07207606 0.07207606 0.07207606 0.07207606 0.07207606 0.07207606 0.07207606 0.07207606 0.07207606 0.07207606 0.07207606 0.07207606] [-0.06987666 0.06808692 0.06808692 0.06808692 0.06808692 0.06808692 0.06808692 0.06808692 0.06808692 0.06808692 0.06808692 0.06808692 0.06808692 0.06808692] [-0.09111125 0.06409779 0.06409779 0.06409779 0.06409779 0.06409779 0.06409779 0.06409779 0.06409779 0.06409779 0.06409779 0.06409779 0.06409779 0.06409779] [-0.11234583 0.06010865 0.06010865 0.06010865 0.06010865 0.06010865 0.06010865 0.06010865 0.06010865 0.06010865 0.06010865 0.06010865 0.06010865 0.06010865]]
4、输出层的权值
[[ 0.84862336 0.32002838 -0.03326946 -0.09136811 0.37524535 0.39260519 -0.0092981 -0.16755761 0.0498955 0.20946782 0.25873617 0.18002566 0.02618395 -0.14465799 -0.28499839 -0.34794328 -0.31142901 -0.19944158 -0.06019286 0.06126102 0.12937757] [ 0.18798645 0.06200714 0.01949841 0.01364099 0.07058899 0.07345472 0.02196489 0.0060815 0.02822658 0.04684481 0.05331062 0.04316889 0.025686 0.00835243 -0.00595306 -0.01301628 -0.00884466 0.00289912 0.016766 0.02946129 0.03712508] [ 0.18798645 0.06200714 0.01949841 0.01364099 0.07058899 0.07345472 0.02196489 0.0060815 0.02822658 0.04684481 0.05331062 0.04316889 0.025686 0.00835243 -0.00595306 -0.01301628 -0.00884466 0.00289912 0.016766 0.02946129 0.03712508] [ 0.18798645 0.06200714 0.01949841 0.01364099 0.07058899 0.07345472 0.02196489 0.0060815 0.02822658 0.04684481 0.05331062 0.04316889 0.025686 0.00835243 -0.00595306 -0.01301628 -0.00884466 0.00289912 0.016766 0.02946129 0.03712508] [ 0.18798645 0.06200714 0.01949841 0.01364099 0.07058899 0.07345472 0.02196489 0.0060815 0.02822658 0.04684481 0.05331062 0.04316889 0.025686 0.00835243 -0.00595306 -0.01301628 -0.00884466 0.00289912 0.016766 0.02946129 0.03712508] [ 0.18798645 0.06200714 0.01949841 0.01364099 0.07058899 0.07345472 0.02196489 0.0060815 0.02822658 0.04684481 0.05331062 0.04316889 0.025686 0.00835243 -0.00595306 -0.01301628 -0.00884466 0.00289912 0.016766 0.02946129 0.03712508] [ 0.18798645 0.06200714 0.01949841 0.01364099 0.07058899 0.07345472 0.02196489 0.0060815 0.02822658 0.04684481 0.05331062 0.04316889 0.025686 0.00835243 -0.00595306 -0.01301628 -0.00884466 0.00289912 0.016766 0.02946129 0.03712508] [ 0.18798645 0.06200714 0.01949841 0.01364099 0.07058899 0.07345472 0.02196489 0.0060815 0.02822658 0.04684481 0.05331062 0.04316889 0.025686 0.00835243 -0.00595306 -0.01301628 -0.00884466 0.00289912 0.016766 0.02946129 0.03712508] [ 0.18798645 0.06200714 0.01949841 0.01364099 0.07058899 0.07345472 0.02196489 0.0060815 0.02822658 0.04684481 0.05331062 0.04316889 0.025686 0.00835243 -0.00595306 -0.01301628 -0.00884466 0.00289912 0.016766 0.02946129 0.03712508] [ 0.18798645 0.06200714 0.01949841 0.01364099 0.07058899 0.07345472 0.02196489 0.0060815 0.02822658 0.04684481 0.05331062 0.04316889 0.025686 0.00835243 -0.00595306 -0.01301628 -0.00884466 0.00289912 0.016766 0.02946129 0.03712508] [ 0.18798645 0.06200714 0.01949841 0.01364099 0.07058899 0.07345472 0.02196489 0.0060815 0.02822658 0.04684481 0.05331062 0.04316889 0.025686 0.00835243 -0.00595306 -0.01301628 -0.00884466 0.00289912 0.016766 0.02946129 0.03712508] [ 0.18798645 0.06200714 0.01949841 0.01364099 0.07058899 0.07345472 0.02196489 0.0060815 0.02822658 0.04684481 0.05331062 0.04316889 0.025686 0.00835243 -0.00595306 -0.01301628 -0.00884466 0.00289912 0.016766 0.02946129 0.03712508] [ 0.18798645 0.06200714 0.01949841 0.01364099 0.07058899 0.07345472 0.02196489 0.0060815 0.02822658 0.04684481 0.05331062 0.04316889 0.025686 0.00835243 -0.00595306 -0.01301628 -0.00884466 0.00289912 0.016766 0.02946129 0.03712508] [ 0.18798645 0.06200714 0.01949841 0.01364099 0.07058899 0.07345472 0.02196489 0.0060815 0.02822658 0.04684481 0.05331062 0.04316889 0.025686 0.00835243 -0.00595306 -0.01301628 -0.00884466 0.00289912 0.016766 0.02946129 0.03712508]]
5、可视化预测值和真实值的差距:
图中其实有两根线,分别为黄线和蓝线,因为预测效果较好导致蓝线不太明显;黄线代表经过三层感知机预测出的数据,蓝线代表真实值,两条曲线拟合度很高说明三层感知机训练效果较好;
1、上述为三层的BP神经网络,即三层感知机; 2、此BP网络对标准BP网络进行改进:
(1)标准BP网络属于单样本训练,训练速度满;改进后可以进行批训练,将所有样本输入后计算网络的总误差,并根据总误差调整权值,这样训练时的收敛速度很快; (2)标准BP网络在调整权值时只按t时刻误差的梯度降方向调整,而没有考虑t时刻之前的梯度方向,在训练过程中可能会出现振荡,收敛速度慢;改进后添加了动量因子考虑了t时刻之前的梯度变化,可以提高训练速度;
#! BP神经网络(误差逆传播算法)
#! 三层BP神经网络/三层感知机
#? 激活函数sigmoid(x)、及其导数DS(x)
import numpy as np
# 双曲正切函数tanh
def sigmoid(x):
return np.tanh(x)
def DS(x):
return 1 - (np.tanh(x)) ** 2
# 第90次迭代 误差0.00005
#? 生成区间[a,b]内的随机数
import random
def random_number(a,b):
return (b-a)*random.random()+a # random.random()随机生成[0,1)内浮点数
#? 生成一个m*n矩阵,并且设置默认零矩阵
def makematrix(m,n,fill=0.0):
a = []
for i in range(m):
a.append([fill]*n) # 列表1*n会得到一个新列表,新列表元素为列表1元素重复n次。[fill]*3==[fill fill fill]
return np.array(a)
#? 构造3层BP神经网络架构
class BP:
#? 初始化函数:各层结点数、激活结点、权重矩阵、偏差、动量因子
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 # 输出层结点数
# 激活BP神经网络的所有结点(向量)
self.active_in=np.array([-1.0]*self.num_in)
self.active_hidden=np.array([-1.0]*self.num_hidden)
self.active_out=np.array([1.0]*self.num_out)
# 创建权重矩阵
self.weight_in=makematrix(self.num_in,self.num_hidden) # in*hidden 的0矩阵
self.weight_out=makematrix(self.num_hidden,self.num_out) # hidden*out的0矩阵
# 对权重矩阵weight赋初值
for i in range(self.num_in): # 对weight_in矩阵赋初值
for j in range(self.num_hidden):
self.weight_in[i][j]=random_number(0.1,0.1)
for i in range(self.num_hidden): # 对weight_out矩阵赋初值
for j in range(self.num_out):
self.weight_out[i][j]=random_number(0.1,0.1)
# 偏差
for j in range(self.num_hidden):
self.weight_in[0][j]=0.1
for j in range(self.num_out):
self.weight_out[0][j]=0.1
# 建立动量因子(矩阵)
self.ci=makematrix(self.num_in,self.num_hidden) # num_in*num_hidden 矩阵
self.co=makematrix(self.num_hidden,self.num_out) # num_hidden*num_out矩阵
#? 信号正向传播
def update(self,inputs):
if len(inputs)!=(self.num_in-1):
raise ValueError("与输入层结点数不符")
# 数据输入 输入层
self.active_in[1:self.num_in]=inputs
# 数据在隐藏层处理
self.sum_hidden=np.dot(self.weight_in.T,self.active_in.reshape(-1,1)) # 叉乘
# .T操作是对于array操作后的数组进行转置操作
# .reshape(x,y)操作是对于array操作后的数组进行重新排列成一个x*y的矩阵,参数为负数表示无限制,如(-1,1)转换成一列的矩阵
self.active_hidden=sigmoid(self.sum_hidden) # active_hidden[]是处理完输入数据之后处理,作为输出层的输入数据
self.active_hidden[0]=-1
# 数据在输出层处理
self.sum_out=np.dot(self.weight_out.T,self.active_hidden)
self.active_out=sigmoid(self.sum_out)
# 返回输出层结果
return self.active_out
#? 误差反向传播
def errorbackpropagate(self,targets,lr,m): # lr 学习效率
if self.num_out==1:
targets=[targets]
if len(targets)!=self.num_out:
raise ValueError("与输出层结点数不符")
# 误差
error=(1/2)*np.dot((targets.reshape(-1,1)-self.active_out).T,
(targets.reshape(-1,1)-self.active_out))
# 输出层 误差信号
self.error_out=(targets.reshape(-1,1)-self.active_out)*DS(self.sum_out) # DS(self.active_out)
# 隐层 误差信号
self.error_hidden=np.dot(self.weight_out,self.error_out)*DS(self.sum_hidden) # DS(self.active_hidden)
# 更新权值
# 隐层
self.weight_out=self.weight_out+lr*np.dot(self.error_out,self.active_hidden.reshape(1,-1)).T+m*self.co
self.co=lr*np.dot(self.error_out,self.active_hidden.reshape(1,-1)).T
# 输入层
self.weight_in=self.weight_in+lr*np.dot(self.error_hidden,self.active_in.reshape(1,-1)).T+m*self.ci
self.ci=lr*np.dot(self.error_hidden,self.active_in.reshape(1,-1)).T
return error
#? 测试
def test(self,patterns):
for i in patterns: # i为传入数组的第一维数据
print(i[0:self.num_in-1],"->",self.update(i[0:self.num_in-1]))
return self.update(i[0:self.num_in-1]) # 返回测试结果,用于作图
#? 权值
def weights(self):
print("输入层的权值:")
print(self.weight_in)
print("输出层的权值:")
print(self.weight_out)
def train(self,pattern,itera=100,lr=0.2,m=0.1):
for i in range(itera):
error=0.0 # 每一次迭代将error置0
for j in pattern: # j为传入数组的第一维数据
inputs=j[0:self.num_in-1] # 根据输入层结点的个数确定传入结点值的个数
targets=j[self.num_in-1:] # 剩下的结点值作为输出层的值
self.update(inputs) # 正向传播 更新了active_out
error=error+self.errorbackpropagate(targets,lr,m) # 误差反向传播 计算总误差
if i%10==0:
print("########################误差 %-.5f ######################第%d次迭代" %(error, i))
#? 算法检验——预测数据D
# X 输入数据;D 目标数据
X = list(np.arange(-1, 1.1, 0.1)) # -1~1.1 步长0.1增加
D = [-0.96, -0.577, -0.0729, 0.017, -0.641, -0.66, -0.11, 0.1336, -0.201, -0.434, -0.5,
-0.393, -0.1647, 0.0988, 0.3072,0.396, 0.3449, 0.1816, -0.0312, -0.2183, -0.3201]
A = X + D # 数据合并 方便处理
patt = np.array([A] * 2) # 2*42矩阵
# 创建神经网络,21个输入节点,13个隐藏层节点,21个输出层节点
bp = BP(21, 13, 21)
# 训练神经网络
bp.train(patt)
# 测试神经网络
d = bp.test(patt)
# 查阅权重值
bp.weights()
import matplotlib.pyplot as plt
fig,ax=plt.subplots(1,3)
ax[0].plot(X, D, label="source data",color='red') # D为真实值
# plt.subplots(212)
ax[1].plot(X, d, label="predict data",color='green') # d为预测值
ax[2].plot(X, D, label="source data",color='red') # D为真实值
# plt.subplots(212)
ax[2].plot(X, d, label="predict data",color='green') # d为预测值
plt.legend()
plt.show()