You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

TensorFlow/Keras中如何为二分类损失函数加权真阳性与真阴性?

好问题!默认的加权交叉熵只给正样本整体加权重,但要给TP、TN、FP、FN四个结果分别加权,确实需要自定义损失函数。下面是具体的实现思路和代码:

自定义四分类加权交叉熵损失函数

首先,先明确我们的目标:给二分类的四个结果(真阳性TP、假阴性FN、真阴性TN、假阳性FP)分别设置独立的权重,替代原来仅针对正样本的pos_weight。

核心思路

标准的二分类交叉熵损失可以拆解为四个部分的组合,但默认是对正负样本的错误预测(FN、FP)和正确预测(TP、TN)使用相同的权重。要实现分别加权,我们需要:

  • 为四个结果定义独立权重:w_tp(TP的损失权重)、w_fn(FN的损失权重)、w_tn(TN的损失权重)、w_fp(FP的损失权重)
  • 构建连续可导的权重映射,避免阈值带来的梯度不稳定性(因为模型输出是连续的概率值,不是离散的0/1)
  • 将权重与标准交叉熵损失相乘,得到最终的加权损失

实现代码

这里提供一个TensorFlow/Keras兼容的自定义损失函数,支持直接输入logits(数值更稳定):

import tensorflow as tf

def weighted_binary_crossentropy(w_tp, w_fn, w_tn, w_fp):
    def loss(y_true, logits):
        # 计算预测概率(仅用于权重映射,不直接参与损失计算)
        y_pred = tf.sigmoid(logits)
        
        # 为正样本构建权重:y_pred接近1(TP)时用w_tp,接近0(FN)时用w_fn
        pos_weights = w_fn + (w_tp - w_fn) * y_pred
        # 为负样本构建权重:y_pred接近0(TN)时用w_tn,接近1(FP)时用w_fp
        neg_weights = w_tn + (w_fp - w_tn) * (1 - y_pred)
        
        # 合并权重:正样本用pos_weights,负样本用neg_weights
        sample_weights = y_true * pos_weights + (1 - y_true) * neg_weights
        
        # 用logits直接计算交叉熵(数值更稳定)
        base_bce = tf.keras.losses.binary_crossentropy(y_true, logits, from_logits=True)
        # 应用权重并返回平均损失
        return tf.reduce_mean(sample_weights * base_bce)
    return loss

使用示例

假设你的业务场景中,假阴性(FN)的代价是普通情况的5倍,假阳性(FP)的代价是3倍,而真阳性和真阴性的权重保持为1,那么可以这样编译模型:

model.compile(
    optimizer='adam',
    loss=weighted_binary_crossentropy(w_tp=1, w_fn=5, w_tn=1, w_fp=3)
)

与原生pos_weight的关系

如果你设置w_tp=pos_weight、w_fn=pos_weight、w_tn=1、w_fp=1,这个自定义损失就完全等价于原生的tf.keras.losses.BinaryCrossentropy(from_logits=True, pos_weight=pos_weight),完美兼容原有逻辑。

注意事项

  • 权重的取值需要根据业务需求调整:如果某类错误(比如FN)的代价极高,就对应调大相应的权重
  • 不要使用基于阈值的离散权重(比如判断y_pred>0.5再赋值),这会导致损失函数不连续,梯度不稳定,影响模型优化

内容的提问来源于stack exchange,提问作者Nickpick

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 08:17:09