神经网络之反向传播算法(自适应矩估计算法Adam变形形式之Adamax、Nadam)

news2024/11/25 0:31:04

文章目录

  • 自适应矩估计算法(Adam)的两种变形形式
  • 1、Adamax算法原理
  • 2、Nadam算法原理
  • 3、算法实现
    • 3.1 Adamax训练过程
    • 3.2 Adamax测试过程及结果
    • 3.3 Nadam训练过程
    • 3.4 Nadam测试过程及结果
  • 4、参考源码及数据集

自适应矩估计算法(Adam)的两种变形形式

自适应矩估计算法的基础上还进一步提出了两种变形,一种变形的英文名称为Adamax,另一种变形的英文名称为Nadam。
自适应矩估计算法原理参考:
神经网络之反向传播算法(自适应矩估计算法Adam)

1、Adamax算法原理

Adamax主要对最后参数的更新量计算公式进行了调整,原式中的分母部分为对二阶矩估计进行如下开方:
在这里插入图片描述
而Adamax采用了下列公式进行该部分的确定:
在这里插入图片描述
ρ_2为衰减率,g_t为当前第t次迭代时的梯度值。
梯度g的计算原理参考:
神经网络之反向传播算法(梯度、误差反向传播算法BP)

之后采用下列公式对参数的调整量进行计算:
在这里插入图片描述

此算法的主要特点在于为学习率提供了一个更加简单的上限范围。

2、Nadam算法原理

Nadam相对Adamax来说更加简单,此算法相当于将Nestrov动量法的临时梯度思想引入了自适应矩估计算法之中,在每次对梯度进行计算时先获得一个参数临时更新量,对参数进行临时更新后计算获得临时梯度,利用临时梯度对一阶矩与二阶矩进行估计,并使用临时一阶矩与二阶矩来计算参数的更新量。
Nestrov动量法原理参考:
神经网络之反向传播算法(加入Nesterov动量的误差反向传播算法)

3、算法实现

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

3.1 Adamax训练过程

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

#用于计算一阶矩估计与二阶矩估计的函数,其中s为一阶矩估计,r为二阶矩估计,delta为梯度值,
#,0.9和0.999分别表示两个衰减系数,0.1为1-衰减系数的计算结果
def accumulation(s,r,delta):
    s = 0.9 * s + 0.1 * delta
    r = max((0.999*r),abs(delta))
    return  s,r
#参数更新函数,w为待更新参数,s与r分别为修正后的一阶矩估计和二阶矩估计
def adjust(s,r,w):
    change1 =r + 0.000001
    change2 =s/change1
    change = (-0.001)*change2
    w = w + change
    return w

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

#输入数据的导入
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])
sampleout = np.mat([Ti])
#数据归一化,将输入数据压缩至0到1之间,便于计算,后续通过反归一化恢复原始值
sampleinminmax = np.array([samplein.min(axis=1).T.tolist()[0],samplein.max(axis=1).T.tolist()[0]]).transpose()
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)

#利用归一化后的输入数据初始化参数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 = []

#sw1、sb1,sw2,sb2分别保存参数w1、b1、w2、b2的一阶矩估计,其形状与w1、b1、w2、b2一一对应
sw2 = np.zeros((1,8))
sb2 = np.zeros((1,1))
sw1 = np.zeros((8,4))
sb1 = np.zeros((8,1))

#rw1、rb1,rw2,rb2分别保存参数w1、b1、w2、b2的二阶矩估计,其形状与w1、b1、w2、b2一一对应
rw2 = np.zeros((1,8))
rb2 = np.zeros((1,1))
rw1 = np.zeros((8,4))
rb1 = np.zeros((8,1))

