Keras/TensorFlow如何自定义TP-FP(真阳性减假阳性)指标
报错原因
tf.keras.metrics.TruePositives()、tf.keras.metrics.FalsePositives()是Keras内置的有状态指标类实例,本身不直接输出数值,不能直接对实例做算术运算。必须传入真实标签、预测值更新内部状态后,才能读取计算结果。
你遇到的f1_loss与tfa.metrics.F1Score数值不匹配问题,是因为现有f1_loss是逐batch计算F1后取平均,而内置F1指标是跨整个epoch累积所有样本的TP/FP/FN后统一计算,统计口径不同,数值自然不会相等。
自定义TP-FP差值指标实现方案
方案1:自定义Metric子类(推荐,适配模型筛选需求)
该写法完全遵循Keras指标的状态累积逻辑,跨batch统计全量样本的TP、FP值,计算结果准确,适合做最优模型筛选的判断依据:
import tensorflow as tf class TPMinusFP(tf.keras.metrics.Metric): def __init__(self, name='tp_minus_fp', **kwargs): super().__init__(name=name, **kwargs) # 定义跨batch累积的状态变量 self.total_tp = self.add_weight(name='total_tp', initializer='zeros') self.total_fp = self.add_weight(name='total_fp', initializer='zeros') def update_state(self, y_true, y_pred, sample_weight=None): # 每个batch流入时更新累积值,和内置TP/FP指标的阈值、类型逻辑对齐 y_true = tf.cast(y_true, tf.bool) y_pred = tf.cast(y_pred >= 0.5, tf.bool) # 多标签分类默认判定阈值0.5 # 计算当前batch的TP、FP batch_tp = tf.reduce_sum(tf.cast(tf.logical_and(y_true, y_pred), self.dtype)) batch_fp = tf.reduce_sum(tf.cast(tf.logical_and(tf.logical_not(y_true), y_pred), self.dtype)) # 累加到全局统计值 self.total_tp.assign_add(batch_tp) self.total_fp.assign_add(batch_fp) def result(self): # 输出最终计算结果:TP - FP return self.total_tp - self.total_fp def reset_state(self): # 每个epoch开始前重置统计状态 self.total_tp.assign(0.) self.total_fp.assign(0.)
调用时直接将类实例加入metrics列表即可:
metrics=[ TPMinusFP(), tfa.metrics.F1Score(num_classes=2), tf.keras.metrics.TruePositives(), tf.keras.metrics.FalsePositives() ]
方案2:无状态函数式写法(不推荐用于模型筛选)
如果不需要跨batch累积统计,仅需要逐batch计算差值,可以直接在函数内手动计算TP、FP,不需要实例化内置指标类:
def tp_minus_fp(y_true, y_pred): y_true = tf.cast(y_true, tf.float32) y_pred = tf.cast(y_pred >= 0.5, tf.float32) tp = tf.reduce_sum(y_true * y_pred) fp = tf.reduce_sum((1 - y_true) * y_pred) return tp - fp
注意:该写法在验证阶段会返回所有batch计算结果的平均值,和全量样本统计的真实TP-FP值存在偏差,仅可做快速调试用,不能作为模型筛选的依据。
补充说明
训练阶段的loss本身是逐batch计算用于反向传播的,和全量样本累积计算的评估指标不需要数值完全相等,只要优化方向一致即可,无需强行对齐数值。
内容的提问来源于stack exchange,提问作者dergham
相关产品推荐
相关产品推荐

