在TensorFlow中训练ResNet/ResNeXt时如何计算宏、加权Precision和Recall?
问题解决:ResNet/ResNeXt训练中获取宏平均/加权平均Precision、Recall
一、原生tf.metrics.Precision/Recall得分相同的原因与解决方法
原因
tf.keras.metrics.Precision和Recall默认采用**微平均(micro)**计算:将所有类别的真阳性、假阳性、假阴性累加后计算整体指标。对于二分类任务+categorical_crossentropy(标签为one-hot编码)的场景,微平均的Precision和Recall结果会等于准确率,因此每一步输出的数值完全相同。
解决方法
直接使用TensorFlow Addons(tfa)中支持average参数的Precision和Recall指标,与你使用的F1Score保持框架一致:
import tensorflow_addons as tfa # 定义加权平均的Precision、Recall weighted_prec = tfa.metrics.Precision(num_classes=2, average='weighted') weighted_recall = tfa.metrics.Recall(num_classes=2, average='weighted') # 若需要宏平均,将average参数改为'macro' macro_prec = tfa.metrics.Precision(num_classes=2, average='macro') macro_recall = tfa.metrics.Recall(num_classes=2, average='macro') # 模型编译 f1 = tfa.metrics.F1Score(num_classes=2, average='weighted') model.compile( loss='categorical_crossentropy', optimizer="adam", metrics=[f1, weighted_prec, weighted_recall, macro_prec, macro_recall] )
二、使用torchmetrics报错的原因与解决办法
原因
torchmetrics是PyTorch专属的指标库,无法直接与TensorFlow/Keras的模型兼容。TensorFlow输出的预测结果格式(形状、张量类型)与PyTorch的要求不匹配,因此会抛出形状不匹配的错误。
解决办法
放弃跨框架混用,统一使用TensorFlow生态的工具:
- 优先采用上述tfa提供的指标实现
- 若需要自定义逻辑,可基于
tf.keras.metrics.Metric类实现自定义宏/加权平均指标,示例如下:
import tensorflow as tf class MacroPrecision(tf.keras.metrics.Metric): def __init__(self, num_classes=2, name='macro_precision', **kwargs): super().__init__(name=name, **kwargs) self.num_classes = num_classes self.precisions = self.add_weight(name='precisions', shape=(num_classes,), initializer='zeros') self.counts = self.add_weight(name='counts', shape=(num_classes,), initializer='zeros') def update_state(self, y_true, y_pred, sample_weight=None): y_true = tf.argmax(y_true, axis=1) y_pred = tf.argmax(y_pred, axis=1) for cls in range(self.num_classes): true_positive = tf.reduce_sum(tf.cast(tf.logical_and(y_true == cls, y_pred == cls), tf.float32)) predicted_positive = tf.reduce_sum(tf.cast(y_pred == cls, tf.float32)) precision = true_positive / (predicted_positive + tf.keras.backend.epsilon()) self.precisions[cls].assign_add(precision) self.counts[cls].assign_add(1.0) def result(self): return tf.reduce_mean(self.precisions / (self.counts + tf.keras.backend.epsilon())) # 同理可实现MacroRecall、WeightedPrecision等自定义指标
内容的提问来源于stack exchange,提问作者javeqx
相关产品推荐
相关产品推荐