#t用于对一阶矩估计和二阶矩估计进行修正,随训练次数不断累加
t = 0
for i in range(maxepochs):
    t = t + 1
    #前向传播
    #计算隐含层输出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更新
    for m in range(hiddenunitnum):
        #计算一阶矩估计sw2和二阶矩估计rw2
        sw2[:, m],rw2[:,m] = accumulation(sw2[:,m],rw2[:,m],dw2now[:,m])
        #使用t值对一阶矩估计进行修正
        saw2 = sw2[:,m] / (1 - (0.9**t))
        #利用修正后的一阶矩估计和二阶矩估计对w2进行更新
        w2[:,m] = adjust(saw2,rw2[:,m],w2[:,m])

    #b2更新
    #计算一阶矩估计sb2和二阶矩估计rb2
    sb2,rb2 = accumulation(sb2,rb2,db2now)
    #使用t值对一阶矩估计进行修正
    sab2 = sb2/(1 - (0.9**t))
    #利用修正后的一阶矩估计和二阶矩估计对b2进行更新
    b2 = adjust(sab2, rb2, b2)

    #更新隐含层参数
    #w1更新
    #计算一阶矩估计sw1和二阶矩估计rw1
    for a in range(hiddenunitnum):
        for b in range(indim):
            sw1[a,b],rw1[a,b] = accumulation(sw1[a,b],rw1[a,b],dw1now[a,b])
            #使用t值对一阶矩估计进行修正
            saw1 = sw1[a,b]/(1 - (0.9**t))
            #利用修正后的一阶矩估计和二阶矩估计对w1进行更新
            w1[a,b] = adjust(saw1,rw1[a,b],w1[a,b])

    #b1更新
    #计算一阶矩估计sb1和二阶矩估计rb1
    for n in range(hiddenunitnum):
        sb1[n,:],rb1[n,:] = accumulation(sb1[n,:],rb1[n,:],db1now[n,:])
        #使用t值对一阶矩估计进行修正
        sab1 = sb1[n,:]/(1 - (0.9**t))
        #利用修正后的一阶矩估计和二阶矩估计对b1进行更新
        b1[n,:] = adjust(sab1,rb1[n,:],b1[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 Adamax测试过程及结果

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

3.3 Nadam训练过程

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


#用于计算一阶矩估计与二阶矩估计的函数,其中s为一阶矩估计,r为二阶矩估计,delta为梯度值,
#,0.9和0.999分别表示两个衰减系数,0.1和0.001均为1-衰减系数的计算结果
def accumulation(s,r,delta):
    s = 0.9 * s + 0.1 * delta
    r = 0.999 * r + 0.001 * (delta**2)
    return  s,r
#参数更新量计算函数,w为待更新参数,s与r分别为修正后的一阶矩估计和二阶矩估计
def adjust(s,r):
    change1 =r**0.5 + 0.000001
    change2 =s/change1
    #0.001为学习率
    change = (-0.001)*change2
    return change



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

#输入数据的导入
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])
sampleout = np.mat([Ti])
#数据归一化,将输入数据压缩至0到1之间,便于计算,后续通过反归一化恢复原始值
sampleinminmax = np.array([samplein.min(axis=1).T.tolist()[0],samplein.max(axis=1).T.tolist()[0]]).transpose()
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)

#利用归一化后的输入数据初始化参数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 = []

#sw1、sb1,sw2,sb2分别保存参数w1、b1、w2、b2的一阶矩估计,其形状与w1、b1、w2、b2一一对应
sw2 = np.zeros((1,8))
sb2 = np.zeros((1,1))
sw1 = np.zeros((8,4))
sb1 = np.zeros((8,1))

#rw1、rb1,rw2,rb2分别保存参数w1、b1、w2、b2的二阶矩估计,其形状与w1、b1、w2、b2一一对应
rw2 = np.zeros((1,8))
rb2 = np.zeros((1,1))
rw1 = np.zeros((8,4))
rb1 = 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))

#t用于对一阶矩估计和二阶矩估计进行修正,随训练次数不断累加
t = 0
for i in range(maxepochs):
    t = t + 1
    #利用参数临时更新量对参数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更新
    for m in range(hiddenunitnum):
        #计算一阶矩估计sw2和二阶矩估计rw2
        sw2[:, m], rw2[:, m] = accumulation(sw2[:, m], rw2[:, m], dw2now[:, m])
        #使用t值对一阶矩估计和二阶矩估计进行修正
        saw2 = sw2[:, m] / (1 - (0.9 ** t))
        raw2 = rw2[:, m] / (1 - (0.999 ** t))
        #获得参数更新量,并作为下一次训练时的临时更新量
        deltaw2[:,m] = adjust(saw2,raw2)
        #对参数w2进行更新
        w2[:,m] += deltaw2[:,m]

    #b2更新
    #计算一阶矩估计sb2和二阶矩估计rb2
    sb2,rb2 = accumulation(sb2,rb2,db2now)
    #使用t值对一阶矩估计和二阶矩估计进行修正
    sab2 = sb2/(1 - (0.9**t))
    rab2 = rb2/(1-(0.999**t))
    #获得参数更新量,并作为下一次训练时的临时更新量
    deltab2 = adjust(sab2,rab2)
    #对参数b2进行更新
    b2 += deltab2

    #更新隐含层参数
    #w1更新
    #计算一阶矩估计sw1和二阶矩估计rw1
    for a in range(hiddenunitnum):
        for b in range(indim):
            #计算一阶矩估计sw1和二阶矩估计rw1
            sw1[a,b],rw1[a,b] = accumulation(sw1[a,b],rw1[a,b],dw1now[a,b])
            #使用t值对一阶矩估计和二阶矩估计进行修正
            saw1 = sw1[a,b]/(1 - (0.9**t))
            raw1 = rw1[a,b]/(1 - (0.999**t))
            #获得参数更新量,并作为下一次训练时的临时更新量
            deltaw1[a,b] = adjust(saw1,raw1)
            #对参数w1进行更新
            w1[a, b] += deltaw1[a,b]

    #b1更新
    #计算一阶矩估计sb1和二阶矩估计rb1
    for n in range(hiddenunitnum):
        #计算一阶矩估计sb1和二阶矩估计rb1
        sb1[n,:],rb1[n,:] = accumulation(sb1[n,:],rb1[n,:],db1now[n,:])
        #使用t值对一阶矩估计和二阶矩估计进行修正
        sab1 = sb1[n,:]/(1 - (0.9**t))
        rab1 = rb1[n,:]/(1 - (0.999**t))
        #获得参数更新量,并作为下一次训练时的临时更新量
        deltab1[n,:] = adjust(sab1,rab1)
        #对参数b1进行更新
        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.4 Nadam测试过程及结果

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

