神经网络之反向传播算法(加入Nesterov动量的误差反向传播算法)

文章目录

  • 1、Nesterov动量
  • 2、结合Nesterov动量的误差反向传播算法
  • 3、算法实现
    • 3.1 训练过程
    • 3.2 测试过程
  • 4、参考源码及数据集

1、Nesterov动量

在动量法提出不久之后,Nesterov动量也随之被提了出来,此方法属于动量法的进一步发展,与动量法不同的是,在动量法中会用每一次迭代中计算得来动量项作为参数调整的方向和速率,而在Nesterov动量法中,在计算新的动量项之前,会用当前的动量项进行一次参数的调整,然后用调整的临时参数计算梯度值,然后再利用该梯度值进行新的动量项的计算,最后进行参数的更新,此过程可以看作在动量法中添加了一个较正因子。Nesterov动量法的核心思想在于在每次计算梯度的时候使用下一次的权重,然后将下一次的变化情况反映在这次计算的梯度上。
Nesterov动量法的具体步骤如下:

  1. 使用当前的动量项进行参数的临时调整;
  2. 使用调整后的临时参数计算出临时梯度值g;
  3. 使用临时梯度值计算获得新的动量项;
  4. 利用新的动量项对参数进行调整以获得新的参数值。

基于动量项的参数更新原理参考:
神经网络之反向传播算法(加入动量momentum的误差反向传播算法)
梯度g的计算原理参考:
神经网络之反向传播算法(梯度、误差反向传播算法BP)

2、结合Nesterov动量的误差反向传播算法

将加入动量法的误差反向传播算法应用于神经网络参数优化时的算法步骤如下:

  1. 随机初始化神经网络中所有的参数;
  2. 设置学习率、动量参数,设置变量v的初始值为0;
  3. 输入数据,利用变量v(动量项)对参数进行临时更新;
  4. 按照前向传播过程计算网络的输出;
  5. 使用损失函数计算误差值;
  6. 根据误差值计算出隐含层、输出层每个参数的临时梯度值;
  7. 利用临时梯度值计算变量v;
  8. 利用变量v对参数进行更新;
  9. 重复步骤3到步骤8,当满足停止迭代条件时输出训练后的参数。

误差反向传播算法BP原理参考:
神经网络之反向传播算法(梯度、误差反向传播算法BP)
参数初始化方法参考:
神经网络基础知识之参数初始化

3、算法实现

以数据预测为例,下面介绍加入Nesterov动量的误差反向传播算法的实现过程,将加入Nesterov动量的误差反向传播算法应用于普通的三层神经网络(输入层、隐含层、输出层)的反向传播过程。
选用某省市的表层土壤重金属元素数据集作为实验数据,该数据集总共96组,随机选择其中的24组作为测试数据集,72组作为训练数据集。选取重金属Ti的含量作为待预测的输出特征,选取重金属Co、Cr、Mg、Pb作为模型的输入特征。

3.1 训练过程

#库的导入
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)

# 梯度加权平均函数,0.9为衰减系数
def accumulation(v,delta):
    v = 0.9 * v + 0.1 * delta
    return  v

# 参数更新量计算函数
def adjust(v):
    change = (-0.01)*v
    return change

#输入数据的导入
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()
sampleinmax = np.array([sampleinnorm.max(axis=1).T.tolist()]).transpose()
sampleinmin = np.array([sampleinnorm.min(axis=1).T.tolist()]).transpose()
#为归一化后的数据添加噪声
noise = 0.03*np.random.rand(sampleoutnorm.shape[0],sampleoutnorm.shape[1])
sampleoutnorm += noise
sampleinnorm = np.mat(sampleinnorm)

maxepochs = 1000  #训练次数
errorfinal = 0.65*10**(-3)  #停止训练误差阈值
samnum = 72  #输入数据数量
indim = 4  #输入层节点数
outdim = 1  #输出层节点数
hiddenunitnum = 8  #隐含层节点数

#利用归一化后的输入数据初始化参数w1、b1、w2、b2
dvalue = sampleinmax-sampleinmin
valuemid=(sampleinmin+sampleinmax)/2
wmag=0.7*(hiddenunitnum**(1/indim))
rand1=np.random.rand(hiddenunitnum,outdim)
rand2=np.random.randn(hiddenunitnum,indim)
rand1=rand1*wmag
rand2=rand2*wmag
b1=rand1-np.dot(rand2,valuemid)
for i in range(hiddenunitnum):
    for j in range(indim):
        rand2[i][j]=(2*rand2[i][j])/dvalue[j]
