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。这样,遍历训练数据加载器时,会返回每个小批次的索引和对应的训练样本,获取当前是第几次迭代。
假设我们有一个训练集包含10000个图像样本,用于进行手写数字识别任务。
如果我们选择不使用Mini-batch,直接将整个训练集作为一个批次进行训练,那么每次迭代更新参数时,我们需要计算10000个样本的损失和梯度,然后更新参数,计算和更新参数的代价非常高。
在选择使用Mini-batch时,设置batch-size=1000,在每个迭代中,我们只计算并更新一个Mini-batch的损失和梯度。那么只需要迭代10次便可完成计算。
Dataset是一个抽象类,用于表示数据集的抽象接口。它定义了一些必须实现的方法,例如__len__
(返回数据集的大小)和__getitem__
(通过索引获取样本)等。通过创建一个数据集对象,我们可以访问和处理数据集中的样本。
我的通俗理解是:dataset是一个支持索引index[i]和长度len的数据集
import torch
from torch.utils.data import Dataset
from torch.utils.data import DataLoader
# 创建数据加载器
train_loader = DataLoader(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小白真的好难理解,难怪那么多人开玩笑说“从入门到放弃”,老师布置的课后作业还没做,准备明天去做,周末晚上浅学了一小会儿,收工啦。经常会内耗,研一没参加任何竞赛,也没学到什么东西,不知道大家学的怎么样了,真的好想像师兄那样,研一的下的暑假就发小论文,道阻且长,行将必至。