2021研究生数学建模D题,BP神经网络和卷积神经网络解题代码(基于pytorch)
(需要数据或者有关于代码问题请留言)
第二题
本题是利用二十个自变量对最后的结果(因变量)做预测,本题我使用BP神经网络解题。先将数据整理好,把二十个变量选出来放入新的excel表,把因变量放在最后一列。下面进行代码解析(代码博主已经跑通)
导入包
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import torch
import torch.nn as nn
读取excel数据
# ------------------1. 数据读取------------------
# 读取数据
data = pd.read_excel("a.xlsx")
# 看看数据长什么样子
print(data.head())
# 查看数据维度
print("数据维度:", data.shape
# 查看数据类型
print("数据类型:", type(data))
本文读取的使excel数据,其余类型数据也可以使用pandas库里的对应函数进行读取,读取后的数据都是dataframe类型
数据处理
# ------------------2. 数据预处理------------------
# 标签,即因变量,因变量名字是pIC50
labelss = np.array(data["pIC50"])
# 取前1800行因变量作为训练数据标签
labels=labelss[:1800,]
print('----------------lable.shape-----------')
print(labels.shape)
# 取消标签,即将标签列(因变量)删除
data = data.drop(["pIC50"], axis= 1)
# 取前1800行自变量数据作为训练数据
data_news = np.array(data)
data_new=data_news[:1800,:]
print('-----------------data.shape------------')
print(data_new.shape)
在本题中选择前1800行数据作为训练集,后174行数据作为测试集,用来测试网络实际预测效果。
定义网络
#------------------3. 定义网络------------------
input_size = data_new.shape[1]
hidden_size = 128
output_size = 1
batch_size = 16
my_nn = nn.Sequential(
nn.Linear(input_size,hidden_size),
nn.ReLU(),
nn.Linear(hidden_size,hidden_size),
nn.ReLU(),
nn.Linear(hidden_size,hidden_size),
nn.ReLU(),
nn.Linear(hidden_size, hidden_size),
nn.ReLU(),
nn.Linear(hidden_size, hidden_size),
nn.ReLU(),
nn.Linear(hidden_size,output_size)
)
cost = torch.nn.MSELoss(reduction = 'mean') #损失函数
optimizer = torch.optim.Adam(my_nn.parameters(),lr=0.001) #优化器 Adam/SGD
训练网络
#------------------4. 训练集训练网络------------------
losses = []
for i in range(1000):
batch_loss = []
#MINI-Batch方法来进行训练 每次取16个数据
for start in range(0,len(data_new),batch_size):
end = start + batch_size if start + batch_size < len(data_new) else len(data_new)
xx = torch.tensor(data_new[start:end],dtype=torch.float,requires_grad = True)
yy = torch.tensor(labels[start:end],dtype=torch.float,requires_grad = True)
prediction = my_nn(xx)
prediction=prediction.squeeze(1)
loss = cost(prediction,yy)
optimizer.zero_grad() #每次梯度清零
loss.backward(retain_graph=True)
optimizer.step()#实时更新
batch_loss.append(loss.data.numpy())
#打印损失
if i%100==0:
losses.append(np.mean(batch_loss))
print(i,np.mean(batch_loss))
torch.save(my_nn,'my_nn_3.pth')
验证集预测结果,画出预测图与实际值图
#------------------5. 验证集预测结果------------------
test_x=data_news[1801:,:]
test_x=torch.tensor(test_x,dtype=torch.float)
predx=my_nn(test_x).data.numpy()
predx=np.squeeze(predx,1)
test_y=labelss[1801:,]
loss=[]
for i in range(len(test_y)):
lo=abs(predx[i]-test_y[i])/test_y[i]
loss.append(lo)
print(sum(loss))
#------------------6. 画图观察预测拟合情况------------------
#画损失函数曲线
# 真实值
plt.plot(test_y,'b', label ='pIC50')
# 预测值
plt.plot(predx, 'r', label ='prediction')
plt.xticks(rotation = '60')
plt.legend()
# 图名
plt.title('Actual and Predicted Values')
plt.show()
结果预测
#-----------测试集测试结果
testdata = pd.read_excel("test.xlsx")
testdata=np.array(testdata)
testdata_x=torch.tensor(testdata,dtype=torch.float)
predx=my_nn(testdata_x).data.numpy()
print(predx.shape)
print(predx)
训练损失(我训练1000次,每过100次就输出一个损失值):
0 11.978955
100 0.7511373
200 0.35879636
300 0.2481647
400 0.22193664
500 0.16860785
600 0.16576535
700 0.13864414
800 0.17848253
900 0.14543799
可以看出训练损失较低,说明模型拟合效果不错,下面看一下实际预测效果如何。
输出图片如下,因为最后174个结果上下起伏较大,所以实际预测效果不好。预测值和实际值之间偏差较大,但是总体预测趋势是有的,预测误差为19%.ps:换一组测试集可能会实际预测效果好一点。
第三题
第三题是0、1分类问题,要建立五个0,1分类模型,因为要对五种性质进行分类。本题想利用尽可能多的变量对结果进行预测,本题共有729个变量,且变量直接并没有时序关系,所以我们把729个变量进行排列,既有27* 27=729 ,把729个变量变成二维数据。这样我们就可以使用卷积神经网络,用尽量少的参数提取更加多的特征。代码如下(代码博主已经跑通)
读取数据
本题的数据读取不用对原数据进行处理,因为我们选择全部变量作为网络的输入。
# ------------------1. 数据读取------------------
#下面三行是测试数据的读取
testdata=pd.read_excel('D:\\SZ\\jianmo\\1\Molecular_Descriptor.xlsx',sheet_name='test')
testdata=testdata.drop(['SMILES'],1)
testdata=np.array(testdata)
# 读取训练数据
data = pd.read_excel("D:\\SZ\\jianmo\\1\\Molecular_Descriptor.xlsx")
#读取标签数据
labelss=pd.read_excel('D:\\SZ\\jianmo\\1\\ADMET.xlsx')
# 看看数据长什么样子
print(labelss.head())
labelss=labelss.drop(['SMILES'], axis= 1)
# 查看数据维度
print("数据维度:", data.shape)
# 查看数据类型
print("数据类型:", type(data))
数据预处理
同样取前1800行数据作为训练集,后174行数据作为验证集
# ------------------2. 数据预处理------------------
# 标签
labelss=np.array(labelss)
labela=labelss[:1800,:1]
labelb=labelss[:1800,1:2]
labelc=labelss[:1800,2:3]
labeld=labelss[:1800,3:4]
labele=labelss[:1800,4:]
print('----------------lable.shape-----------')
print(labela.shape)
print(labelb.shape)
print(labelc.shape)
# 取消标签
data = data.drop(["pIC50",'SMILES'], axis= 1)
data_news = np.array(data)
data_new=data_news[:1800,:].reshape(1800,27,27)
print('-----------------data.shape------------')
print(data_new.shape)
定义网络
#------------------3. 定义网络------------------
input_size = 1
hidden_size = 16
output_size = 1
batch_size = 16
class ABC(nn.Module):
def __init__(self):
super(ABC, self).__init__()
self.a=nn.Sequential(
nn.Conv2d(1, 8, 3),
nn.ReLU(),
nn.Conv2d(8, 8, 3),
nn.ReLU(),
nn.Conv2d(8, 8, 3),
nn.ReLU(),
nn.Conv2d(8, 8, 3),
nn.ReLU(),
nn.Conv2d(8, 8, 3),
nn.ReLU(),
nn.Conv2d(8, 8, 3),
nn.ReLU(),
nn.Conv2d(8, 8, 3),
nn.ReLU(),
nn.Conv2d(8, 8, 3),
nn.ReLU(),
nn.Conv2d(8, 8, 3),
nn.ReLU(),
nn.Conv2d(8, 8, 3),
nn.ReLU(),
nn.Conv2d(8, 8, 3),
nn.ReLU(),
nn.Conv2d(8, 8, 3),
nn.ReLU(),
nn.Conv2d(8, 1, 3),
nn.Sigmoid()
)
self.b=nn.Sequential(
nn.Conv2d(1, 8, 3),
nn.ReLU(),
nn.Conv2d(8, 8, 3),
nn.ReLU(),
nn.Conv2d(8, 8, 3),
nn.ReLU(),
nn.Conv2d(8, 8, 3),
nn.ReLU(),
nn.Conv2d(8, 8, 3),
nn.ReLU(),
nn.Conv2d(8, 8, 3),
nn.ReLU(),
nn.Conv2d(8, 8, 3),
nn.ReLU(),
nn.Conv2d(8, 8, 3),
nn.ReLU(),
nn.Conv2d(8, 8, 3),
nn.ReLU(),
nn.Conv2d(8, 8, 3),
nn.ReLU(),
nn.Conv2d(8, 8, 3),
nn.ReLU(),
nn.Conv2d(8, 8, 3),
nn.ReLU(),
nn.Conv2d(8, 1, 3),
nn.Sigmoid()
)
self.c=nn.Sequential(
nn.Conv2d(1, 8, 3),
nn.ReLU(),
nn.Conv2d(8, 8, 3),
nn.ReLU(),
nn.Conv2d(8, 8, 3),
nn.ReLU(),
nn.Conv2d(8, 8, 3),
nn.ReLU(),
nn.Conv2d(8, 8, 3),
nn.ReLU(),
nn.Conv2d(8, 8, 3),
nn.ReLU(),
nn.Conv2d(8, 8, 3),
nn.ReLU(),
nn.Conv2d(8, 8, 3),
nn.ReLU(),
nn.Conv2d(8, 8, 3),
nn.ReLU(),
nn.Conv2d(8, 8, 3),
nn.ReLU(),
nn.Conv2d(8, 8, 3),
nn.ReLU(),
nn.Conv2d(8, 8, 3),
nn.ReLU(),
nn.Conv2d(8, 1, 3),
nn.Sigmoid()
)
self.d=nn.Sequential(
nn.Conv2d(1, 8, 3),
nn.ReLU(),
nn.Conv2d(8, 8, 3),
nn.ReLU(),
nn.Conv2d(8, 8, 3),
nn.ReLU(),
nn.Conv2d(8, 8, 3),
nn.ReLU(),
nn.Conv2d(8, 8, 3),
nn.ReLU(),
nn.Conv2d(8, 8, 3),
nn.ReLU(),
nn.Conv2d(8, 8, 3),
nn.ReLU(),
nn.Conv2d(8, 8, 3),
nn.ReLU(),
nn.Conv2d(8, 8, 3),
nn.ReLU(),
nn.Conv2d(8, 8, 3),
nn.ReLU(),
nn.Conv2d(8, 8, 3),
nn.ReLU(),
nn.Conv2d(8, 8, 3),
nn.ReLU(),
nn.Conv2d(8, 1, 3),
nn.Sigmoid()
)
self.e=nn.Sequential(
nn.Conv2d(1,8,3),
nn.ReLU(),
nn.Conv2d(8, 8, 3),
nn.ReLU(),
nn.Conv2d(8, 8, 3),
nn.ReLU(),
nn.Conv2d(8, 8, 3),
nn.ReLU(),
nn.Conv2d(8, 8, 3),
nn.ReLU(),
nn.Conv2d(8, 8, 3),
nn.ReLU(),
nn.Conv2d(8, 8, 3),
nn.ReLU(),
nn.Conv2d(8, 8, 3),
nn.ReLU(),
nn.Conv2d(8, 8, 3),
nn.ReLU(),
nn.Conv2d(8, 8, 3),
nn.ReLU(),
nn.Conv2d(8, 8, 3),
nn.ReLU(),
nn.Conv2d(8, 8, 3),
nn.ReLU(),
nn.Conv2d(8, 1, 3),
nn.Sigmoid()
)
def forward(self, x):
a=self.a(x)
b = self.b(x)
c = self.c(x)
d = self.d(x)
e = self.e(x)
return a,b,c,d,e
my_nn=ABC()
my_nn.to('cuda')
cost = nn.BCELoss() #损失函数
optimizer = torch.optim.Adam(my_nn.parameters(),lr=0.001) #优化器 Adam/SGD
训练网络
#------------------4. 训练集训练网络------------------
losses = []
for i in range(50):
batch_loss = []
#MINI-Batch方法来进行训练 每次取16个数据
for start in range(0,len(data_new),batch_size):
end = start + batch_size if start + batch_size < len(data_new) else len(data_new)
xx = torch.tensor(data_new[start:end],dtype=torch.float,requires_grad = True,device='cuda').unsqueeze(1)
a = torch.tensor(labela[start:end],dtype=torch.float,device='cuda')
b=torch.tensor(labelb[start:end],dtype=torch.float,device='cuda')
c=torch.tensor(labelc[start:end],dtype=torch.float,device='cuda')
d=torch.tensor(labeld[start:end],dtype=torch.float,device='cuda')
e=torch.tensor(labele[start:end],dtype=torch.float,device='cuda')
prediction =my_nn(xx)
pa=prediction[0]
pb=prediction[1]
pc=prediction[2]
pd=prediction[3]
pe=prediction[4]
loss = cost(pa,a)+cost(pb,b)+cost(pc,c)+cost(pd,d)+cost(pe,e)
optimizer.zero_grad() #每次梯度清零
loss.backward(retain_graph=True)
optimizer.step()#实时更新
batch_loss.append(loss.clone().detach().requires_grad_(False).cpu().numpy())
# torch.save(my_nn,'my_nn_1.pkl')
#打印损失
if i%10==0:
losses.append(np.mean(batch_loss))
print(i,np.mean(batch_loss))
torch.save(my_nn,'test2.pth')
验证集测试
#------------------5. 验证集预测结果------------------
lo=nn.L1Loss()
lossa=[]
lossb=[]
lossc=[]
lossd=[]
losse=[]
my_nn.to('cpu')
test_xx=data_news[1801:,:]
for i in range(173):
test_x=test_xx[i:i+1,:].reshape(1,27,27)
# print('a',test_x.shape)
test_x = torch.tensor(test_x, dtype=torch.float,device='cpu').unsqueeze(0)#1,1,20
# print('b',test_x.shape)
predx = my_nn(test_x)
predx=torch.tensor(predx).squeeze(0).squeeze(0).squeeze(0)
# print(predx.dtype)#5
# print(predx)
preda=predx[0]
predb=predx[1]
predc=predx[2]
predd=predx[3]
prede=predx[4]
test_y = labelss[1801:, ]
test_y=test_y[i:i+1,:]
test_y=torch.tensor(test_y, dtype=torch.float,device='cpu').squeeze(0)
test_ya = test_y[0]
test_yb = test_y[1]
test_yc = test_y[2]
test_yd = test_y[3]
test_ye = test_y[4]
# print(test_ya)
# print(preda)
la=lo(preda,test_ya).cpu().numpy()
lb = lo(predb, test_yb).cpu().numpy()
lc = lo(predc, test_yc).cpu().numpy()
ld = lo(predd, test_yd).cpu().numpy()
le = lo(prede, test_ye).cpu().numpy()
lossa.append(la)
lossb.append(lb)
lossc.append(lc)
lossd.append(ld)
losse.append(le)
aa=1-sum(lossa)/174
bb = 1 - sum(lossb) / 174
cc = 1 - sum(lossc) / 174
dd = 1 - sum(lossd) / 174
ee = 1 - sum(losse) / 174
print(aa,bb,cc,dd,ee)
plt.plot(lossa,'r')
# plt.plot(lossb,'g')
# plt.plot(lossc,'b')
# plt.plot(lossd,'w')
# plt.plot(losse,'y')
plt.show()
结果预测
#-------------实际预测值------------
for i in range(50):
test_data=testdata[i:i+1,:].reshape(1,27,27)
# print('c',test_data.shape)
test_data = torch.tensor(test_data, dtype=torch.float,device='cpu').unsqueeze(1)#1,1,20
# print('d',test_data.shape)
predx = my_nn(test_data)
predx=torch.tensor(predx).squeeze(0).squeeze(0).squeeze(0)
print(predx.dtype)#5
print(predx)
输出图片如下,在验证集上测试分类精度还不错,分别是87.35%,91.37%,86.78%,86.78%,82.18%