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

TensorFlow 2.5下指定类别F1 Score无自定义函数实现问题

方案1:使用TensorFlow Addons F1Score 单独统计指定类别(无需自定义函数)

你可以直接和之前的Precision/Recall用法一致,为每个目标类别单独实例化F1Score指标,指定class_id参数即可,和原有指标的使用逻辑完全对齐:

import tensorflow as tf
import tensorflow_addons as tfa

metrics = [
    # 原有已在使用的召回、精确率指标
    tf.keras.metrics.Recall(class_id=1, name='Bkwd_R'),
    tf.keras.metrics.Recall(class_id=2, name='Fwd_R'),
    tf.keras.metrics.Precision(class_id=1, name='Bkwd_P'),
    tf.keras.metrics.Precision(class_id=2, name='Fwd_P'),
    # 新增类别1、2的单独F1指标
    tfa.metrics.F1Score(num_classes=3, class_id=1, name='Bkwd_F1'),
    tfa.metrics.F1Score(num_classes=3, class_id=2, name='Fwd_F1')
]

注意:如果你的模型输出是未经过softmax的logits,需要给F1Score参数加上from_logits=True,否则预测结果判定错误会导致F1值为0。

这个方式会在训练、验证、评估阶段单独输出每个类别的F1值,自动忽略类别0的统计,也不会出现多类别结果被默认全局平均的问题。


方案2:统计类别1和2的平均F1

如果你需要这两个类别的综合平均F1(默认macro平均,排除类别0),可以用以下兼容TensorFlow训练流程的自定义指标实现:

import tensorflow as tf
from tensorflow.keras import metrics

class TargetClassesF1(metrics.Metric):
    def __init__(self, target_class_ids=[1,2], num_classes=3, average='macro', name='target_f1', **kwargs):
        super().__init__(name=name, **kwargs)
        self.target_class_ids = target_class_ids
        self.num_classes = num_classes
        self.average = average
        # 初始化计数变量
        self.tp = self.add_weight(name='tp', shape=(num_classes,), initializer='zeros')
        self.fp = self.add_weight(name='fp', shape=(num_classes,), initializer='zeros')
        self.fn = self.add_weight(name='fn', shape=(num_classes,), initializer='zeros')

    def update_state(self, y_true, y_pred, sample_weight=None):
        y_true = tf.argmax(y_true, axis=-1) if len(y_true.shape) > 1 and y_true.shape[-1] == self.num_classes else y_true
        y_pred = tf.argmax(y_pred, axis=-1)
        for cls in self.target_class_ids:
            true_pos = tf.reduce_sum(tf.cast(tf.logical_and(y_true == cls, y_pred == cls), self.dtype))
            false_pos = tf.reduce_sum(tf.cast(tf.logical_and(y_true != cls, y_pred == cls), self.dtype))
            false_neg = tf.reduce_sum(tf.cast(tf.logical_and(y_true == cls, y_pred != cls), self.dtype))
            self.tp[cls].assign_add(true_pos)
            self.fp[cls].assign_add(false_pos)
            self.fn[cls].assign_add(false_neg)

    def result(self):
        f1_scores = []
        eps = tf.keras.backend.epsilon()
        for cls in self.target_class_ids:
            precision = self.tp[cls] / (self.tp[cls] + self.fp[cls] + eps)
            recall = self.tp[cls] / (self.tp[cls] + self.fn[cls] + eps)
            f1 = 2 * (precision * recall) / (precision + recall + eps)
            f1_scores.append(f1)
        if self.average == 'macro':
            return tf.reduce_mean(f1_scores)
        return f1_scores

    def reset_state(self):
        self.tp.assign(tf.zeros_like(self.tp))
        self.fp.assign(tf.zeros_like(self.fp))
        self.fn.assign(tf.zeros_like(self.fn))

调用方式直接加入metrics列表即可,适配model.fit、model.evaluate全流程:

metrics = [
    # 原有指标
    tf.keras.metrics.Recall(class_id=1, name='Bkwd_R'),
    tf.keras.metrics.Recall(class_id=2, name='Fwd_R'),
    tf.keras.metrics.Precision(class_id=1, name='Bkwd_P'),
    tf.keras.metrics.Precision(class_id=2, name='Fwd_P'),
    # 新增目标类别平均F1
    TargetClassesF1(target_class_ids=[1,2], num_classes=3, average='macro', name='target_f1')
]

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.10 05:21:01