反向传播神经网络(BPNN)的实现(Python,附源码及数据集)

文章目录

  • 一、理论基础
    • 1、前向传播
    • 2、反向传播
    • 3、激活函数
    • 4、神经网络结构
  • 二、BP神经网络的实现
    • 1、训练过程(BPNN.py)
    • 2、测试过程(test.py)
    • 3、测试结果
    • 4、参考源码及实验数据集

一、理论基础

反向传播神经网络(BPNN)是1986年由Rumelhart和McClelland为首的科学家提出的概念,是一种按照误差逆向传播算法训练的多层前馈神经网络,最常见结构为3层。
数据在神经网络中的训练过程可分为前向传播过程与反向传播过程。通过前向传递过程将数据输入网络,数据依次通过隐含层与输出层并进行相关计算,得到输出值与目标值之间的误差;然后在反向进行传递过程进行神经网络权值、阈值的调整,重复此过程,使得神经网络的输出结果不断逼近真实值。
常见的BP神经网络为3层,输入层、隐含层、输出层。其中输入层传入数据,然后在隐含层与输出层分别与权值、阈值进行计算、从而实现非线性变换,最后在输出层与目标值进行比较获取误差。

1、前向传播

前向传播过程中隐含层与输出层的输出公式及误差公式计算如下:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

其中W与b为隐含层与输出层的权值和阈值,通过初始化生成,x为隐含层与输出层的输入数据,g为激活函数,h为输出,E为误差,y_i为目标值,y ̂_i为实际值。
参数初始化方法参考:
神经网络基础知识之参数初始化

2、反向传播

反向传播过程中输出层的误差项计算公式如下:
在这里插入图片描述
在这里插入图片描述

其中V与b_2为输出层的权值和阈值,E为损失函数。隐含层的误差项的计算公式可以此类推进行计算。
隐含层与输出层的权值和阈值的更新计算公式如下:
在这里插入图片描述
在这里插入图片描述
损失函数原理参考:
机器学习基础知识之损失函数
反向传播原理参考:
神经网络之反向传播算法(梯度、误差反向传播算法BP)

3、激活函数

在前向传播过程中,输入数据除了和隐含层、输出层的权值、阈值进行计算外,还会使用激活函数g对计算结果进行非线性计算。激活函数作为人工神经网络中神经元的核心,其作用在于将非线性因素引入神经元,它在输入传递至输出的过程中进行函数转换,以此将无限范围内的输入非线性变换为有限范围内的输出,一旦人工神经网络缺少激活函数,那么它每一层的数据传递过程就变成了单纯的矩阵计算过程,无论数据传递了多少层,最后的输出都是输入的线性组合。
常见的激活函数如下:
1、sigmod
Sigmod函数是一种常见的S型函数,它能够将输入变量映射到0到1之间,其公式如下:
在这里插入图片描述

2、Tanh
Tanh函数是一种双曲正切函数,它是由双曲正弦函数与双曲余弦函数推导而来,同样将输入处理成0到1之间,与sigmod不同的是它的输出是零中心的,其公式如下:
在这里插入图片描述

3、Relu
Relu函数将输入和零进行比较,输出较大值,其公式如下:
在这里插入图片描述

4、Leaky Relu
Leaky Relu函数和Relu函数不同的是,当输入小于零时,将输入与常量gamma进行计算作为输出,其公式如下:
在这里插入图片描述
激活函数对比及适用场景参考:
神经网络基础知识之激活函数

4、神经网络结构

BP神经网络的输入层和输出层层数通常需要根据实际问题进行确定,而隐含层的层数即节点数的确定,通常没有一个确定的方法,一般通过设置不同的节点数然后比较其网络训练结果来选择最优数量,而节点数的范围可通过以下公式进行确定:
在这里插入图片描述
在这里插入图片描述

其中h为隐含层单元数,n为输入层单元数,m为输出层单元数,a为1到10之间的常数。

二、BP神经网络的实现

以数据预测为例,下面介绍BP神经网络的实现过程。
选用某省市的表层土壤重金属元素数据集作为实验数据,该数据集总共96组,随机选择其中的24组作为测试数据集,72组作为训练数据集。选取重金属Ti的含量作为待预测的输出特征,选取重金属Co、Cr、Mg、Pb作为模型的输入特征。