4、参考源码及数据集

Adamax参考源码及数据集
Nadam参考源码及数据集

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

打造安全无忧软件应用的十大最佳实践

安全无忧的软件开发最佳实践实在是很有必要&#xff0c;因为安全风险无处不在。在网络攻击盛行的时代&#xff0c;它们可能影响到每个人&#xff0c;包括个人、公司和政府。因此&#xff0c;确保软件开发的安全性至关重要。 本篇文章将解释了什么是安全的软件&#xff0c;如何…

你了解C语言中的柔性数组吗?

本篇博客主要讲解C99中的新语法&#xff1a;柔性数组。 1.什么是柔性数组&#xff1f; 柔性数组就是大小可以变化的数组。 注意跟C99中的变长数组区分开来&#xff0c;变长数组指的是可以使用变量来指定大小&#xff0c;并且不能初始化的数组&#xff0c;比如&#xff1a; i…

实例方法、类方法、静态方法、实例属性、类属性

背景&#xff1a;今天在复习类相关知识的时候&#xff0c;突然想到这几种类型的方法的区别和用法&#xff0c;感觉有点模棱两可&#xff0c;于是总结一下&#xff0c;加深记忆。 定义&#xff1a;想要区别和理解几种方法&#xff0c;首先要定义一个类&#xff0c;要在类中加深…

mysql如何修改时区

mysql 里CST时区的坑 一、 问题简述 mysql里CST时区是个非常坑的概念&#xff0c;因为在mysql里CST既表示中国也表示美国的时区。但是在JDK代码里&#xff0c;CST这个字符串被理解为CenTral Standard Time&#xff08;USA&#xff09;&#xff08;GMT-6&#xff09;&#xff…

java框架都有哪些

Java框架是对Java2中的一些基本概念进行抽象&#xff0c;封装成能被开发者使用的类库&#xff0c;使之能快速开发应用程序。它让开发者能够专注于业务逻辑而不是实现细节。可以说&#xff0c; Java框架是 Java开发中的重要组成部分&#xff0c;它极大地方便了开发者。下面为大家…

腾讯云GPU服务器NVIDIA P40 GPU、P4、T4和GPU自由卡详解

腾讯云GPU云服务器&#xff0c;GPU云服务器实例可选GN8机型、GN6S机型、GN7机型等规格&#xff0c;搭载 NVIDIA P40 GPU&#xff0c;最长可3年&#xff0c;云服务器吧来详细说下腾讯云GPU云服务器&#xff1a; 目录 腾讯云GPU云服务器 腾讯云GPU自由卡 腾讯云GPU云服务器 腾…

选品趋势分析 | 2023开斋节将至,穆斯林时尚在TIKTOK上增长势头正劲!

2023年Q1 穆斯林时尚的销售额环比2022年Q4 暴涨153%&#xff0c;领跑TikTok电商大盘&#xff0c;成为2023年Q1的超级黑马品类。加之开斋节临近&#xff0c;人民陆续开始为庆祝开斋节作采购准备&#xff0c;购物需求相应激增&#xff0c;其中&#xff0c;穆斯林群体会在开斋节的…

GELU激活函数

GELU是一种常见的激活函数&#xff0c;全称为“Gaussian Error Linear Unit”, 作为2020年提出的优秀激活函数&#xff0c;越来越多的引起了人们的注意。 GELU (Gaussian Error Linear Units) 是一种基于高斯误差函数的激活函数&#xff0c;相较于 ReLU 等激活函数&#xff0c…

java版工程项目管理系统-功能清单 图文解析

Java版工程项目管理系统 Spring CloudSpring BootMybatisVueElementUI前后端分离 功能清单如下&#xff1a; 首页 工作台&#xff1a;待办工作、消息通知、预警信息&#xff0c;点击可进入相应的列表 项目进度图表&#xff1a;选择&#xff08;总体或单个&#xff09;项目显示…

