RNN实现原理可参考http://t.csdnimg.cn/ReYXS
定义网络可参考http://t.csdnimg.cn/IZaEG
# This is a sample Python script.
import numpy as np
# Press Shift+F10 to execute it or replace it with your code.
# Press Double Shift to search everywhere for classes, files, tool windows, actions, and settings.
import torch
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
import numpy as np
import torch
import matplotlib.pyplot as plt
from torch.utils.data import Dataset, DataLoader
import torch.nn as nn
# Prepare the dataset
class DiabetesDateset(Dataset):
# 加载数据集
def __init__(self, filepath): #构造函数进行定义和初始化,创建对象时自动调用
xy = np.loadtxt(filepath, delimiter=',', dtype=np.float32, encoding='utf-8')
self.len = xy.shape[0] # shape[0]是矩阵的行数,shape[1]是矩阵的列数
self.x_data = torch.from_numpy(xy[:, :-1])
self.y_data = torch.from_numpy(xy[:, [-1]])
# 获取数据索引
def __getitem__(self, index):
return self.x_data[index], self.y_data[index]
# 获得数据总量
def __len__(self):
return self.len
dataset = DiabetesDateset('diabetes.csv')
train_loader = DataLoader(dataset=dataset, batch_size=32, shuffle=True, num_workers=2) # num_workers为多线程
#Dataloader是一个迭代器,当传入一个Dataset对象,它会根据参数batch_size的值生成一个batch数据,实现多线程、数据打乱等处理。
# Define the model
class FNNModel(torch.nn.Module): #定义网络;通过继承torch.nn.Module 类来实现扩展;在这种情况下,只需要重新实现__init__和forward函数就行。
def __init__(self): #也可以在这个括号中设置参数,如input_size,hidden_size,output_size,num_layers)
super(FNNModel, self).__init__()
self.linear1 = nn.Linear(8, 6) # 输入数据的特征有8个,也就是有8个维度,随后将其降维到6维
self.linear2 = nn.Linear(6, 4) # 6维降到4维
self.linear3 = nn.Linear(4, 2) # 4维降到2维
self.linear4 = nn.Linear(2, 1) # 2维降到1维
self.sigmoid = nn.Sigmoid() # 可以视其为网络的一层,而不是简单的函数使用
#nn.linear(in_features(int类型,输入的神经元个数/输入的通道数) ,out_features(输出的神经元个数/输出的通道数),bias(bool类型,是否含有偏置))
def forward(self, x): #向前传播
x = self.sigmoid(self.linear1(x)) #sigmoid是激活函数的一种,它会将样本值映射到0到1之间。
x = self.sigmoid(self.linear2(x))
x = self.sigmoid(self.linear3(x))
x = self.sigmoid(self.linear4(x))
return x
#调用网络
model = FNNModel().to(device) #在这里将运行环境转为cuda
#定义标准和优化器
criterion = nn.BCELoss(reduction='mean')
# nn.BCELoss函数用来计算目标值和预测值之间的二进制交叉熵损失函数。
#reduction='none',直接返回向量形式的loss
#reduction='sum' ,返回loss之和
#reduction='mean',返回loss的平均值
optimizer = torch.optim.SGD(model.parameters(), lr=0.01) #优化
#优化是在每个循环步骤中调整模型参数以减小模型误差的过程。优化算法定义了这个过程是如何执行的。所有优化算法都风筝在优化器对象optimizer中。
#这里使用的是SGD优化器,此外Pytorch中有许多不同的优化器,他们可以更好地使用不用类型的模型和数据。
#lr为Learning Rate学习率,表示在每个批次时间更新模型参数的程度。
# 较小的值会产生较慢的学习速度,而较大的值可能会导致训练期间出现不可预测的行为。
epoch_list = []
loss_list = []
# Training
if __name__ == '__main__':
for epoch in range(100): #epoch为每个优化循环的迭代 #如果加大训练量loss会继续收敛
# i是一个epoch中第几次迭代,一共756条数据,每个mini_batch为32,所以一个epoch需要迭代23次
# data获取的数据为(x,y)
loss_one_epoch = 0
for i, data in enumerate(train_loader, 0): #一个batch有32行数据,这里的i表示这个epoch中第几个batch
inputs, labels = data
inputs = inputs.to(device)
labels = labels.to(device)
outputs = model(inputs) #向前传播
loss = criterion(outputs, labels) #用求平均值的方式计算损失函数,将模型输出与真实标签lable进行比较
loss_one_epoch += loss.item() #统计这23个batch的损失总和,也是这次epoch里计算出的总损失
optimizer.zero_grad() #清空上一层的梯度,如果不清空,梯度仍然和上一个batch有关
loss.backward() #反向传播;产生新的梯度;根据损失函数,使用反向传播算法来更新网络中的权重和偏置,以最小化损失函数
optimizer.step() #使用梯度下降等优化算法来更新网络中的参数
loss_list.append(loss_one_epoch / 23) #计算每一个batch的平均计算损失
epoch_list.append(epoch)
print('Epoch[{}/{}],loss:{:.6f}'.format(epoch + 1, 100, loss_one_epoch / 23))
#
# Drawing
plt.plot(epoch_list, loss_list) #横轴为迭代次数,纵轴为平均损失
plt.xlabel('epoch')
plt.ylabel('loss')
plt.show() #展现图表
#epoch只设置了100层,最终的loss在67%左右