1、训练过程(BPNN.py)

#库的导入
import numpy as np
import pandas as pd#激活函数tanh
def tanh(x):return (np.exp(x)-np.exp(-x))/(np.exp(x)+np.exp(-x))
#激活函数偏导数
def de_tanh(x):return (1-x**2)#输入数据的导入
df = pd.read_csv("train.csv")
df.columns = ["Co", "Cr", "Mg", "Pb", "Ti"]
Co = df["Co"]
Co = np.array(Co)
Cr = df["Cr"]
Cr = np.array(Cr)
Mg=df["Mg"]
Mg=np.array(Mg)
Pb = df["Pb"]
Pb =np.array(Pb)
Ti = df["Ti"]
Ti = np.array(Ti)
samplein = np.mat([Co,Cr,Mg,Pb])
#数据归一化,将输入数据压缩至0到1之间,便于计算,后续通过反归一化恢复原始值
sampleinminmax = np.array([samplein.min(axis=1).T.tolist()[0],samplein.max(axis=1).T.tolist()[0]]).transpose()
sampleout = np.mat([Ti])
sampleoutminmax = np.array([sampleout.min(axis=1).T.tolist()[0],sampleout.max(axis=1).T.tolist()[0]]).transpose()
sampleinnorm = (2*(np.array(samplein.T)-sampleinminmax.transpose()[0])/(sampleinminmax.transpose()[1]-sampleinminmax.transpose()[0])-1).transpose()
sampleoutnorm = (2*(np.array(sampleout.T)-sampleoutminmax.transpose()[0])/(sampleoutminmax.transpose()[1]-sampleoutminmax.transpose()[0])-1).transpose()
noise = 0.03*np.random.rand(sampleoutnorm.shape[0],sampleoutnorm.shape[1])
sampleoutnorm += noisemaxepochs = 5000  #训练次数
learnrate = 0.001  #学习率
errorfinal = 0.65*10**(-3)  #停止训练误差阈值
samnum = 72  #输入数据数量
indim = 4  #输入层节点数
outdim = 1  #输出层节点数
hiddenunitnum = 8  #隐含层节点数#随机生成隐含层与输出层的权值w和阈值b
scale = np.sqrt(3/((indim+outdim)*0.5))  #最大值最小值范围为-1.44~1.44
w1 = np.random.uniform(low=-scale, high=scale, size=[hiddenunitnum,indim])
b1 = np.random.uniform(low=-scale, high=scale, size=[hiddenunitnum,1])
w2 = np.random.uniform(low=-scale, high=scale, size=[outdim,hiddenunitnum])
b2 = np.random.uniform(low=-scale, high=scale, size=[outdim,1])#errhistory存储误差
errhistory = np.mat(np.zeros((1,maxepochs)))#开始训练
for i in range(maxepochs):print("The iteration is : ", i)#前向传播,计算隐含层、输出层输出hiddenout = tanh((np.dot(w1,sampleinnorm).transpose()+b1.transpose())).transpose()networkout = tanh((np.dot(w2,hiddenout).transpose()+b2.transpose())).transpose()#计算误差值err = sampleoutnorm - networkoutloss = np.sum(err**2)/2print("the loss is :",loss)errhistory[:,i] = loss#判断是否停止训练if loss < errorfinal:break#反向传播,利用结果误差进行误差项的计算delta2 = err*de_tanh(networkout)delta1 = np.dot(w2.transpose(),delta2)*de_tanh(hiddenout)#计算输出层的误差项dw2 = np.dot(delta2,hiddenout.transpose())dw2 = dw2 / samnumdb2 = np.dot(delta2,np.ones((samnum,1)))db2 = db2 / samnum#计算隐含层的误差项dw1 = np.dot(delta1,sampleinnorm.transpose())dw1 = dw1 / samnumdb1 = np.dot(delta1,np.ones((samnum,1)))db1 = db1/samnum#对权值、阈值进行更新w2 += learnrate*dw2b2 += learnrate*db2w1 += learnrate*dw1b1 += learnrate*db1
print('更新的权重w1:',w1)
print('更新的偏置b1:',b1)
print('更新的权重w2:',w2)
print('更新的偏置b2:',b2)
print("The loss after iteration is :",loss)#保存训练结束后的权值、阈值,用于测试
np.save("w1.npy",w1)
np.save("b1.npy",b1)
np.save("w2.npy",w2)
np.save("b2.npy",b2)