MySQL事务的四大特性及事务的隔离级别

什么是事务&#xff1f;Transaction 常言道&#xff1a;能不麻烦就不麻烦&#xff0c;能简单化就简单化。但是为什么需要事务呢&#xff1f; 事务&#xff1a;用来保证一个业务的完整性&#xff0c;最大的优势就是回滚&#xff0c;并撤销正在进行的所有未提交的修改&#xff1…

linux运行串口相关的java.jar报错:java.lang.UnsatisfiedLinkError

目录 linux运行串口相关的java.jar报错如下&#xff1a; java.lang.UnsatisfiedLinkError是Java中的一个错误类型&#xff0c;通常发生在调用本地&#xff08;native&#xff09;方法或使用JNI&#xff08;Java Native Interface&#xff09;时。 在Java中&#xff0c;本地方…

微分中值定理—柯西中值定理

微分中值定理—柯西中值定理前面我们已经学习了罗尔中值定理,和拉格朗日中值定理&#xff0c;它们的相同点是&#xff0c;研究的曲线都能用函数来表示。那假如曲线不能被函数表示呢&#xff0c;用柯西中值定理。 1 定义 柯西中值定理是拉格朗日中值定理的推广。如果&#xff0c…

助力企业节能降耗:综合能效管理之场景控制

企业综合能效管理系统是为企业提供能耗管理、电能质量和用能安全监测的整套解决方案&#xff0c;系统可采集多种类型能源&#xff08;电、水、天然气、工业气体、冷热量等&#xff09;数据&#xff0c;并对能源消耗进行分析&#xff0c;包括分类分项能耗、区域能耗、部门能耗数…

海思编码:1、mpp系统详谈以及VI、VPSS、VENC之间的关系

在HiMPP手册中都会有这么一张图 1、VI部分 视频输入设备 视频输入设备支持标准 BT.656、标准 BT.1120、自定义时序等若干种时序输入&#xff0c;负责对时序进行解析。 视频物理通道 视频物理通道负责将输入设备解析后得到的视频数据输出到 DDR。在真正将数据输出到 DDR 之前…

FTP-----局域网内部远程桌面

此文包含详细的图文教程。有疑问评论区留言。博主第一时间解决。 目录 一、被远程桌面的电脑 1.开启远程权限 2.添加账户&#xff0c;有本地账户跳过这步 3.帐号隶属于 远程桌面 4.帐号隶属于 本地用户组 二、本地电脑连接远程桌面 前提条件&#xff1a; 1.两台电脑在…

接口自动化【二】(图形验证码处理)

文章目录 前言一、图形验证码图片获取(需要实际截图做对比补充)二、调第三方接口获取验证码三、后端登录接口&#xff08;举例&#xff09;总结前言 讲解了图片验证的处理&#xff1b;在接口测试中遇见的一些问题&#xff1b;多部分编码的注意点 一、图形验证码图片获取(需要实…

【4.13(补)】二叉搜索树的遍历、插入、删除

文章目录二叉搜索树的最近公共祖先二叉搜索树中的插入操作删除二叉搜索树中的节点二叉搜索树的最近公共祖先 235. 二叉搜索树的最近公共祖先 - 力扣&#xff08;LeetCode&#xff09; 因为二叉搜索树是有序的&#xff0c;第一次找到p和q中间的值&#xff0c;就是最近的公共祖先…

【FPGA-DSP】第六期:Black Box调用流程

目录 1. 实际操作流程 1.1 Verilog 代码编写 1.2 system generator操作 1.2.1 Black box模块 1.2.2 Simulink 搭建 2. Simulink模型优化 System Generator是一个Xilinx公司的工具&#xff0c;用于设计数字信号处理系统。Black Box是System Generator中的一个block&#…

【数值模型系列】CAMx编译运行中的几个小问题

最近在CAMx的编译运行工作中&#xff0c;遇到了几个小问题&#xff0c;在此记录一下。 问题1&#xff1a;CAMx2IOAPI编译报错 报错如下&#xff1a; CAMx2IOAPI依赖于IOAPI和NetCDF库&#xff0c;在Makefile文件中加以配置即可&#xff0c;但出现此错的原因其实是默认的Makef…

【大数据之Hadoop】十四、MapReduce之Combiner合并

Combiner是Mapper和Reducer之间的组件&#xff0c;其组件的父类是Reducer。 Combiner和Reducer的区别&#xff1a; Combiner是运行在每一个MapTask所在的节点&#xff0c;即对每一个MapTask的输出进行局部汇总&#xff0c;减少网络传输量。 Reducer则是接收全局是Mapper的输出…