w1=rand2
w2 = np.random.uniform(low=-1, high=1, size=[outdim,hiddenunitnum])
b2 = np.random.uniform(low=-1, high=1, size=[outdim,1])

#参数w1、b1、w2、b2均为矩阵形式参与计算,其形状依次为8*4,8*1,1*8,1*1
w1 = np.mat(w1)
b1 = np.mat(b1)
w2 = np.mat(w2)
b2 = np.mat(b2)

#errhistory存储每次训练后的预测值与真实值的误差
errhistory = []

#vw2、vb2、vw1、vb1分别保存参数w1、b1、w2、b2的梯度加权平均值,其形状与w1、b1、w2、b2一一对应
vw2 = np.zeros((1,8))
vb2 = np.zeros((1,1))
vw1 = np.zeros((8,4))
vb1 = np.zeros((8,1))

#deltaw1、deltab1、deltaw2 、deltab2分别保存参数w1、b1、w2、b2的临时更新量
deltaw2 = np.zeros((1,8))
deltab2 = np.zeros((1,1))
deltaw1 = np.zeros((8,4))
deltab1 = np.zeros((8,1))

for i in range(maxepochs):
    #前向传播
    # 利用参数临时更新量对参数w1、b1、w2、b2进行临时更新
    w1 += deltaw1
    b1 += deltab1
    w2 += deltaw2
    b2 += deltab2
    #计算隐含层输出hiddenout,输出层输出networkout
    hiddenout = tanh((np.dot(w1,sampleinnorm).transpose()+b1.transpose())).transpose()
    networkout = np.dot(w2,hiddenout).transpose()+b2.transpose()
    for j in range(samnum):
        networkout[j,:] = tanh(networkout[j,:])
    networkout = networkout.transpose()
    # 计算损失函数
    err = sampleoutnorm - networkout
    loss = np.sum(np.abs(err))/samnum
    sse = np.sum(np.square(err))
    #判断是否满足停止训练条件
    errhistory.append(sse)
    if sse < errorfinal:
        break
    #反向传播
    #利用损失函数计算结果和激活函数偏导数,来计算参数w1、b1、w2、b2的梯度值
    delta2 = np.zeros((outdim,samnum))
    for n in range(samnum):
        delta2[:,n] = (-1) * err[:,n] * de_tanh(networkout[:,n])
    delta1 = np.zeros((hiddenunitnum,samnum))
    for e in range(samnum):
        for f in range(hiddenunitnum):
            delta1[f,e] = w2[:,f] * delta2[:,e] * de_tanh(hiddenout[f,e])
    dw2now = np.dot(delta2,hiddenout.transpose()) #1*8
    db2now = np.dot(delta2,np.ones((samnum,1))) #1*1
    dw1now = np.dot(delta1,sampleinnorm.transpose()) #8*4
    db1now = np.dot(delta1,np.ones((samnum,1))) #8*1

    # 先更新输出层参数
    # w2更新,依次更新w2的梯度加权平均值,参数更新量,w2
    for m in range(hiddenunitnum):
        vw2[:,m] = accumulation(vw2[:,m],dw2now[:,m])
        deltaw2[:,m] = adjust(vw2[:,m])
        w2[:,m] = w2[:,m] + deltaw2[:,m]

    #b2更新,依次更新b2的梯度加权平均值,参数更新量,b2
    vb2 = accumulation(vb2,db2now)
    deltab2 = adjust(vb2)
    b2 = b2 + deltab2

    # 更新隐含层参数
    #w1更新,依次更新w1的梯度加权平均值,参数更新量,w1
    for a in range(hiddenunitnum):
        for b in range(indim):
            vw1[a,b] = accumulation(vw1[a,b],dw1now[a,b])
            deltaw1[a,b] = adjust(vw1[a,b])
            w1[a,b] = w1[a,b] + deltaw1[a,b]

    #b1更新,依次更新b1的梯度加权平均值,参数更新量,b1
    for n in range(hiddenunitnum):
        vb1[n,:] = accumulation(vb1[n,:],db1now[n,:])
        deltab1[n,:] = adjust(vb1[n,:])
        b1[n,:] = b1[n,:] + deltab1[n,:]


    print("the generation is:",i,",the loss is:",loss)

