刘二大人《PyTorch深度学习实践》p8加载数据集
一、零碎知识点
1.enumerate()
enumerate()
是python的一个内置函数,用于对可迭代对象进行遍历,并返回索引和对应的元素。
citys = ["wuhan", "chengdu", "shanghai", "beijing"]
for index,city in enumerate(citys):
print(index,city)
# output:
0 wuhan
1 chengdu
2 shanghai
3 beijing
在深度学习中,enumerate(train_loader, 0)
将训练数据加载器train_loader
作为第一个参数传递给enumerate()
函数,同时将起始索引设置为0。这样,遍历训练数据加载器时,会返回每个小批次的索引和对应的训练样本,获取当前是第几次迭代。
二、Batch(批次)和Mini-Batch
假设我们有一个训练集包含10000个图像样本,用于进行手写数字识别任务。
如果我们选择不使用Mini-batch,直接将整个训练集作为一个批次进行训练,那么每次迭代更新参数时,我们需要计算10000个样本的损失和梯度,然后更新参数,计算和更新参数的代价非常高。
在选择使用Mini-batch时,设置batch-size=1000,在每个迭代中,我们只计算并更新一个Mini-batch的损失和梯度。那么只需要迭代10次便可完成计算。
1.Mini-Batch
- Epoch(训练周期)
Epoch是训练神经网络时的一个概念,表示将所有训练样本都通过神经网络进行前馈传播和反向传播的一次迭代。 - Batch-Size(批次大小)
Batch-Size是指在训练过程中每个迭代步骤中用于更新模型参数的样本数量。 - Iteration(迭代)
Iteration表示完成一次batch训练所需更新权重和偏置参数的迭代次数。
2.Dataset(数据集)
Dataset是一个抽象类,用于表示数据集的抽象接口。它定义了一些必须实现的方法,例如__len__
(返回数据集的大小)和__getitem__
(通过索引获取样本)等。通过创建一个数据集对象,我们可以访问和处理数据集中的样本。
我的通俗理解是:dataset是一个支持索引index[i]和长度len的数据集
import torch
from torch.utils.data import Dataset
from torch.utils.data import DataLoader
3.DataLoader(数据加载器)
# 创建数据加载器
train_loader = DataLoader(dataset=dataset,
batch_size=2,
shuffle=True,
num_workers=2)
- dataset=dataset
- batch_size=2(一个批次里面含有两个样本)
- shuffle=True
为了提高训练的随机性,对数据集进行打乱。 - num_workers=2
将来读数据集的时候,需要几个并行进程来去读取数据。
三、课程代码
- 准备数据集
- 构造模型
- 构造损失函数和优化器
- 训练周期循环
import numpy as np
import torch
from matplotlib import pyplot as plt
from torch.utils.data import 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]])
def __getitem__(self, index):
return self.x_data[index], self.y_data[index] # 返回的是元祖
def __len__(self):
return self.len
dataset = DiabetesDataset('diabetes.csv') # 自定义的糖尿病数据类把dataset实例化为对象
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.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.BCELoss(reduction='mean')
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)
losses = []
if __name__ == '__main__':
for epoch in range(100):
epoch_losses = [] # 创建一个空列表来保存当前训练周期的损失值
for i, data in enumerate(train_loader, 0):
# 1.准备数据集
inputs, labels = data # inputs和label都是张量
# 2.构造模型
y_pred = model(inputs)
loss = criterion(y_pred, labels)
epoch_losses.append(loss.item())
print(epoch, i, loss.item())
# 3.构造损失和优化器
optimizer.zero_grad()
loss.backward()
# 4.训练周期
optimizer.step()
# 计算当前训练周期的平均损失值并保存到总损失列表中
avg_loss = sum(epoch_losses) / len(epoch_losses)
losses.append(avg_loss)
plt.plot(losses)
plt.xlabel('Epoch')
plt.ylabel('Loss')
plt.title('Training Loss')
plt.show()
损失值出现震荡,总体呈现下降的趋势。
课后作业连接,大家可以去做看看:Titanic - Machine Learning from Disaster
小结:这节看似短短的三十几分钟,对于我这个pytorch小白真的好难理解,难怪那么多人开玩笑说“从入门到放弃”,老师布置的课后作业还没做,准备明天去做,周末晚上浅学了一小会儿,收工啦。经常会内耗,研一没参加任何竞赛,也没学到什么东西,不知道大家学的怎么样了,真的好想像师兄那样,研一的下的暑假就发小论文,道阻且长,行将必至。