如何在奇数示例大小的批次中训练神经网络?
我刚开始接触神经网络(NN)这个领域,正在用pytorch进行一些训练。
我决定做一个简单的基础神经网络。
我使用了一个个人的数据集,这个数据集有2377个数值特征和6277个样本。
我第一次尝试让神经网络预测每一个样本,所以伪代码大概是这样的:
for i in range(...):
X = ... # features
y = ... # outcome
y_pred = model(X[i])
loss = criterion(y_pred, y)
y_pred.size # [1,1]
y.size # [1,1]
这个过程每个周期大约需要10秒,我决定通过使用小批量来提高效率。
所以我在开始时定义了批量大小,而在pytorch中,神经网络是这样定义的:
batch_size = 30
n_inputs = X.size[1] #2377
## 2 hidden layers
model = nn.Sequential(
nn.Linear(n_inputs, 1024),
nn.ReLU(),
nn.Linear(1024, 512),
nn.ReLU(),
nn.Linear(512, 356),
nn.ReLU(),
nn.Linear(356, batch_size),
nn.ReLU(),
)
然后我就开始按批次进行训练:
for epoch in range(5):
totalloss = 0
permutation = torch.randperm(X.size()[0])
for i in range(0, X.size()[0], batch_size):
optimizer.zero_grad()
indices = permutation[i:i+batch_size]
batch_x, batch_y = x[indices], y[indices]
ypred = model(batch_x)
loss = criterion(ypred, batch_y)
totalloss += loss.item()
## update the weights
loss.backward()
optimizer.step()
现在的问题是,我的神经网络总是输出100个值,但是最后一个批次的大小可能会变化。
实际上,如果我选择100作为批量大小,那么最后一个批次就会由77个样本组成(6277%100)。
我相信有办法解决这个问题,而且我的结构中肯定有错误,但我看不出来。
你能帮我把批量训练的过程通用化,让它能适应任何数量的样本和批量大小吗?
2 个回答
我建议你使用 Pytorch 的 DataLoader
来批量加载数据,而不是手动加载。这样做会更简单。PyTorch 提供了一个很方便的解决方案,就是在 DataLoader
中使用 drop_last
这个参数。当你把它设置为 True 时,它会丢掉最后一个不完整的批次,确保除了最后一个批次外,所有批次的大小都是一致的。Dataloader
是对 torch 的 Dataset
的一个封装,你可以在 这里 找到更多信息。
import torch
import torch.nn as nn
from torch.utils.data import DataLoader
X = torch.Tensor(...) # your features
y = torch.Tensor(...) # your labels
dataset =
# Create a DataLoader with drop_last=True
dataloader = DataLoader(dataset, batch_size=batch_size, shuffle=True, drop_last=True)
model = ...
optimizer = torch.optim.Adam(model.parameters(), lr=0.001)
criterion = nn.MSELoss()
# Training loop
num_epochs = 5
for epoch in range(num_epochs):
total_loss = 0
for batch_x, batch_y in dataloader:
optimizer.zero_grad()
y_pred = model(batch_x)
loss = criterion(y_pred, batch_y)
total_loss += loss.item()
loss.backward()
optimizer.step()
average_loss = total_loss / len(dataloader)
print(f'Epoch {epoch + 1}/{num_epochs}, Average Loss: {average_loss}')
我不明白为什么其他的回答被接受了,因为在你提问时构建模型的方式上有一个根本性的误解!而且其他的回答没有考虑到这一点。
当你定义一个模型以及它的输入和输出大小时,其实你只是在考虑一个样本。你并没有使用 batch_size
来调整输出。当你把一批输入数据放入模型时,PyTorch
会在内部处理这批数据,模型会同时对每个样本进行评估。
你可以看看官方的 PyTorch 教程,他们在这个教程中为 Fashion MNIST
数据集构建了一个模型。这个数据集中的每张图片是 (28x28x1)
像素(灰度图),并且有10个不同的类别需要预测。注意一下模型的第一层和最后一层:
nn.Linear(28*28, 512)
....
nn.Linear(512, 10)
这里的输入是图片的像素 28*28
,输出是 10
个数字,代表10个类别。然后你可以使用 SoftMax
或 categorical_crossentropy
来进行预测。模型本身并没有关于批量大小的信息,因为模型并不需要这些。
大多数情况下,最后一批数据的大小比其他批次小一点也没问题。如果你的批量大小是 32
,但最后一批只有 15
个样本,模型会只处理这15个样本和标签,进行预测,并将这15个结果与最后一批的15个标签进行比较。
如果出于某种原因你需要所有批次的大小完全相同(例如,对于有状态的 LSTM
),那么你可以使用 DataLoader
并设置 drop_last=True
。但大多数情况下,这并不是必要的,如果你使用它,模型只会忽略掉一些数据。
使用 DataLoader
仍然是个好主意,因为它们可以高效地在CPU上加载你的数据,而模型则可以在GPU上进行训练。