#达到最大训练次数,保存此时的参数w1、b1、w2、b2
np.save("w1.npy",w1)
np.save("b1.npy",b1)
np.save("w2.npy",w2)
np.save("b2.npy",b2)

3.2 测试过程

测试过程只需要利用训练过程生成的相关参数,对测试数据执行一次前向传播过程来获得预测值,之后可使用相关的误差指标对预测值进行评价,详细的测试过程源码见参考源码及数据集。
在这里插入图片描述

4、参考源码及数据集

参考源码及数据集

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

基于windows11配置深度学习环境包含WSL2配置ubuntu20.04

基于windows11配置深度学习环境包含WSL2配置ubuntu20.04目录平台WSL2 系统准备(Windows Subsystem of Linux)安装WSL2基于WSL2中的Ubuntu安装CUDA和cudnnCUDA 安装目录 平台 系统 : windows11 专业版 CPU Intel I7 8750hq 显卡&#xff1a;Nvidia GTX1060移动端 显卡驱动版本…

安装Windows11提示这台电脑不符合安装此版本的Windows所需的最低系统要求

现在很多用户都会选择用U盘来安装系统&#xff0c;最新有用户在使用U盘安装Win11系统的时候&#xff0c;结果安装到第一步就提示这台电脑无法运行Windows11&#xff0c;这台电脑不符合安装此版本的Windows所需的最低系统要求。下面小编就来教大家解决此问题的方法。 问题解析&a…

BIO/NIO/AIO/IO多路复用简介

bio、nio、aio、io多路复用、reactor模式io&#xff0c;在将IO的时候&#xff0c;是不是都遇到过这些概念&#xff0c;也有种傻傻分不清&#xff1f;甚至别人在大谈特谈的时候&#xff0c;一会nio&#xff0c;一会io多路复用&#xff0c;一会又搞到reactor模式上去了&#xff1…

一文搞懂原型和原型链

在了解原型和原型链之前首先得明确它俩是什么东西&#xff1a; 原型&#xff1a;prototype 又称显示原型 1、原型是一个普通对象 2、只有构造函数才具备该属性 3、公有属性可操作 隐式原型&#xff1a;__proto__ 1、只有对象(普通对象、函数对象&#xff09;具备 2、私有的对…

《Spring系列》第2章 解析XML获取Bean