2、测试过程(test.py)

#库的导入
import numpy as np
import pandas as pd#激活函数tanh
def tanh(x):return (np.exp(x)-np.exp(-x))/(np.exp(x)+np.exp(-x))
#输入数据的导入,用于测试数据的归一化与返归一化
df = pd.read_csv("train.csv")
df.columns = ["Co", "Cr", "Mg", "Pb", "Ti"]
Co = df["Co"]
Co = np.array(Co)
Cr = df["Cr"]
Cr = np.array(Cr)
Mg=df["Mg"]
Mg=np.array(Mg)
Pb = df["Pb"]
Pb =np.array(Pb)
Ti = df["Ti"]
Ti = np.array(Ti)
samplein = np.mat([Co,Cr,Mg,Pb])sampleinminmax = np.array([samplein.min(axis=1).T.tolist()[0],samplein.max(axis=1).T.tolist()[0]]).transpose()
sampleout = np.mat([Ti])
sampleoutminmax = np.array([sampleout.min(axis=1).T.tolist()[0],sampleout.max(axis=1).T.tolist()[0]]).transpose()#导入训练的权值、阈值
w1=np.load('w1.npy')
w2=np.load('w2.npy')
b1=np.load('b1.npy')
b2=np.load('b2.npy')#测试数据的导入
df = pd.read_csv("test.csv")
df.columns = ["Co", "Cr", "Mg", "Pb", "Ti"]
Co = df["Co"]
Co = np.array(Co)
Cr = df["Cr"]
Cr = np.array(Cr)
Mg=df["Mg"]
Mg=np.array(Mg)
Pb = df["Pb"]
Pb =np.array(Pb)
Ti = df["Ti"]
Ti = np.array(Ti)
input=np.mat([Co,Cr,Mg,Pb])#测试数据数量
testnum = 24#测试数据中输入数据的归一化
inputnorm=(2*(np.array(input.T)-sampleinminmax.transpose()[0])/(sampleinminmax.transpose()[1]-sampleinminmax.transpose()[0])-1).transpose()
#隐含层、输出层的计算
hiddenout = tanh((np.dot(w1,inputnorm).transpose()+b1.transpose())).transpose()
networkout = tanh((np.dot(w2,hiddenout).transpose()+b2.transpose())).transpose()
#对输出结果进行反归一化
diff = sampleoutminmax[:,1]-sampleoutminmax[:,0]
networkout2 = (networkout+1)/2
networkout2 = networkout2*diff+sampleoutminmax[0][0]
output1=networkout2.flatten()
output1=output1.tolist()
for i in range(testnum):output1[i] = float('%.2f'%output1[i])
print("the prediction is:",output1)#将输出结果与真实值进行对比,计算误差
output=Ti
rmse = (np.sum(np.square(output-output1))/len(output))**0.5
mae = np.sum(np.abs(output-output1))/len(output)
average_loss1=np.sum(np.abs((output-output1)/output))/len(output)
mape="%.2f%%"%(average_loss1*100)
f1 = 0
for m in range(testnum):f1 = f1 + np.abs(output[m]-output1[m])/((np.abs(output[m])+np.abs(output1[m]))/2)
f2 = f1 / testnum
smape="%.2f%%"%(f2*100)
print("the MAE is :",mae)
print("the RMSE is :",rmse)
print("the MAPE is :",mape)
print("the SMAPE is :",smape)#计算预测值与真实值误差与真实值之比的分布
A=0
B=0
C=0
D=0
E=0
for m in range(testnum):y1 = np.abs(output[m]-output1[m])/np.abs(output[m])if y1 <= 0.1:A = A + 1elif y1 > 0.1 and y1 <= 0.2:B = B + 1elif y1 > 0.2 and y1 <= 0.3:C = C + 1elif y1 > 0.3 and y1 <= 0.4:D = D + 1else:E = E + 1
print("Ratio <= 0.1 :",A)
print("0.1< Ratio <= 0.2 :",B)
print("0.2< Ratio <= 0.3 :",C)
print("0.3< Ratio <= 0.4 :",D)
print("Ratio > 0.4 :",E)

