PyTorch 中的高效指标评估

Posted

技术标签:

【中文标题】PyTorch 中的高效指标评估【英文标题】:Efficient metrics evaluation in PyTorch 【发布时间】:2019-10-31 18:24:33 【问题描述】:

我是 PyTorch 的新手,希望在训练和验证循环期间有效地评估 F1。

到目前为止,我的方法是在 GPU 上计算预测,然后将它们推送到 CPU 并将它们附加到一个向量中以进行训练和验证。在训练和验证之后,我将使用 sklearn 对每个 epoch 进行评估。但是,分析我的代码显示,推送到 cpu 是一个相当大的瓶颈。

for epoch in range(n_epochs):
    model.train()
    avg_loss = 0
    avg_val_loss = 0
    train_pred = np.array([])
    val_pred = np.array([])
    # Training loop (transpose X_batch to fit pretrained (features, samples) style)
    for X_batch, y_batch in train_loader:
        scores = model(X_batch)
        y_pred = F.softmax(scores, dim=1)
        train_pred = np.append(train_pred, self.get_vector(y_pred.detach().cpu().numpy()))

        loss = loss_fn(scores, self.get_vector(y_batch))
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
        avg_loss += loss.item() / len(train_loader)

    model.eval()
    # Validation loop
    for X_batch, y_batch in val_loader:
        with torch.no_grad():
            scores = model(X_batch)
            y_pred = F.softmax(scores, dim=1)
            val_pred = np.append(val_pred, self.get_vector(y_pred.detach().cpu().numpy()))
            loss = loss_fn(scores, self.get_vector(y_batch))
            avg_val_loss += loss.item() / len(val_loader)

    # Model Checkpoint for best validation f1
    val_f1 = self.calculate_metrics(train_targets[val_index], val_pred, f1_only=True)
    if val_f1 > best_val_f1:
        prev_best_val_f1 = best_val_f1
        best_val_f1 = val_f1
        torch.save(model.state_dict(), self.PATHS['xlm'])
        evaluated_epoch = epoch

    # Calc the metrics
    self.save_metrics(train_targets[train_index], train_pred, avg_loss, 'train')
    self.save_metrics(train_targets[val_index], val_pred, avg_val_loss, 'val')

我确信有一种更有效的方法 a) 存储预测,而不必每批次将它们推送到 cpu。 b) 直接在 GPU 上计算指标?

由于我是 PyTorch 的新手,我非常感谢任何提示和反馈 :)

【问题讨论】:

【参考方案1】:

您可以在 pytorch 中自己计算 F 分数。 F1 分数仅针对单类(真/假)分类定义。您唯一需要做的就是汇总以下数量:

地面实况目标数据中的类计数; 预测中的类计数; 计算该类被正确预测的次数。

假设您要计算 softmax 中索引为 0 的班级的 F1 分数。在每个批次中,您都可以:

predicted_classes = torch.argmax(y_pred, dim=1) == 0
target_classes = self.get_vector(y_batch)
target_true += torch.sum(target_classes == 0).float()
predicted_true += torch.sum(predicted_classes).float()
correct_true += torch.sum(
    predicted_classes == target_classes * predicted_classes == 0).float()

当所有批次都处理完毕时:

recall = correct_true / target_true
precision = correct_true / predicted_true
f1_score = 2 * precission * recall / (precision + recall)

不要忘记处理精度和召回率为零以及根本无法预测所需类别的情况。

【讨论】:

“F1 分数仅针对单类(真/假)分类定义”,不是真的 chk scikit-learn.org/stable/modules/generated/…,参数 average (半)与此相关:计算指标时,是否有理由希望在 CPU 而不是 GPU 上进行计算?这就是他们在Andrew Ng's tutorial 中的做法(移至 CPU)。我还就此向a question 询问过,如果您能提供任何见解,我将不胜感激。

以上是关于PyTorch 中的高效指标评估的主要内容,如果未能解决你的问题,请参考以下文章

图像融合评估指标Python版

PyTorch - 如何在评估模式下停用辍学

Pytorch 训练和评估不同的样本大小

PyTorch Lightning 是不是在整个时期内平均指标?

全网最详细使用PyTorch实现循环神经网络

使用pytorch计算分类模型的混淆矩阵