PyTorch–数据加载和处理

一、数据处理与加载

torch.utils.data.Datasettorch.utils.data.DataLoader是pytorch中高效地处理数据,帮助我们管理数据集、批量加载和数据增强的强大工具。

**full-batch:**直接加载所有的样本数据.

**mini-batch:**将样本数据分成等量的子集,训练或测试时将所有子集进行迭代,遍历完所有的样本后算作一个epoch.

mini-batch优点:可以加快训练速度;可以更有效地更新模型参数,克服鞍点;减少内存占用,尤其是处理大型数据集时,不需要一次性将整个数据集加载到内存中。

Mini-Batch 的缺点:由于每次梯度下降只使用部分数据,可能导致模型的精度较低;在训练过程中,损失函数可能会出现上下波动,但总体趋势是下降的。

**epoch:**所有的训练次数

**batch-size:**一次训练用的数据

**iteration:**内层迭代

1.dataset

通过继承 torch.utils.data.Dataset这个抽象类 来加载自己的数据集。

Dataset 两种使用方式
  1. 将所有数据一次性加载进内存:适用于数据规模较小的场景。
  2. 按需加载数据:适用于数据量较大的场景,如图像或语音数据,按索引逐批加载,节约内存。
1
2
3
4
5
6
7
8
class DiadetsDataset(Dataset):
def __init__(self):#初始化
pass
def __getitem__(self, index):#索引
pass
def __len__(self):#长度
pass
dataset = DiadetsDataset()

2、dataLoader

DataLoader 按批次加载数据,支持多线程加载并进行数据打乱。

1
2
3
4
5
6
7
8
9
10
11
train_loader = DataLoader(dataset=dataset,
batch_size=32,
shuffle=True, #指定batch_size,如果需要打乱数据,shuffle=True
num_workers=2)#num_workers个并行进程

#for epoch in range(100):
# for i,data in enumerate(train_loader,0):
#这样windows下会报错
if __name__ == '__main__':
for epoch in range(100):
for i,data in enumerate(train_loader,0):

三、完整代码示例

刘二大人PyTorch深度学习实践 完整代码(利用matplotlib库进行可视化):

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 numpy as np
import torch
import matplotlib.pyplot as plt

from torch.utils.data import Dataset # 是一个抽象类,只能继承,不能实例化
from torch.utils.data import DataLoader

class DiadetesDataset(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]])

def __getitem__(self, index):
return self.x_data[index], self.y_data[index]

def __len__(self):
return self.len


dataset = DiadetesDataset('./data/diabetes.csv.gz')
train_loader = DataLoader(dataset=dataset,
batch_size=32,
shuffle=True,
num_workers=2) # num_workers个并行进程


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)) # 这样可以一直用x
return x

model = Model()

criterion = torch.nn.BCELoss(reduction='mean')
optimizer = torch.optim.SGD(model.parameters(), lr=0.001)

epoch_list = []
loss_list = []

if __name__ == '__main__':
for epoch in range(100):
total_loss = 0.0
for i, data in enumerate(train_loader, 0):
inputs, labels = data # 自动变成tensor
y_pred = model(inputs)
loss = criterion(y_pred, labels)
total_loss += loss

optimizer.zero_grad()
loss.backward()
optimizer.step()

average_loss = total_loss / len(train_loader)
epoch_list.append(epoch)
loss_list.append(average_loss)
print("Epoch:", epoch, "average loss:", average_loss)

# 训练完后绘制损失曲线
# 如果 epoch_list 和 loss_list 是 Tensor
epoch_list = np.array(epoch_list) # 将 epoch_list 转换为 numpy 数组
loss_list = [loss.detach().numpy() for loss in loss_list] # 对 loss_list 中的每个 tensor 进行转换
plt.plot(epoch_list, loss_list, label='Loss Curve', marker='o')
plt.xlabel('Epoch')
plt.ylabel('Loss')
plt.title('Loss Curve')
plt.legend()
plt.grid(True)
plt.show()

image-20241222190646212

image-20241222194143565