PyTorch深度学习实践Part8——加载数据集

Dataset and DataLoader

  1. Dataset:主要构造数据集,支持索引。

  2. DataLoader:主要能拿出mini-batch,拿出一组组数据以快速使用。

    改成mini-batch之后,训练循环会变成一个二层的嵌套循环,第一层迭代epoch,第二层迭代mini-batch。

  3. Epoch:将所有的样本都参与了一次正向传播、训练,是一次epoch。

  4. Batch-Size:每次训练(前馈+反馈+更新)所用的样本数量。

  5. Iteration:batch分了多少批,内层的迭代执行多少次。例如:1w个样本,1k个batch,iteration为10。

image-20210118100748425

代码实现

处理数据方式

  1. 全部读取到内存,适用于关系表或者小批量结构化的数据。
  2. 将数据文件分开,路径存放在列表中打包,适用于图像、音频等非结构化数据。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
import torch
import numpy as np
import matplotlib.pyplot as plt
from torch.utils.data import DataLoader
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] # shape(行数,列数)是元组
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')
# shuffle=True打乱mini-batch保证随机,num_workers多线程
train_loader = DataLoader(dataset=dataset, batch_size=32, shuffle=True, num_workers=2)


# 创建模型
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.activate = torch.nn.Sigmoid() # 是模块而不是函数,没有参数,没有需要训练的地方,只用来构建计算图

def forward(self, x):
x = self.activate(self.linear1(x))
x = self.activate(self.linear2(x))
x = self.activate(self.linear3(x))
return x


model = Model()

# 损失&优化
criterion = torch.nn.BCELoss(reduction='mean')
# model.parameters()会扫描module中的所有成员,如果成员中有相应权重,那么都会将结果加到要训练的参数集合上
optimizer = torch.optim.SGD(model.parameters(), lr=1)
loss_list = []

# 循环训练
if __name__ == '__main__': # 在windows系统下要用if封装训练循环,否则会报错
for epoch in range(100):
loss_sum = 0
num = 0
for i, data in enumerate(train_loader, 0):
# prepare data
inputs, labels = data # 此时两个已经转化成tensor
# Forward
y_pred = model(inputs)
loss = criterion(y_pred, labels)
print(epoch, i, loss.item())

loss_sum += loss.item()
num += 1
# Backward
optimizer.zero_grad()
loss.backward()
# Update
optimizer.step()

loss_list.append(loss_sum / num)

plt.plot(range(100), loss_list)
plt.ylabel('loss')
plt.xlabel('epoch')
plt.show()

image-20210118110538070

二层循环速度反而变慢了,效率也没有很大提升?t