TensorFlow Keras多分类任务中召回率与精确率指标获取方案咨询
多分类场景下监控每个类别的召回率与精确率
针对你的3分类任务,无需手动转换预测结果为类别标签,TensorFlow Keras的内置Recall和Precision指标支持直接适配多分类场景,只需为每个类别单独创建指标实例即可在训练epoch中实时监控。
方案一:使用内置指标的class_id参数
TensorFlow的Recall和Precision类提供了class_id参数,用于指定计算某一特定类别的指标值。结合你的sparse标签(整数形式),可以直接在模型编译时加入这些指标:
import tensorflow as tf from tensorflow.keras.layers import Dense from tensorflow.keras.metrics import Recall, Precision # 假设你的模型结构已定义,最后一层如下 output = Dense(3, activation='softmax')(attention_mul) # 为每个类别创建召回率和精确率指标,自定义名称方便日志识别 recall_class_0 = Recall(class_id=0, name='recall_class_0') recall_class_1 = Recall(class_id=1, name='recall_class_1') recall_class_2 = Recall(class_id=2, name='recall_class_2') precision_class_0 = Precision(class_id=0, name='precision_class_0') precision_class_1 = Precision(class_id=1, name='precision_class_1') precision_class_2 = Precision(class_id=2, name='precision_class_2') # 编译模型时加入所有需要监控的指标 model.compile( loss=tf.keras.losses.sparse_categorical_crossentropy, optimizer='Adam', metrics=[ 'accuracy', recall_class_0, recall_class_1, recall_class_2, precision_class_0, precision_class_1, precision_class_2 ] ) # 训练模型时,每个epoch会自动输出所有指标的结果 model.fit(x_train, y_train, epochs=10, validation_data=(x_val, y_val))
原理说明
- 内置指标会自动处理模型输出的概率向量:内部会对
y_pred执行argmax操作得到预测类别标签,无需手动转换。 - 由于使用
sparse_categorical_crossentropy,输入的y_true是整数形式,指标可以直接兼容,无需转换为one-hot编码。 - 每个epoch结束后,训练日志会显示每个类别的召回率、精确率以及整体准确率,方便实时监控。
方案二:自定义指标函数(灵活扩展)
如果需要更个性化的计算逻辑,可以为每个类别单独编写自定义指标函数:
import tensorflow as tf def recall_class_0(y_true, y_pred): # 将概率向量转换为预测类别 y_pred = tf.argmax(y_pred, axis=1) # 计算该类别的真阳性样本数 true_positives = tf.reduce_sum(tf.cast( tf.logical_and(tf.equal(y_true, 0), tf.equal(y_pred, 0)), tf.float32 )) # 计算该类别的实际阳性样本数 possible_positives = tf.reduce_sum(tf.cast(tf.equal(y_true, 0), tf.float32)) # 加入epsilon避免除以0 return true_positives / (possible_positives + tf.keras.backend.epsilon()) # 同理编写其他类别的召回率和精确率函数 def recall_class_1(y_true, y_pred): y_pred = tf.argmax(y_pred, axis=1) true_positives = tf.reduce_sum(tf.cast( tf.logical_and(tf.equal(y_true, 1), tf.equal(y_pred, 1)), tf.float32 )) possible_positives = tf.reduce_sum(tf.cast(tf.equal(y_true, 1), tf.float32)) return true_positives / (possible_positives + tf.keras.backend.epsilon()) def precision_class_0(y_true, y_pred): y_pred = tf.argmax(y_pred, axis=1) true_positives = tf.reduce_sum(tf.cast( tf.logical_and(tf.equal(y_true, 0), tf.equal(y_pred, 0)), tf.float32 )) # 计算该类别的预测阳性样本数 predicted_positives = tf.reduce_sum(tf.cast(tf.equal(y_pred, 0), tf.float32)) return true_positives / (predicted_positives + tf.keras.backend.epsilon()) # 编译模型时加入自定义指标 model.compile( loss=tf.keras.losses.sparse_categorical_crossentropy, optimizer='Adam', metrics=['accuracy', recall_class_0, recall_class_1, precision_class_0] )
注意事项
- 自定义指标函数需返回单个标量值,每个函数对应一个类别的指标,这样训练日志才能正常显示。
- 加入
tf.keras.backend.epsilon()是为了避免当分母为0时出现NaN的情况。
内容的提问来源于stack exchange,提问作者Ethan Huang
相关产品推荐
相关产品推荐

