糖尿病数据集来源:UCI
1.特征包括:怀孕次数,血糖,血压,胰岛素等特征
2.target:预测是否患糖尿病---0/1
这是一个典型的二分类问题,可以用Sigmoid函数来解决
1. 数据集构建
构建自己的DiabetesDataSet类,继承自torch中的Dataset
from torch.utils.data import Dataset # 构建数据集
# dataset是一个抽象类,不能实例化,必须先用子类继承该抽象类
class DiabetesDataSet(Dataset):
def __init__(self, filepath):
xy = np.loadtxt(filepath, delimiter=" ", dtype=np.float32)
self.len = xy.shape[0] # 读取矩阵第一维的长度
# self.shape = xy.shape() # 读取矩阵的形状
# 若不写 self. 开头的话, 那么x_data就是函数内部的成员变量
# 若写了 self. 的话,那么这个成员变量就是类中的成员变量
self.x_data = torch.from_numpy(xy[:, :-1])
self.y_data = torch.from_numpy(xy[:, [-1]])
# 通过 index 获得数据索引
def __getitem__(self, index):
return self.x_data[index], self.y_data[index]
# 获取数据的长度 length
def __len__(self):
return self.len
# 初始化数据集
dataset = DiabetesDataSet("../DataSet/diabetes/diabetes_data.csv.gz")
2. 用Pytorch提供的DataLoader来加载数据集
# dataset:数据集 batch_size:mini-batch的大小 shuffle:是否打乱数据集顺序 num_workers:读取 batch 时采用的多线程的线程数
train_loader = DataLoader(dataset=dataset, batch_size=64, shuffle=True, num_workers=0)
3.采用全连接的神经网络,最后用sigmoid来处理output
# 构建神经网络模型
class Model(torch.nn.Module):
def __init__(self):
super(Model, self).__init__()
# 线性模型: y = w*x + b
# 在线性模型 Linear 类中,第一次训练时的参数 w 和 b 都是给的随机数,所以多次运行代码,结果不大相同
self.linear1 = torch.nn.Linear(9, 6)
self.linear2 = torch.nn.Linear(6, 4)
self.linear3 = torch.nn.Linear(4, 1)
self.sigmoid = torch.nn.Sigmoid()
# 类里面定义的每个函数都需要有个参数self,来代表自己,用来调用类中的成员变量和方法
def forward(self, x):
x = self.linear1(x)
x = self.linear2(x)
x = self.linear3(x)
x = self.sigmoid(x)
return x
4. 构建损失函数和优化器
损失函数采用BCELoss计算两个分布之间的差异
优化器采用 SGD 随机梯度优化算法
# 构建损失函数和优化器:BCELoss---运用交叉熵计算两个分布之间的差异
criterion = torch.nn.BCELoss(reduction="mean")
opt = torch.optim.SGD(params=model.parameters(), lr=0.001)
5.完整代码
# -*- codeing = utf-8 -*-
import numpy as np
import torch
from matplotlib import pyplot as plt
from torch.utils.data import Dataset # 构建数据集
from torch.utils.data import DataLoader # 加载数据 mini-batch 以供训练
# dataset是一个抽象类,不能实例化,必须先用子类继承该抽象类
class DiabetesDataSet(Dataset):
def __init__(self, filepath):
xy = np.loadtxt(filepath, delimiter=" ", dtype=np.float32)
self.len = xy.shape[0] # 读取矩阵第一维的长度
# self.shape = xy.shape() # 读取矩阵的形状
# 若不写 self. 开头的话, 那么x_data就是函数内部的成员变量
# 若写了 self. 的话,那么这个成员变量就是类中的成员变量
self.x_data = torch.from_numpy(xy[:, :-1])
self.y_data = torch.from_numpy(xy[:, [-1]])
# 通过 index 获得数据索引
def __getitem__(self, index):
return self.x_data[index], self.y_data[index]
# 获取数据的长度 length
def __len__(self):
return self.len
# 初始化数据集
dataset = DiabetesDataSet("../DataSet/diabetes/diabetes_data.csv.gz")
# dataset:数据集 batch_size:mini-batch的大小 shuffle:是否打乱数据集顺序 num_workers:读取 batch 时采用的多线程的线程数
train_loader = DataLoader(dataset=dataset, batch_size=64, shuffle=True, num_workers=0)
# 2.构建神经网络模型
class Model(torch.nn.Module):
def __init__(self):
super(Model, self).__init__()
# 线性模型: y = w*x + b
# 在线性模型 Linear 类中,第一次训练时的参数 w 和 b 都是给的随机数,所以多次运行代码,结果不大相同
self.linear1 = torch.nn.Linear(9, 6)
self.linear2 = torch.nn.Linear(6, 4)
self.linear3 = torch.nn.Linear(4, 1)
self.sigmoid = torch.nn.Sigmoid()
# 类里面定义的每个函数都需要有个参数self,来代表自己,用来调用类中的成员变量和方法
def forward(self, x):
x = self.linear1(x)
x = self.linear2(x)
x = self.linear3(x)
x = self.sigmoid(x)
return x
model = Model()
# 3.构建损失函数和优化器:BCELoss---运用交叉熵计算两个分布之间的差异
criterion = torch.nn.BCELoss(reduction="mean")
opt = torch.optim.SGD(params=model.parameters(), lr=0.001)
epochs = []
costs = []
# 4.开始训练
for epoch in range(300):
epochs.append(epoch)
# enumerate: 在循环列表或元组的同时引入下标 i
# zip: 将两个 list 或 tuple , 取出一一对应
for i, data in enumerate(train_loader, 0):
inputs, labels = data
# 前向计算模型训练输出的值
y_pred_data = model(inputs)
# 计算训练输出的值和真实的值之前的分布差异
loss = criterion(y_pred_data, labels)
print(print("epoch=", epoch, "batch=", i, "loss=", loss.item()))
# 重置梯度
opt.zero_grad()
# 计算梯度反向传播
loss.backward()
# 优化器根据梯度值进行优化
opt.step()
costs.append(loss.item())
# 5.进行模型测试
# 6.训练过程可视化
plt.plot(epochs, costs)
plt.ylabel('Cost')
plt.xlabel('Epoch')
plt.show()