我可以用pytorch训练(优化)f1分数损失吗

问题描述 投票:0回答:2

我正在构建一个如下所示的二元分类器。我可以替换 BCELoss 来优化 f1 分数吗?

criterion = nn.BCELoss()

preds = model(inputs)
loss = criterion(preds , labels)
tensorflow deep-learning neural-network pytorch
2个回答
11
投票

F1分数不是平滑函数,因此不能直接用梯度下降来优化。随着网络参数逐渐变化,输出概率平滑变化,但 F1 分数仅在概率越过 0.5 边界时发生变化。结果,F1 分数的梯度几乎到处都是零。

您可以使用 F 测量的软版本,如此处所述。诀窍在于,您基本上用某种概率版本替换真阳性和假阳性的计数:

其中 oi 是网络输出,ti 是地面真实目标概率。然后您继续照常计算 F 测量。

这些定义随后用于公式 F1=2TP/(2TP+FP+FN)。

此外,您可能会发现这个 Kaggle 教程 很有用。


1
投票

Jindřich 提到的 Kaggle 教程中显示的 TensorFlow 示例的一个 PyTorch 实现是:

import torch

def f1(y_true, y_pred):
    y_pred = torch.round(y_pred)
    tp = torch.sum((y_true * y_pred).float(), dim=0)
    tn = torch.sum(((1 - y_true) * (1 - y_pred)).float(), dim=0)
    fp = torch.sum(((1 - y_true) * y_pred).float(), dim=0)
    fn = torch.sum((y_true * (1 - y_pred)).float(), dim=0)

    p = tp / (tp + fp + 1e-7)
    r = tp / (tp + fn + 1e-7)

    f1 = 2 * p * r / (p + r + 1e-7)
    f1 = torch.where(torch.isnan(f1), torch.zeros_like(f1), f1)
    return torch.mean(f1)

def f1_loss(y_true, y_pred):
    tp = torch.sum((y_true * y_pred).float(), dim=0)
    tn = torch.sum(((1 - y_true) * (1 - y_pred)).float(), dim=0)
    fp = torch.sum(((1 - y_true) * y_pred).float(), dim=0)
    fn = torch.sum((y_true * (1 - y_pred)).float(), dim=0)

    p = tp / (tp + fp + 1e-7)
    r = tp / (tp + fn + 1e-7)

    f1 = 2 * p * r / (p + r + 1e-7)
    f1 = torch.where(torch.isnan(f1), torch.zeros_like(f1), f1)
    return 1 - torch.mean(f1)
© www.soinside.com 2019 - 2024. All rights reserved.