上一篇训练神经网络是用的是批梯度下降,容易陷入鞍点中。Pytorch 提供了一个数据集加载工具,使得我们可以方便地用小批量随机梯度下降来训练网络。其包含两个部分:
# 训练循环
for epoch in range(trainning_epochs):
# 用所有 Mini-Batch 训练
for i in range(total_batch): # 执行 Iteration 次
pass
torch.utils.data.DataLoader(dataset, batch_size=1, shuffle=False, sampler=None, batch_sampler=None, num_workers=0, collate_fn=None, pin_memory=False, drop_last=False, timeout=0, worker_init_fn=None, multiprocessing_context=None)
参数释义:
假设 batch_dize=2,shuffle=True, 经 DataLoader 过程如下:
从左至右先打乱样本顺序最终得到一个可迭代的 Loader,每次迭代将(yield)产生一个 Mini-Batch 用于训练网络。
Dataset 是一个抽象类,无法被实例化。只能被其子类继承,再实例化。因此,若要实例化 Dataset 我们必须自己写一个类来继承自它。其结构大致为:
from torch.utils.data import Dataset # Dataset 是一个抽象类, 不能实例化
from torch.utils.data import DataLoader
class MyDataset(Dataset):
def __init__(self, filepath):
# 加载数据集,如 csv 文件等,有两种方式:# 1. All in: 将所有数据加载到内存 (适用于数据集不大的情况)
# 2. 如果数据集很大,可以分割成内存允许大小的文件,用一个列表放文件名,然后训练时用 getitem 函数时在将其读取到内存中
pass
def __getitem__(self,index): # 使对象支持下标操作 dataset[index]
pass
def __len__(self): # 返回数据集中的样本数
pass
实例化数据集对象:
dataset = DiabetesDataset(filepath)
train_loader = DataLoader(dataset=dataset,batch_size=32,shuffle=True,num_workers=2)
import torch
import numpy as np
from torch.utils.data import Dataset # Dataset 是一个抽象类, 不能实例化
from torch.utils.data import DataLoader
class DiabetesDataset(Dataset):
def __init__(self, filepath):
# 数据集很小,直接加载进内存
xy = np.loadtxt(filepath,delimiter=',',dtype=np.float32)
self.len = xy.shape[0] # 取 行 数(样本数)
self.x_data = torch.from_numpy(xy[:,:-1]) # 所有行,最后一列不要
self.y_data = torch.from_numpy(xy[:,[-1]]) # 所有行,只要最后一列,- 1 加 [] 表示拿出来一个矩阵,而不是向量
def __getitem__(self,index):
return self.x_data[index], self.y_data[index] # 返回一个元组(x,y)def __len__(self):
return self.len
dataset = DiabetesDataset('https://project-preview-1257022783.cos.ap-chengdu.myqcloud.com/diabetes.csv.gz')
train_loader = DataLoader(dataset=dataset,batch_size=32,shuffle=True,num_workers=2)
for epoch in range(100):
for i, data in enumerate(train_loader,0): # for i, (data,labels) in enumerate(train_loader,0):
# 准备数据
inputs, labels = data # 自动转换成 Tensor
# 前馈计算
y_pred = model(inputs)
loss = criterion(y_pred,labels)
#print(epoch, i, loss.item())
# 反向传播
optimizer.zero_grad()
loss.backward()
# 更新参数
optimizer.step()
这些数据集都继承与 torch.utils.data.Dataset
, 都具有 getitem 和 len 函数的实现,可以直接用 torch.utils.data.DataLoader
进行加载。
import torch
from torch.utils.data import DataLoader
from torchvision import transforms
from torchvision import datasets
# Mnist
import torch
import torchvision
from torch.utils.data import DataLoader
from torchvision import transforms
from torchvision import datasets
# FashionMnist
train_dataset = torchvision.datasets.FashionMNIST(root='./dataset/fmnist/',train=True,transform=transforms.ToTensor(),download=True)
test_dataset = torchvision.datasets.FashionMNIST(root='./dataset/fmnist/',train=False,transform=transforms.ToTensor(),download=True)
train_loader = torch.utils.data.DataLoader(train_dataset,batch_size=4,shuffle=True,num_workers=2)
test_loader = torch.utils.data.DataLoader(test_dataset,batch_size=4,shuffle=False) # 测试不需要 shuffle 打乱顺序,保证结果的顺序
# 训练
for epoch in range(epoch_trainning):
for batch_idx, (inputs, target) in enumerate(train_loader,0):
pass # 前馈、反馈计算