python,质谱数据,加噪声后用小波神经网络,二分类预测

发布时间 2023-07-15 20:39:19作者: 奋发图强的小赵
#库的导入
import numpy as np
import pandas as pd
import math

#激活函数
def tanh(x):
    return (np.exp(x)-np.exp(-x))/(np.exp(x)+np.exp(-x))
#激活函数偏导数
def de_tanh(x):
    return (1-x**2)
#小波基函数
def wavelet(x):
    return (math.cos(1.75*x)) * (np.exp((x**2)/(-2)))
#小波基函数偏导数
def de_wavelet(x):
    y = (-1) * (1.75 * math.sin(1.75 * x)  + x * math.cos(1.75 * x)) * (np.exp(( x **2)/(-2)))
    return y

#数据输入
data=pd.read_pickle('ICC_rms.pkl')
df=pd.DataFrame(data)
X = df.iloc[:, 0:510].values #所有样本的x值,0-510列 矩阵(1544,510)由此得出样本个数1544个,特征510
y = df.iloc[:, 511].values #所有样本的标签,511列 矩阵(1544,)
#把y转成1-0形式,Neurons对应0,Astrocytes对应1
Y=np.array([-1.0] * 1544)
for i in range(len(y)):
    if y[i] =='Neurons':
        Y[i]=0
    if y[i] =='Astrocytes':
        Y[i]=1
# y=['Neurons' 'Neurons' 'Neurons' ... 'Astrocytes' 'Astrocytes' 'Astrocytes']
# Y=[0. 0. 0. ... 1. 1. 1.]


# #参数设置
# samnum = 72   #输入数据数量
# hiddenunitnum = 8   #隐含层节点数
# indim = 4   #输入层节点数
# outdim = 1   #输出层节点数
# maxepochs = 500   #迭代次数
# errorfinal = 0.65*10**(-3)   #停止迭代训练条件
# learnrate = 0.001   #学习率

#参数设置
samnum = 1544   #输入数据数量
hiddenunitnum = 8   #隐含层节点数
indim = 510   #输入层节点数
outdim = 1   #输出层节点数
maxepochs = 500   #迭代次数
errorfinal = 0.65*10**(-3)   #停止迭代训练条件
learnrate = 0.001   #学习率

#输入数据的导入
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"]
# Tisample = np.array(Ti)
# sampleinshaple = np.mat([Co,Cr,Mg,Pb])
Ti = np.array(Y)
samplein = np.mat(X.T)

#数据归一化,将输入数据压缩至0到1之间,便于计算,后续通过反归一化恢复原始值
sampleinminmax = np.array([samplein.min(axis=1).T.tolist()[0],samplein.max(axis=1).T.tolist()[0]]).transpose()#对应最大值最小值
#待预测数据为Ti
sampleout = np.mat([Ti])
sampleoutminmax = np.array([sampleout.min(axis=1).T.tolist()[0],sampleout.max(axis=1).T.tolist()[0]]).transpose()#对应最大值最小值
sampleinnorm = ((np.array(samplein.T)-sampleinminmax.transpose()[0])/(sampleinminmax.transpose()[1]-sampleinminmax.transpose()[0])).transpose()
sampleoutnorm = ((np.array(sampleout.T)-sampleoutminmax.transpose()[0])/(sampleoutminmax.transpose()[1]-sampleoutminmax.transpose()[0])).transpose()

#给归一化后的数据添加噪声
noise = 0.03*np.random.rand(sampleoutnorm.shape[0],sampleoutnorm.shape[1])
sampleoutnorm += noise

#
scale = np.sqrt(3/((indim+outdim)*0.5))
w1 = np.random.uniform(low=-scale,high=scale,size=[hiddenunitnum,indim])
b = np.random.uniform(low=-scale, high=scale, size=[hiddenunitnum,1])
a = np.random.uniform(low=-scale, high=scale, size=[hiddenunitnum,1])
w2 = np.random.uniform(low=-scale,high=scale,size=[hiddenunitnum,outdim])

#对隐含层的连接权值w1、平滑因子被b和伸缩因子a、输出层的连接权值w2进行随机初始化
inputin=np.mat(sampleinnorm.T)
w1=np.mat(w1)
b=np.mat(b)
a=np.mat(a)
w2=np.mat(w2)

#errhistory存储每次迭代训练计算的误差
errhistory = np.mat(np.zeros((1,maxepochs)))
#开始训练
for i in range(maxepochs):
    #前向计算:
    #hidden_out为隐含层输出
    hidden_out = np.mat(np.zeros((samnum,hiddenunitnum)))
    for m in range(samnum):
        for j in range(hiddenunitnum):
            d=((inputin[m, :] * w1[j, :].T) - b[j,:]) * (a[j,:] ** (-1))
            hidden_out[m,j] = wavelet(d)
    #output为输出层输出
    output = tanh(hidden_out * w2)
    #计算误差
    out_real = np.mat(sampleoutnorm.transpose())
    err = out_real - output
    loss = np.sum(np.square(err))
    #判断是否停止训练
    if loss < errorfinal:
        break
    errhistory[:,i] = loss
    #反向计算
    out_put=np.array(output.T)
    belta=de_tanh(out_put).transpose()
    #分别计算每个参数的误差项
    for j in range(hiddenunitnum):
        sum1 = 0.0
        sum2 = 0.0
        sum3 = 0.0
        sum4 = 0.0
        sum5 = 0.0
        for m in range(samnum):
            sum1+= err[m,:] * belta[m,:] * w2[j,:] * de_wavelet(hidden_out[m,j]) * (inputin[m,:] / a[j,:])
            #1*1
            sum2+= err[m,:] * belta[m,:] * w2[j,:] * de_wavelet(hidden_out[m,j]) * (-1) * (1 / a[j,:])
            #1*1
            sum3+= err[m,:] * belta[m,:] * w2[j,:] * de_wavelet(hidden_out[m,j]) * (-1) * ((inputin[m,:] * w1[j,:].T - b[j,:]) / (a[j,:] * a[j,:]))
            #1*1
            sum4+= err[m,:] * belta[m,:] * hidden_out[m,j]
        delta_w1 = sum1
        delta_b = sum2
        delta_a = sum3
        delta_w2 = sum4
        #根据误差项对四个参数进行更新
        w1[j,:] = w1[j,:] + learnrate * delta_w1
        b[j,:] = b[j,:] + learnrate * delta_b
        a[j,:] = a[j,:] + learnrate * delta_a
        w2[j,:] = w2[j,:] + learnrate * delta_w2
    print("the generation is:",i+1,",the loss is:",loss)

print('更新的w1:',w1)
print('更新的b:',b)
print('更新的w2:',w2)
print('更新的a:',a)
print("The loss after iteration is :",loss)

np.save("w1.npy",w1)
np.save("b.npy",b)
np.save("w2.npy",w2)
np.save("a.npy",a)

迭代500次后:The loss after iteration is : 883.4984505986399

期间loss上蹿下跳,梯度消失,可以尝试调低学习率

另外:原问题是时序预测的回归问题,现在改成二分类需要改loss