我这里用的网上下载的diabetes.csv数据,首先载入数据,导入包:
import torch
import numpy as np
from torch import nn
from torch.autograd import Variable
import torch.nn.functional as F
import matplotlib.pyplot as plt
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
%matplotlib inline
data = pd.read_csv('diabetes.csv')
看看数据长啥样:
可以看到’Outcome’这一栏是数据的类别
我们将特征和类别分离,划分验证集和训练集,然后将特征归一化:
data1=data.copy()
y=data1.loc[:,['Outcome']] #数据标签
del data1['Outcome']
x = data1 #数据
x_train, x_test,y_train,y_test= train_test_split(x, y, test_size=0.3,random_state=2018) #数据集三七分,随机种子2018
ss = StandardScaler()
x_train = ss.fit_transform(x_train) #数据标准化
x_test = ss.fit_transform(x_test) #数据标准化
x_train_tensor=torch.from_numpy(x_train)
x_test_tensor=torch.from_numpy(x_test)
y_train_numpy=np.array(y_train)
y_train_tensor=torch.from_numpy(y_train_numpy)
y_test_numpy=np.array(y_test)
y_test_tensor=torch.from_numpy(y_test_numpy)
x=x_train_tensor.float()
y=y_train_tensor.float()
这里要注意的是我这里如果x=x_train_tensor.float()这一居后面不加.float()的话它的类型就是float64,float64的类型在后面导入网络时不知道为啥会出错,报如下错误:
== Expected object of type torch.FloatTensor but found type torch.DoubleTensor for argument #4 ‘mat1’==
加了float()之后类型变了float32,导入网络后没有错误。
到此为止,数据处理步骤结束。
我这里构建了一个七层网络(算数量时包括了激活函数层),代码如下,用的是module的方式:
class module_net(nn.Module):
def __init__(self, num_input, num_hidden, num_output):
super(module_net, self).__init__()
self.layer1 = nn.Linear(num_input, num_hidden)
self.layer2 = nn.Tanh()
self.layer3 = nn.Linear(num_hidden, num_hidden)
self.layer4 = nn.Tanh()
self.layer5 = nn.Linear(num_hidden, num_hidden)
self.layer6 = nn.Tanh()
self.layer7 = nn.Linear(num_hidden, num_output)
def forward(self, x):
x = self.layer1(x)
x = self.layer2(x)
x = self.layer3(x)
x = self.layer4(x)
x = self.layer5(x)
x = self.layer6(x)
x = self.layer7(x)
return x
我们可以打印一下上面y和x的shape,我们看到:
所以我们网络的输入大小肯定是8,输出大小肯定是1
我将module_net传入的参数为(8,10,1为例),损失函数和优化器如下定义:
criterion=nn.BCEWithLogitsLoss()
mo_net = module_net(8, 10, 1)
optim = torch.optim.SGD(mo_net.parameters(), 0.01, momentum=0.9)
我在模型训练时也将准确率和loss曲线也画了出来,代码如下:
Loss_list = [] #用来装loss值,以便之后画图
Accuracy_list = [] #用来装准确率,以便之后画图
for e in range(10000):
out = mo_net.forward(Variable(x)) #这里省略了 mo_net.forward()
loss = criterion(out, Variable(y))
Loss_list.append(loss.data[0])
#--------------------用于求准确率-------------------------#
out_class=(out[:]>0).float() #将out矩阵中大于0的转化为1,小于0的转化为0,存入a中
right_num=torch.sum(y==out_class).float() #分类对的数值
precision=right_num/out.shape[0] #准确率
#--------------------求准确率结束-------------------------#
Accuracy_list.append(precision)
optim.zero_grad()
loss.backward()
optim.step()
if (e + 1) % 1000 == 0:
print('epoch: {}, loss: {},precision{},right_num{}'.format(e+1, loss.data[0],precision,right_num))
plt.plot(x1, Loss_list,c='red',label='loss')
plt.plot(x1, Accuracy_list,c='blue',label='precision')
plt.legend()
我们看看结果:
可以看到,在训练集上神经网络划分的效果相当好,我们现在看看在验证集上效果如何。
我们写代码对验证集的结果进行评估,代验证集在上面1.2里已经划分好了,代码如下:
x_test_tensor=x_test_tensor.float()
y_test_tensor=y_test_tensor.float()
out_test=mo_net.forward(Variable(x_test_tensor))
loss_test = criterion(out_test, Variable(y_test_tensor))
out_test_class=(out_test[:]>0).float() #将out矩阵中大于0的转化为1,小于0的转化为0,存入a中
right_num_test=torch.sum(y_test_tensor==out_test_class).float() #分类对的数值
precision_test=right_num_test/out_test.shape[0] #准确率
loss_test=loss_test.data[0]
print('loss_test:{},precision_test:{},right_num_test:{}'.format(loss_test,precision_test,right_num_test))
结果:
可以看到效果不太好,模型过拟合,我们来改进一下模型,可以把层数降低然后来看看效果:
我简单地将模型从7层删除成为3层,模型如下:
class module_net(nn.Module):
def __init__(self, num_input, num_hidden, num_output):
super(module_net, self).__init__()
self.layer1 = nn.Linear(num_input, num_hidden)
self.layer2 = nn.ReLU()
self.layer3 = nn.Linear(num_hidden, num_output)
self.layer4 = nn.ReLU()
def forward(self, x):
x = self.layer1(x)
x = self.layer2(x)
x = self.layer3(x)
x = self.layer4(x)
return x
改进后训练集:
然后验证集中:
可以看到对比原理0.66的正确率,正确率还是有提高,怎么进一步提高模型的能力下一个博客见~