3、测试结果

在这里插入图片描述
注:由于每次初始化生成的参数不同,因此对参数设置相同的神经网络进行多次训练和预测,测试结果不会完全一致,此外测试结果的好坏也会受到隐含层节点数、学习率、训练次数等参数的影响。

4、参考源码及实验数据集

参考源码及实验数据集

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

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

相关文章

微服务-统一网关Gateway

网关的作用 对用户请求做身份认证、权限校验将用户请求路由到微服务&#xff0c;并实现负载均衡对用户请求做限流 搭建网关服务 创建新module&#xff0c;命名为Gateway&#xff0c;引入依赖&#xff08;1.SpringCloudGateway依赖&#xff1b;2.Eureka客户端依赖或者nacos的服…

【开源】基于SpringBoot的城市桥梁道路管理系统的设计和实现

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块三、系统展示四、核心代码4.1 查询城市桥梁4.2 新增城市桥梁4.3 编辑城市桥梁4.4 删除城市桥梁4.5 查询单个城市桥梁 五、免责说明 一、摘要 1.1 项目介绍 基于VueSpringBootMySQL的城市桥梁道路管理系统&#xff0c;支持…

40.查找练习题(王道2023数据结构第7章)

试题1&#xff08;王道7.2.4节综合练习5&#xff09;&#xff1a; 写出折半查找的递归算法。 #include<stdio.h> #include<stdlib.h> #include<string.h>#define MAXSIZE 10 #define ElemType int #define Status inttypedef struct{int data[MAXSIZE]; /…

Python---break关键字对for...else结构的影响

for循环中添加else结构 循环可以和else配合使用&#xff0c; else下方缩进的代码指的是当循环正常结束之后要执行的代码。 强调&#xff1a; 循环 正常结束&#xff0c;else之后要执行的代码。 非正常结束&#xff0c;其else中的代码是不会执行的。&#xff08;如遇到br…

[计算机提升] Windows系统各种开机启动方式介绍

1.14 开机启动 在Windows系统中&#xff0c;开机启动是指开启电脑后&#xff0c;自动运行指定的程序或服务的技术。一些程序或服务需要在开机后自动启动&#xff0c;以便及时响应用户操作&#xff0c;比如防安防软件、即时通信工具、文件同步软件等。 同时&#xff0c;一些系统…

Power BI 实现日历图,在一张图中展示天、周、月数据变化规律

《数据可视化》这本书里介绍了一个时间可视化的案例&#xff08;如下图所示&#xff09;&#xff0c;以日历图的形式展示数据的变化&#xff0c;可以在一张图上同时观察到&#xff1a;&#xff08;1&#xff09;每一天的数据变化&#xff1b;&#xff08;2&#xff09;随周变化…

图纸管理制度 《五》

1、存档文件应由专人管理&#xff0c;其他人未征得管理人员同意&#xff0c;不得随意翻阅查看。 2、档案管理人员要认真贯彻执行公司相关制度&#xff0c;严禁泄露档案材料中的秘密。 彩虹图纸管理软件_图纸管理系统_图纸文档管理软件系统_彩虹EDM【官网】彩虹EDM图纸管理软件…

Unity C#中LuaTable、LuaArrayTable、LuaDictTable中数据的增删改查

LuaTable、LuaArrayTable、LuaDictTable中数据的增删改查 介绍Lua表lua表初始化lua移除引用lua中向表中添加数据lua中表中移除数据lua表中连接数据lua表中数据排序获取lua表长度获取表中最大值 UnityC#中LuaTableUnityC#中LuaArrayTable、LuaDictTable、LuaDictTable<K,V>…

【C程序设计】用心浇灌<C程序>

目录 数据类型 整数类型 实例 浮点类型 void 类型 类型转换 数据类型 在 C 语言中&#xff0c;数据类型指的是用于声明不同类型的变量或函数的一个广泛的系统。变量的类型决定了变量存储占用的空间&#xff0c;以及如何解释存储的位模式。 C 中的类型可分为以下几种&…

云计算与ai人工智能对高防cdn的发展

高防CDN&#xff08;Content Delivery Network&#xff09;作为网络安全领域的一项关键技术&#xff0c;致力于保护在线内容免受各种网络攻击&#xff0c;包括分布式拒绝服务攻击&#xff08;DDoS&#xff09;等。然而&#xff0c;随着人工智能&#xff08;AI&#xff09;和大数…

