Dataset and DataLoader是加载数据的两个工具类
Dataset:构造数据集(数据集应该支持索引,能够用下标操作快速把数据拿出来) DataLoader:主要目标是拿出一个MiniBatch(一组数据)供我们训练的时候快速使用
在上面的代码中,训练时,每次给Model做前馈的时候都是把所有的数据(x_data)传进去的
在做梯度下降的时候有两种选择:①全部的数据都用(Batch)
②随机梯度下降:只用一个样本
只用一个样本可以得到比较好的随机性,可以帮助我们跨越在优化中所遇到的鞍点
而用Batch(所有数据)的优点是可以最大化地利用向量计算的优势提升计算速度
都用一个样本的随机梯度下降训练出的模型效果可能会比其他模型都更好,但是会导致优化用的时间更长,因为每次一个样本没法使用cpu或gpu的并行能力,训练的时间会很长
而使用Batch计算速度快,但是在求得性能上会遇到一些问题,所以在深度学习中我们使用MiniBatch来平衡训练时间和训练速度上的要求
使用MiniBatch之后训练循环要写成嵌套循环
最外层循环每一次循环是一个Epoch,Epoch里面每一次循环执行一个MiniBatch
Epoch:所有样本都参与了训练,Epoch表示一个训练周期,所有的样本都进行了正向传播和反向传播
Batch-size:批量大小,每次训练所用的样本数量,进行一次前馈,一次反馈,一次更新用的样本数量,
Iteration:表示Batch分出来多少个MiniBatch,如果有10000个样本,每个batch-size是1000,那么迭代次数Iteration=10.
Dataset是抽象类,不能实例化,只能被子类继承
DataLoader这个类用来加载数据,自动完成shuffle,batch-size
在构造数据集的时候有两种选择
一:把所有的数据从__init__加载进来,都读到内存里面,每一次使用getitem的时候,把构造好的数据集比如矩阵,张量,把其中第i个样本传出去(这种方法适合于数据集本身不大,不如几十个G的图像就不适用了)
二:初始化只在列表里面存文件名,然后getitem根据索引取文件里面找相应文件
# 步骤:准备数据集-设计模型-构建损失和优化器-训练周期
import numpy as np
import torch
#from numpy.core._multiarray_umath import ndarray
from torch.utils.data import Dataset
from torch.utils.data import DataLoader
# filepath=r'D:/pyProject/diabetes.csv.gz'
# filepath=r'../diabetes.csv.gz'
class DiabetesDataset(Dataset): # 继承
def __init__(self, filepath):
xy= np.loadtxt(filepath, delimiter=',', dtype=np.float32) # 加载数据集,按逗号分隔,读取浮点数
self.len = xy.shape[0] # 对于这个数据集,xy是N行9列,shape就是(N,9)这样一个元组,shape[0]就是取第0个元素N
self.x_data = torch.from_numpy(xy[:, :-1]) # 前几列
self.y_data = torch.from_numpy(xy[:, [-1]]) # 取最后一列
# pass
def __getitem__(self, index): # getitem使得实例化之后,对象支持下标操作
return self.x_data[index], self.y_data[index]
# pass
def __len__(self): # 返回数据集的数据条数
return self.len
# pass
dataset = DiabetesDataset('diabetes.csv.gz')
train_loader = DataLoader(dataset=dataset,
batch_size=32,
shuffle=True,
num_workers=2) # num_workers=2表示使用2个进程,Cpu核心数较多的话,可以加高
# 构建模型
class Model(torch.nn.Module):
def __init__(self):
super(Model, self).__init__()
self.linearl1 = torch.nn.Linear(8, 6)
self.linearl2 = torch.nn.Linear(6, 4)
self.linearl3 = torch.nn.Linear(4, 1)
self.sigmoid = torch.nn.Sigmoid()
def forward(self, x):
x = self.sigmoid(self.linearl1(x))
x = self.sigmoid(self.linearl2(x))
x = self.sigmoid(self.linearl3(x))
return x
model = Model()
criterion = torch.nn.BCELoss(size_average=True)
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)
# training cycle
if __name__ == '__main__':
for epoch in range(100):
for i, data in enumerate(train_loader, 0): # 对train_loader做迭代,用 enumerate是为了获得当前是第几次迭代
# 把从train_loader拿出来的(x,y)元组放到data里面
# prepare data
inputs, labels = data # 在训练之前把x,y从data里面拿出来,inputs=x,labels=y,此时inputs,labels都已经被自动转换为张量(tensor)
# 2 forward
y_pred = model(inputs)
loss = criterion(y_pred, labels)
print(epoch, i, loss.item())
# 3backward
optimizer.zero_grad()
loss.backward()
# 4update
optimizer.step()
结果
1 0 0.6661569476127625
1 1 0.6954756379127502
1 2 0.6754986643791199
1 3 0.6712696552276611
1 4 0.6603572368621826
1 5 0.6653342843055725
1 6 0.6750143766403198
1 7 0.695863664150238
1 8 0.6855218410491943
1 9 0.6810155510902405
1 10 0.674784243106842
1 11 0.647495448589325
1 12 0.6853384971618652
1 13 0.6627232432365417
1 14 0.6621582508087158
1 15 0.638498067855835
1 16 0.6670188903808594
1 17 0.6672930717468262
1 18 0.654869794845581
1 19 0.6667121052742004
1 20 0.6590706706047058
1 21 0.6593573093414307
1 22 0.6711141467094421
1 23 0.6575161218643188
....................
...................
...................
...................
99 18 0.7427136898040771
99 19 0.6027568578720093
99 20 0.6832196712493896
99 21 0.643141508102417
99 22 0.7225067615509033
99 23 0.6187280416488647