一、基础代码 Spring加载bean实例的代码 public static void main(String[] args) throws IOException {// 1.获取资源Resource resource new ClassPathResource("bean.xml");// 2.获取BeanFactoryDefaultListableBeanFactory factory new DefaultListableBeanFa…

Airtest自动化测试工具实战演练

一开始知道Airtest大概是在年初的时候&#xff0c;当时&#xff0c;看了一下官方的文档&#xff0c;大概是类似Sikuli的一个工具&#xff0c;主要用来做游戏自动化的&#xff0c;通过截图的方式用来解决游戏自动化测试的难题。最近&#xff0c;移动端测试的同事尝试用它的poco库…

iwebsec靶场-命令执行漏洞

漏洞简介 命令执行漏洞&#xff08;Command Injection&#xff09;是一种常见的安全漏洞&#xff0c;也被称为代码注入漏洞。它允许攻击者将恶意代码注入到受攻击的应用程序中&#xff0c;从而可以在应用程序的上下文中执行任意命令。 命令执行漏洞通常出现在Web应用程序中&…

好的表单设计应该遵循什么规则?

在数字化时代&#xff0c;表单已经成为了人们生活中不可或缺的一部分。它们可能是网站注册表格、调查问卷、订单表格或者其他类型的表格。无论表单的类型是什么&#xff0c;都必须经过精心设计才能提供良好的用户体验。在本文中&#xff0c;我们将探讨如何设计一份用户体验好的…

Redis缓存双写一致性

目录双写一致性Redis与Mysql双写一致性canal配置流程代码案例双写一致性理解缓存操作细分缓存一致性多种更新策略挂牌报错,凌晨升级先更新数据库,在更新缓存先删除缓存,在更新数据库先更新数据库,在删除缓存延迟双删策略总结双写一致性 Redis与Mysql双写一致性 canal 主要是…

低代码开发公司:用科技强力开启产业分工新时代!

实现办公自动化&#xff0c;是不少企业的共同追求。低代码开发公司会遵循时代发展规律&#xff0c;注入强劲的科技新生力量&#xff0c;在低代码开发市场厚积爆发、努力奋斗&#xff0c;推动企业数字化转型升级&#xff0c;为每一个企业的办公自动化升级创新贡献应有的力量。 一…

【数据结构与算法】堆的实现(附源码)

目录 一.堆的概念及结构 二.接口实现 A.初始化 Heapinit 销毁 Heapdestroy B.插入 Heappush 向上调整 AdjustUp 1.Heappush 2.AdjustUp C.删除 Heappop 向下调整 AdjustDown D.堆的判空 Heapempty 堆顶数据 Heaptop 堆的大小 Heapsize 三.源码 Heap.h He…

【模板】带权并查集

文章目录1. 奇偶游戏2. 银河英雄传说1. 奇偶游戏 239. 奇偶游戏 题意&#xff1a; 依次给出多个区间的含 111 的个数的奇偶性&#xff0c;找出第一个不符合的答案的回答。 思路&#xff1a; 已知区间[a,b][a,b][a,b][b,c][b,c][b,c]的奇偶性&#xff0c;那么具有传递性&…

分享一个国内可用的免费ChatGPT网站(自己写的)

背景 ChatGPT作为一种基于人工智能技术的自然语言处理工具&#xff0c;近期的热度直接沸腾&#x1f30b;。 作为一个程序员&#xff0c;我也忍不住做了一个基于ChatGPT的网站&#xff0c;免费&#xff01;免登陆&#xff01;&#xff01;国内可直接对话ChatGPT&#xff0c;也…

10.线性表代码实战

10.1 与408关联解析及本节内容介绍 链表比顺序表出现的顺序更加的频繁。 10.2线性表地顺序表示原理解析 线性表的特点&#xff1a; &#xff08;1&#xff09;表中的元素的个数是有限的 &#xff08;2&#xff09;表中元素的数据类型相同。意味着每一个元素占用相同大小的空…

使用Dism++和360安全卫士搞定Windows10离线升级

Windows10有很多版本&#xff0c;常见的由1903、1909、20H1、21H2等&#xff0c;在离线状态下&#xff0c;很难下载到匹配的升级补丁。期间尝试多种方法均失败&#xff0c;最后用Dism和360安全卫士组合拳搞定。 1、使用下载补丁&#xff0c;升级失败 比如这里介绍了常见补丁&a…

【SL101】 传感器接入chirpstack平台

【SL101】 传感器接入chirpstack平台使用硬件SL100工程师答疑chirpstack 中 net-server 使能 80-87 频段网关开启80-87 频段设备传感器端配置频点连接成功测试结果---chirpstackSL100系列温湿度传感器产品&#xff08;墨水屏版&#xff09;接入chirpstack 平台笔记记录 使用硬件…

mysql学习之数据系统概述

☀️马上要成为打工人&#xff0c;这几天把前面的知识都捡了捡&#xff0c;发现自己对关系数据库这块的学习还有所缺失&#xff0c;于是本章开始学习mysql 这里写目录标题1. 数据库系统的发展1.1 人工管理阶段1.2 文件系统阶段1.3 数据库阶段1.4 大数据阶段2 数据库系统的组成2…

了解这7个Node.js库,让你的开发效率提升不止一点点

Node.js是一个流行的JavaScript运行时环境&#xff0c;拥有庞大的生态系统和丰富的库&#xff0c;使得在Node.js上构建高效、可靠的应用程序变得非常容易。在这篇文章中&#xff0c;我们将分享七个有用的Node.js库&#xff0c;它们可以提高您的工作效率&#xff0c;让您更轻松地…

android:手搓一个即时消息聊天框(包含消息记录)

先看一下效果 1.后端 要实现这个&#xff0c;先说一下后端要实现的接口 1.创建会话id 传入“发送id”和“接收id”给服务端&#xff0c;服务端去创建“会话id” 比如 get请求&#xff1a;http://xxxx:8110/picasso/createSession?fromUserId1&toUserId2 返回seesionId…

【SSconv:全色锐化:显式频谱-空间卷积】

SSconv: Explicit Spectral-to-Spatial Convolution for Pansharpening &#xff08;SSconv&#xff1a;用于全色锐化的显式频谱-空间卷积&#xff09; 全色锐化的目的是融合高空间分辨率的全色&#xff08;PAN&#xff09;图像和低分辨率的多光谱&#xff08;LR-MS&#xff…