【问题标题】:How to write a custom f1 loss function with weighted average for keras?如何为keras编写带有加权平均值的自定义f1损失函数?
【发布时间】:2020-05-14 18:19:14
【问题描述】:

我正在尝试在 keras 中进行多类分类。到目前为止,我正在使用 categorical_crossentropy 作为损失函数。但由于所需的指标是 weighted-f1,我不确定 categorical_crossentropy 是否是最佳损失选择。我试图使用 sklearn.metrics.f1_score 在 keras 中实现加权 f1 分数,但由于张量和标量之间的转换问题,我遇到了错误。

类似这样的:

def f1_loss(y_true, y_pred):
   return 1 - f1_score(np.argmax(y_true, axis=1), np.argmax(y_pred, axis=1), average='weighted')

紧随其后

 model.compile(loss=f1_loss, optimizer=opt)

如何在 keras 中编写这个损失函数?

编辑:

y_true 和 y_pred 的形状是 (n_samples, n_classes) 在我的例子中是 (n_samples, 4)

y_truey_pred 都是 张量,所以 sklearn 的 f1_score 不能直接作用于它们。我需要一个计算张量的加权 f1 的函数。

【问题讨论】:

标签: python-3.x tensorflow keras scikit-learn


【解决方案1】:

变量是自我解释的:

def f1_weighted(true, pred): #shapes (batch, 4)

    #for metrics include these two lines, for loss, don't include them
    #these are meant to round 'pred' to exactly zeros and ones
    #predLabels = K.argmax(pred, axis=-1)
    #pred = K.one_hot(predLabels, 4) 


    ground_positives = K.sum(true, axis=0) + K.epsilon()       # = TP + FN
    pred_positives = K.sum(pred, axis=0) + K.epsilon()         # = TP + FP
    true_positives = K.sum(true * pred, axis=0) + K.epsilon()  # = TP
        #all with shape (4,)
    
    precision = true_positives / pred_positives 
    recall = true_positives / ground_positives
        #both = 1 if ground_positives == 0 or pred_positives == 0
        #shape (4,)

    f1 = 2 * (precision * recall) / (precision + recall + K.epsilon())
        #still with shape (4,)

    weighted_f1 = f1 * ground_positives / K.sum(ground_positives) 
    weighted_f1 = K.sum(weighted_f1)

    
    return 1 - weighted_f1 #for metrics, return only 'weighted_f1'

重要提示:

此损失将分批工作(与任何 Keras 损失一样)。

因此,如果您使用的是小批量,每批之间的结果将不稳定,您可能会得到一个糟糕的结果。 使用大批量,足以包含所有类别的大量样本。

由于这种损失会破坏批量大小,因此您将无法使用依赖于批量大小的某些 Keras 功能,例如样本权重。

【讨论】:

  • 正是我想要的。谢谢
  • 我的加权 f1 分数大于 1,使用您的实现
  • @learner,您是否使用“二进制”输出和目标,两者的形状完全相同?
  • @Daniel Moller 我正在研究一个多分类问题
  • @Daniel Moller:我的实现导致了 nan 验证损失。有什么线索吗?
猜你喜欢
  • 2019-11-28
  • 2020-10-05
  • 2021-09-21
  • 2018-02-24
  • 2020-12-21
  • 2019-06-25
  • 2018-04-03
  • 1970-01-01
  • 2018-05-05
相关资源
最近更新 更多