Redis快速上手篇七(集群-六台虚拟机)

Redis集群 主从复制的场景无法吗满足主机单点故障时需要引入集群配置 一般数据库要处理的读请求远大于写请求 &#xff0c;针对这种情况&#xff0c;我们优化数据库可以采用读写分离的策略。我们可以部 署一台主服务器主要用来处理写请求&#xff0c;部署多台从服务器 &#…

【luckfox】添加压力传感器hx711

文章目录 前言一、参考资料二、电路图三、驱动四、makefile——添加驱动五、dts——使能gpio5.1 参考5.2 改动1—— hx117节点5.3 改动2——引脚节点5.4 已经被定义的引脚5.5 gpio源码 六、改动总结——使能hx711七、验证驱动添加八、编写测试文件8.1 测试代码8.2 配置编译环境…

解决:谷歌浏览器访问http时,自动转https访问的问题

问题背景&#xff1a;某个系统网站&#xff0c;之前一直用https域名访问&#xff0c;现在改成http域名后&#xff0c;用http访问&#xff0c;谷歌浏览器会自动跳转到https。 解决方法&#xff1a; 在浏览器中输入网址&#xff1a;chrome://net-internals/#hsts -》 在“Delete…

Jmeter压测实战:Jmeter二次开发之自定义函数

​1 前言 Jmeter是Apache基金会下的一款应用场景非常广的压力测试工具&#xff0c;具备轻量、高扩展性、分布式等特性。Jmeter已支持实现随机数、计数器、时间戳、大小写转换、属性校验等多种函数&#xff0c;方便使用人员使用。如果在使用过程中存在和业务强耦合的常用功能函…

【广州华锐互动】VR公司工厂消防逃生演练带来沉浸式的互动体验

在工业生产过程中&#xff0c;安全问题始终是我们不能忽视的重要环节。特别是火灾事故&#xff0c;不仅会造成重大的经济损失&#xff0c;更会威胁到员工的生命安全。传统的消防安全训练方法&#xff0c;如讲座、实地演练等&#xff0c;虽然具有一定的效果&#xff0c;但是无法…

Matlab绘制散点的95%置信区间图

Matlab常绘制95%置信区间图&#xff0c;主要使用到patch函数。 如果直接使用散点进行拟合&#xff0c;在patch函数绘制95%置信区间时&#xff0c;会绘制的很乱&#xff0c;这个是由于patch函数所导致的&#xff0c;其实这个问题在 Matlab绘制95%置信区间图 中已经讲到过&#…

【教3妹学编程-java实战4】Map遍历删除元素的几种方法

插&#xff1a; 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站。 坚持不懈&#xff0c;越努力越幸运&#xff0c;大家一起学习鸭~~~ 2哥 :3妹&#xff0c;今天是周末&#xff0c;又不用上…

51单片机复位电容计算与分析(附带Proteus电路图)

因为iC x (dU/dt).在上电瞬间&#xff0c;U从0变化到U,所以这一瞬间就是通的&#xff0c;然后这就是一个直流回路&#xff0c;因为电容C直流中是断路的&#xff0c;所以就不通了。 然后来分析一下这个电容的电压到底是能不能达到单片机需要的复位电压。 这是一个线性电容&…

基于springboot实现休闲娱乐代理售票平台系统项目【项目源码+论文说明】计算机毕业设计

基于springboot实现休闲娱乐代理售票平台系统演示 摘要 网络的广泛应用给生活带来了十分的便利。所以把休闲娱乐代理售票管理与现在网络相结合&#xff0c;利用java技术建设休闲娱乐代理售票系统&#xff0c;实现休闲娱乐代理售票的信息化。则对于进一步提高休闲娱乐代理售票管…

【黑产攻防道03】利用JS参数更新检测黑产的协议破解

任何业务在运营一段时间之后都会面临黑产大量的破解。验证码和各种爬虫的关系就像猫和老鼠一样, 会永远持续地进行博弈。极验根据十一年和黑产博弈对抗的经验&#xff0c;将黑产的破解方式分为三类&#xff1a; 1.通过识别出验证码图片答案实现批量破解验证&#xff0c;即图片…