我从Keras转到PyTorch,其中一个令人惊讶的发现是我需要实现自己的训练循环。
在Keras中,有一个事实上的
在PyTorch中,程序员似乎需要实现训练循环。由于我刚接触PyTorch,不知道我的训练循环实现是否正确。我只想比较与Keras中看到的损失和准确性指标相同。 我已经阅读过:
我感到沮丧的几点是:
1.从数据加载器中提取数据在图像数据和NLP数据之间不一致。
2.正确计算损失和准确性在任何示例代码中都不一致。
3.一些代码示例使用Variable,而其他代码则不使用。
4.过于详细:将数据移动到/从GPU;知道何时调用zero_grad()。
就目前而言,这是我的当前实现。有什么明显的错误吗?
在Keras中,有一个事实上的
fit()
函数:(1)运行梯度下降,(2)收集损失和准确性的历史指标,包括训练集和验证集。在PyTorch中,程序员似乎需要实现训练循环。由于我刚接触PyTorch,不知道我的训练循环实现是否正确。我只想比较与Keras中看到的损失和准确性指标相同。 我已经阅读过:
官方PyTorch 60分钟入门, 其中提供了一个样本训练循环。
官方PyTorch示例代码, 我发现训练循环嵌入其他代码中。
O'Reilly图书Programming PyTorch for Deep Learning自带训练循环。
斯坦福CS230 示例代码。
我感到沮丧的几点是:
1.从数据加载器中提取数据在图像数据和NLP数据之间不一致。
2.正确计算损失和准确性在任何示例代码中都不一致。
3.一些代码示例使用Variable,而其他代码则不使用。
4.过于详细:将数据移动到/从GPU;知道何时调用zero_grad()。
就目前而言,这是我的当前实现。有什么明显的错误吗?
import time
def train(model, optimizer, loss_fn, train_dl, val_dl, epochs=20, device='cuda'):
'''
Runs training loop for classification problems. Returns Keras-style
per-epoch history of loss and accuracy over training and validation data.
Parameters
----------
model : nn.Module
Neural network model
optimizer : torch.optim.Optimizer
Search space optimizer (e.g. Adam)
loss_fn :
Loss function (e.g. nn.CrossEntropyLoss())
train_dl :
Iterable dataloader for training data.
val_dl :
Iterable dataloader for validation data.
epochs : int
Number of epochs to run
device : string
Specifies 'cuda' or 'cpu'
Returns
-------
Dictionary
Similar to Keras' fit(), the output dictionary contains per-epoch
history of training loss, training accuracy, validation loss, and
validation accuracy.
'''
print('train() called: model=%s, opt=%s(lr=%f), epochs=%d, device=%s\n' % \
(type(model).__name__, type(optimizer).__name__,
optimizer.param_groups[0]['lr'], epochs, device))
history = {} # Collects per-epoch loss and acc like Keras' fit().
history['loss'] = []
history['val_loss'] = []
history['acc'] = []
history['val_acc'] = []
start_time_sec = time.time()
for epoch in range(epochs):
# --- TRAIN AND EVALUATE ON TRAINING SET -----------------------------
model.train()
train_loss = 0.0
num_train_correct = 0
num_train_examples = 0
for batch in train_dl:
optimizer.zero_grad()
x = batch[0].to(device)
y = batch[1].to(device)
yhat = model(x)
loss = loss_fn(yhat, y)
loss.backward()
optimizer.step()
train_loss += loss.data.item() * x.size(0)
num_train_correct += (torch.max(yhat, 1)[1] == y).sum().item()
num_train_examples += x.shape[0]
train_acc = num_train_correct / num_train_examples
train_loss = train_loss / len(train_dl.dataset)
# --- EVALUATE ON VALIDATION SET -------------------------------------
model.eval()
val_loss = 0.0
num_val_correct = 0
num_val_examples = 0
for batch in val_dl:
x = batch[0].to(device)
y = batch[1].to(device)
yhat = model(x)
loss = loss_fn(yhat, y)
val_loss += loss.data.item() * x.size(0)
num_val_correct += (torch.max(yhat, 1)[1] == y).sum().item()
num_val_examples += y.shape[0]
val_acc = num_val_correct / num_val_examples
val_loss = val_loss / len(val_dl.dataset)
print('Epoch %3d/%3d, train loss: %5.2f, train acc: %5.2f, val loss: %5.2f, val acc: %5.2f' % \
(epoch+1, epochs, train_loss, train_acc, val_loss, val_acc))
history['loss'].append(train_loss)
history['val_loss'].append(val_loss)
history['acc'].append(train_acc)
history['val_acc'].append(val_acc)
# END OF TRAINING LOOP
end_time_sec = time.time()
total_time_sec = end_time_sec - start_time_sec
time_per_epoch_sec = total_time_sec / epochs
print()
print('Time total: %5.2f sec' % (total_time_sec))
print('Time per epoch: %5.2f sec' % (time_per_epoch_sec))
return history
Trainer
类 [示例]。不确定它是否仅用于微调预训练的转换器,还是用于一般用途。 - Alaa M.