本节内容是学习 刘二大人的《PyTorch深度学习实践》的 08 Dataset and DataLoader (加载数据集)。
上节内容:07 Multiple Dimension Input (处理多维特征的输入)-CSDN博客
这节内容:
目录
一、Epoch,Batch-Size,Iterations
二、DataLoader:batch_size=2, shuffle=True
三、How to define your Dataset ?
四、Diabetes Dataset
五、Using DataLoader
六、outputs
七、torchvision.datasets
一、Epoch,Batch-Size,Iterations
先看这两行代码:
# Training cycle
for epoch in range(training_epochs):
# Loop over all batches
for i in range(total_batch):
这是一个嵌套循环,每一次循环就是一个 epoch ,每一次 epoch 中,我们再执行一次循环,这次循环,每一次迭代,我们都会执行一次 Mini-Batch 。
Epoch:One forward pass and one backward pass of all the training examples. 也就是说,当所有的训练样本,都进行了一次正向的前向传播和反馈传播。
Bach-Size:The number of training examples in one forward backfard pass. 也即是说,我们每次训练的时候所用的样本数量。
Iterations:Number of passes, each pass using [ batch-size ] number of examples. 也就是说,内层循环了多少次。
假设你有10000个样本,一个 batch-size 内部有1000个样本,那么 Iterations 就是10.
二、DataLoader:batch_size=2, shuffle=True
接下来取个例子,我们让下面的这些数据 batch_size=2, 在此之前我们要将其打乱,也就是说进行 shuffle 。
三、How to define your Dataset ?
import torch
from torch.utils.data import Dataset,Dataloader # 从utils工具箱里面引入Dataset,Dataloader
# Dataset是个抽象的类,是不能实例化的
# Dataloader用来加载数据,可以实例化
class DiabetesDataset(Dataset): # 自定义一个类DiabetesDataset,继承Dataset的一些基本功能
def __init__(self): # 初始化
pass
def __getitem__(self, index): # 可以通过一个索引进行操作
pass
def __len__(self):
pass
dataset = DiabetesDataset() # 用自定义的类DiabetesDataset,把它实例化成一个数据对象
train_loader = DataLoader(dataset=dataset, batch_size=32, shuffle=True, num_workers=2)
# DataLoader加载器,一般情况下在初始化的时候传递四个量,第一个就是数据dataset,第二个是一个小批量batch_zise的容量,第三个是是否打乱数据,一般训练的时候,我们选择shuffle=True打乱,第四个是读取mini-batch的是时候需要几个并行进程读取数据
extra: num_workers in Windows
如果我们直接用下面的这样的代码,也就是说直接用 DataLoader 去训练,那么将会报错。
报错原因:
(稍微了解一下原因就行了叭,只要知道正确的写法应该就可以了叭)
解决方法:
我们需要对其进行封装,可以用 if 语句或者函数进行封装,如下:
四、Diabetes Dataset
我们看一下糖尿病这个数据集的实现:
class DiabetesDataset(Dataset):
def __init__(self, filepath): # filepath文件地址
xy = np.loadtxt(filepath, delimiter=',', dtype=np.float32) #将文件加载进来,内部数据用逗号作为分隔符,读取一个32位的浮点数
self.len = xy.shape[0] # xy是个n行9列的矩阵,n是数据样本的数量。那么它的尺寸形状就是(N,9),所以xy.shape[0]是指的取出第0元素,也就是是说把N的值取出来
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 = DiabetesDataset('diabetes.csv.gz')
train_loader = DataLoader(dataset=dataset, batch_size=32, shuffle=True, num_workers=2)
五、Using DataLoader
for epoch in range(100):
for i, data in enumerate(train_loader, 0): # enumerate是为得到第几次迭代,(x,y)放在data中
# 1.Prepare data
inputs, labels = data # inputs就是x,labels就是y
# 2.Forward
y_pred = model(inputs)
loss = criterion(y_pred, labels)
print(eopoch, i, loss.item())
# 3.Backward
optimizer.zero_grad() # 优化器权重清零
loss.backward()
# 4.Update
optimizer.step() # 优化更新
六、outputs
import torch
import numpy as np
from torch.utils.data import Dataset, DataLoader
class DiabetesDataset(Dataset):
def __init__(self, filepath): # filepath文件地址
xy = np.loadtxt(filepath, delimiter=',', dtype=np.float32) #将文件加载进来,内部数据用逗号作为分隔符,读取一个32位的浮点数
self.len = xy.shape[0] # xy是个n行9列的矩阵,n是数据样本的数量。那么它的尺寸形状就是(N,9),所以xy.shape[0]是指的取出第0元素,也就是是说把N的值取出来
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 = DiabetesDataset('D:\\STUDY1\\LIUER\\08加载数据集\\diabetes08.csv')
train_loader = DataLoader(dataset=dataset, batch_size=32, shuffle=True, num_workers=0)
class Model(torch.nn.Module):
def __init__(self):
super(Model, self).__init__()
self.linear1 = torch.nn.Linear(8, 6)
self.linear2 = torch.nn.Linear(6, 4)
self.linear3 = torch.nn.Linear(4, 1)
self.sigmoid = torch.nn.Sigmoid()
def forward(self, x):
x = self.sigmoid(self.linear1(x))
x = self.sigmoid(self.linear2(x))
x = self.sigmoid(self.linear3(x))
return x
model = Model()
# 损失函数
criterion = torch.nn.MSELoss(reduction='mean')
# 优化器
optimizer = torch.optim.SGD(model.parameters(), lr=0.1)
for epoch in range(100):
for i, data in enumerate(train_loader, 0): # enumerate是为得到第几次迭代,(x,y)放在data中
# 1.Prepare data
inputs, labels = data # inputs就是x,labels就是y
# 2.Forward
y_pred = model(inputs)
loss = criterion(y_pred, labels)
print(epoch, i, loss.item())
# 3.Backward
optimizer.zero_grad() # 优化器权重清零
loss.backward()
# 4.Update
optimizer.step() # 优化更新
输出结果:
注意:在这个完整的代码里面,num_workers=0, 是单线程。
但我们这节课教的是多线程,所以记得在训练前加上 if __name__='main':
七、torchvision.datasets
torchvision内置了好多数据集(MNIST、Fashion-MNIST、EMNIST、COCO、LSUN、ImageFolder、DatasetFolder、Imageenet-12、CIFAR、STL10,都可以用下面这种结构,以 ImageFolder 为例:
example: MNIST
下节内容:09多分类问题