乐闻世界logo
搜索文章和话题

TensorFlow 中的评估指标有哪些,如何自定义评估指标

2月18日 17:58

评估指标(Metrics)用于评估模型性能,是深度学习模型开发和调优的重要工具。

常用评估指标

1. 分类指标

准确率(Accuracy)

python
from tensorflow.keras.metrics import Accuracy # 使用准确率指标 accuracy = Accuracy() # 计算准确率 y_true = tf.constant([0, 1, 1, 0, 1]) y_pred = tf.constant([0, 1, 0, 0, 1]) accuracy.update_state(y_true, y_pred) result = accuracy.result() print(result) # 0.8 # 在模型编译中使用 model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])

特点

  • 直观易懂
  • 适合平衡数据集
  • 对类别不平衡敏感

适用场景

  • 平衡的分类任务
  • 需要简单评估的场景

精确率(Precision)

python
from tensorflow.keras.metrics import Precision # 使用精确率指标 precision = Precision() # 计算精确率 y_true = tf.constant([0, 1, 1, 0, 1]) y_pred = tf.constant([0, 1, 0, 0, 1]) precision.update_state(y_true, y_pred) result = precision.result() print(result) # 1.0 # 在模型编译中使用 model.compile(optimizer='adam', loss='binary_crossentropy', metrics=[Precision()])

特点

  • 衡量预测为正类的准确性
  • 适合关注假阳性的场景
  • 对类别不平衡不敏感

适用场景

  • 垃圾邮件检测
  • 医疗诊断
  • 需要减少假阳性的场景

召回率(Recall)

python
from tensorflow.keras.metrics import Recall # 使用召回率指标 recall = Recall() # 计算召回率 y_true = tf.constant([0, 1, 1, 0, 1]) y_pred = tf.constant([0, 1, 0, 0, 1]) recall.update_state(y_true, y_pred) result = recall.result() print(result) # 0.666... # 在模型编译中使用 model.compile(optimizer='adam', loss='binary_crossentropy', metrics=[Recall()])

特点

  • 衡量正类样本的识别能力
  • 适合关注假阴性的场景
  • 对类别不平衡不敏感

适用场景

  • 疾病筛查
  • 异常检测
  • 需要减少假阴性的场景

F1 分数(F1 Score)

python
from tensorflow.keras.metrics import F1Score # 使用 F1 分数指标 f1 = F1Score(num_classes=2, threshold=0.5) # 计算 F1 分数 y_true = tf.constant([[0, 1], [1, 0], [1, 0], [0, 1], [1, 0]]) y_pred = tf.constant([[0.1, 0.9], [0.8, 0.2], [0.3, 0.7], [0.2, 0.8], [0.9, 0.1]]) f1.update_state(y_true, y_pred) result = f1.result() print(result) # [0.666..., 0.8] # 在模型编译中使用 model.compile(optimizer='adam', loss='binary_crossentropy', metrics=[F1Score(num_classes=2)])

特点

  • 精确率和召回率的调和平均
  • 平衡精确率和召回率
  • 适合不平衡数据集

适用场景

  • 不平衡分类任务
  • 需要平衡精确率和召回率的场景

AUC-ROC

python
from tensorflow.keras.metrics import AUC # 使用 AUC 指标 auc = AUC() # 计算 AUC y_true = tf.constant([0, 1, 1, 0, 1]) y_pred = tf.constant([0.1, 0.9, 0.8, 0.2, 0.7]) auc.update_state(y_true, y_pred) result = auc.result() print(result) # 0.916... # 在模型编译中使用 model.compile(optimizer='adam', loss='binary_crossentropy', metrics=[AUC()])

特点

  • 衡量分类器的整体性能
  • 不受阈值影响
  • 适合二分类问题

适用场景

  • 二分类任务
  • 需要评估整体性能的场景

2. 回归指标

均方误差(MSE)

python
from tensorflow.keras.metrics import MeanSquaredError # 使用 MSE 指标 mse = MeanSquaredError() # 计算 MSE y_true = tf.constant([1.0, 2.0, 3.0, 4.0]) y_pred = tf.constant([1.1, 2.2, 2.9, 4.1]) mse.update_state(y_true, y_pred) result = mse.result() print(result) # 0.0175 # 在模型编译中使用 model.compile(optimizer='adam', loss='mse', metrics=[MeanSquaredError()])

特点

  • 衡量预测值与真实值的差异
  • 对异常值敏感
  • 适合连续值预测

适用场景

  • 回归任务
  • 需要精确预测的场景

平均绝对误差(MAE)

python
from tensorflow.keras.metrics import MeanAbsoluteError # 使用 MAE 指标 mae = MeanAbsoluteError() # 计算 MAE y_true = tf.constant([1.0, 2.0, 3.0, 4.0]) y_pred = tf.constant([1.1, 2.2, 2.9, 4.1]) mae.update_state(y_true, y_pred) result = mae.result() print(result) # 0.125 # 在模型编译中使用 model.compile(optimizer='adam', loss='mae', metrics=[MeanAbsoluteError()])

特点

  • 衡量预测值与真实值的绝对差异
  • 对异常值不敏感
  • 适合有异常值的回归任务

适用场景

  • 回归任务
  • 有异常值的数据

平均绝对百分比误差(MAPE)

python
# 自定义 MAPE 指标 def mean_absolute_percentage_error(y_true, y_pred): y_true = tf.cast(y_true, tf.float32) y_pred = tf.cast(y_pred, tf.float32) diff = tf.abs((y_true - y_pred) / y_true) return 100.0 * tf.reduce_mean(diff) # 使用 MAPE y_true = tf.constant([100.0, 200.0, 300.0]) y_pred = tf.constant([110.0, 190.0, 310.0]) mape = mean_absolute_percentage_error(y_true, y_pred) print(mape) # 5.555...

特点

  • 衡量预测值的百分比误差
  • 直观易懂
  • 对接近零的值敏感

适用场景

  • 需要百分比误差的场景
  • 时间序列预测

R² 分数(R-squared)

python
# 自定义 R² 指标 def r_squared(y_true, y_pred): y_true = tf.cast(y_true, tf.float32) y_pred = tf.cast(y_pred, tf.float32) ss_res = tf.reduce_sum(tf.square(y_true - y_pred)) ss_tot = tf.reduce_sum(tf.square(y_true - tf.reduce_mean(y_true))) return 1 - ss_res / (ss_tot + tf.keras.backend.epsilon()) # 使用 R² y_true = tf.constant([1.0, 2.0, 3.0, 4.0]) y_pred = tf.constant([1.1, 2.2, 2.9, 4.1]) r2 = r_squared(y_true, y_pred) print(r2) # 0.982...

特点

  • 衡量模型解释的方差比例
  • 范围在 (-∞, 1] 之间
  • 1 表示完美拟合

适用场景

  • 回归任务
  • 需要评估模型解释能力的场景

3. 其他指标

Top-K 准确率

python
from tensorflow.keras.metrics import TopKCategoricalAccuracy # 使用 Top-5 准确率 top5_acc = TopKCategoricalAccuracy(k=5) # 计算 Top-5 准确率 y_true = tf.constant([[0, 0, 1, 0, 0, 0, 0, 0, 0, 0]]) y_pred = tf.constant([[0.1, 0.2, 0.3, 0.1, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05]]) top5_acc.update_state(y_true, y_pred) result = top5_acc.result() print(result) # 1.0 # 在模型编译中使用 model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=[TopKCategoricalAccuracy(k=5)])

特点

  • 衡量预测是否在前 K 个最高概率中
  • 适合多分类任务
  • 常用于图像分类

适用场景

  • 大规模多分类任务
  • 图像分类
  • 推荐系统

混淆矩阵

python
from sklearn.metrics import confusion_matrix import numpy as np # 计算混淆矩阵 y_true = np.array([0, 1, 1, 0, 1, 0, 1, 0]) y_pred = np.array([0, 1, 0, 0, 1, 1, 1, 0]) cm = confusion_matrix(y_true, y_pred) print(cm) # [[2 1] # [1 4]] # 可视化混淆矩阵 import matplotlib.pyplot as plt import seaborn as sns plt.figure(figsize=(8, 6)) sns.heatmap(cm, annot=True, fmt='d', cmap='Blues') plt.xlabel('Predicted') plt.ylabel('True') plt.title('Confusion Matrix') plt.show()

特点

  • 详细展示分类结果
  • 适合多分类任务
  • 可视化分类性能

适用场景

  • 多分类任务
  • 需要详细分析分类结果的场景

自定义评估指标

1. 基本自定义指标

python
# 定义自定义指标 def custom_metric(y_true, y_pred): # 计算自定义指标 return tf.reduce_mean(tf.abs(y_true - y_pred)) # 使用自定义指标 model.compile(optimizer='adam', loss='mse', metrics=[custom_metric])

2. 类形式的自定义指标

python
# 定义类形式的自定义指标 class CustomMetric(tf.keras.metrics.Metric): def __init__(self, name='custom_metric', **kwargs): super(CustomMetric, self).__init__(name=name, **kwargs) self.count = self.add_weight(name='count', initializer='zeros') self.total = self.add_weight(name='total', initializer='zeros') def update_state(self, y_true, y_pred, sample_weight=None): # 更新状态 diff = tf.abs(y_true - y_pred) if sample_weight is not None: diff = diff * sample_weight self.count.assign_add(tf.reduce_sum(tf.cast(diff > 0.5, tf.float32))) self.total.assign_add(tf.cast(tf.size(diff), tf.float32)) def result(self): # 计算结果 return self.count / self.total def reset_states(self): # 重置状态 self.count.assign(0.0) self.total.assign(0.0) # 使用自定义指标 custom_metric = CustomMetric() model.compile(optimizer='adam', loss='mse', metrics=[custom_metric])

3. 多标签分类指标

python
# 定义多标签准确率 def multilabel_accuracy(y_true, y_pred): # 将概率转换为二进制 y_pred_binary = tf.cast(y_pred > 0.5, tf.float32) # 计算每个样本的准确率 sample_accuracy = tf.reduce_all( tf.equal(y_true, y_pred_binary), axis=1 ) # 计算整体准确率 return tf.reduce_mean(tf.cast(sample_accuracy, tf.float32)) # 使用多标签准确率 model.compile(optimizer='adam', loss='binary_crossentropy', metrics=[multilabel_accuracy])

4. IoU(交并比)

python
# 定义 IoU 指标 class IoU(tf.keras.metrics.Metric): def __init__(self, num_classes, name='iou', **kwargs): super(IoU, self).__init__(name=name, **kwargs) self.num_classes = num_classes self.intersection = self.add_weight( name='intersection', shape=(num_classes,), initializer='zeros' ) self.union = self.add_weight( name='union', shape=(num_classes,), initializer='zeros' ) def update_state(self, y_true, y_pred, sample_weight=None): # 将预测转换为类别索引 y_pred = tf.argmax(y_pred, axis=-1) y_true = tf.argmax(y_true, axis=-1) # 计算每个类别的交并比 for i in range(self.num_classes): true_mask = tf.cast(y_true == i, tf.float32) pred_mask = tf.cast(y_pred == i, tf.float32) intersection = tf.reduce_sum(true_mask * pred_mask) union = tf.reduce_sum(true_mask + pred_mask) - intersection self.intersection[i].assign_add(intersection) self.union[i].assign_add(union) def result(self): # 计算 IoU return self.intersection / (self.union + tf.keras.backend.epsilon()) def reset_states(self): # 重置状态 self.intersection.assign(tf.zeros_like(self.intersection)) self.union.assign(tf.zeros_like(self.union)) # 使用 IoU 指标 iou = IoU(num_classes=10) model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=[iou])

5. Dice 系数

python
# 定义 Dice 系数指标 class DiceCoefficient(tf.keras.metrics.Metric): def __init__(self, name='dice_coefficient', **kwargs): super(DiceCoefficient, self).__init__(name=name, **kwargs) self.intersection = self.add_weight(name='intersection', initializer='zeros') self.total = self.add_weight(name='total', initializer='zeros') def update_state(self, y_true, y_pred, sample_weight=None): # 将预测转换为二进制 y_pred_binary = tf.cast(y_pred > 0.5, tf.float32) # 计算交集和并集 intersection = tf.reduce_sum(y_true * y_pred_binary) total = tf.reduce_sum(y_true) + tf.reduce_sum(y_pred_binary) self.intersection.assign_add(intersection) self.total.assign_add(total) def result(self): # 计算 Dice 系数 return 2.0 * self.intersection / (self.total + tf.keras.backend.epsilon()) def reset_states(self): # 重置状态 self.intersection.assign(0.0) self.total.assign(0.0) # 使用 Dice 系数指标 dice = DiceCoefficient() model.compile(optimizer='adam', loss='binary_crossentropy', metrics=[dice])

评估指标组合使用

1. 多指标评估

python
# 组合多个评估指标 model.compile( optimizer='adam', loss='categorical_crossentropy', metrics=[ 'accuracy', Precision(name='precision'), Recall(name='recall'), F1Score(num_classes=10, name='f1_score'), TopKCategoricalAccuracy(k=5, name='top5_accuracy') ] )

2. 条件指标

python
# 定义条件指标 class ConditionalAccuracy(tf.keras.metrics.Metric): def __init__(self, condition_fn, name='conditional_accuracy', **kwargs): super(ConditionalAccuracy, self).__init__(name=name, **kwargs) self.condition_fn = condition_fn self.correct = self.add_weight(name='correct', initializer='zeros') self.total = self.add_weight(name='total', initializer='zeros') def update_state(self, y_true, y_pred, sample_weight=None): # 应用条件函数 mask = self.condition_fn(y_true, y_pred) # 计算准确率 y_pred_class = tf.argmax(y_pred, axis=-1) y_true_class = tf.argmax(y_true, axis=-1) correct = tf.cast(tf.equal(y_pred_class, y_true_class), tf.float32) correct = correct * tf.cast(mask, tf.float32) self.correct.assign_add(tf.reduce_sum(correct)) self.total.assign_add(tf.reduce_sum(tf.cast(mask, tf.float32))) def result(self): return self.correct / (self.total + tf.keras.backend.epsilon()) def reset_states(self): self.correct.assign(0.0) self.total.assign(0.0) # 使用条件指标(例如只计算正类的准确率) positive_condition = lambda y_true, y_pred: tf.reduce_any(y_true > 0.5, axis=-1) positive_accuracy = ConditionalAccuracy(positive_condition, name='positive_accuracy') model.compile( optimizer='adam', loss='binary_crossentropy', metrics=['accuracy', positive_accuracy] )

评估指标最佳实践

1. 根据任务选择合适的指标

python
# 分类任务 model.compile( optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy', 'precision', 'recall', 'f1_score'] ) # 回归任务 model.compile( optimizer='adam', loss='mse', metrics=['mae', 'mse'] ) # 不平衡分类任务 model.compile( optimizer='adam', loss='binary_crossentropy', metrics=['precision', 'recall', 'auc'] )

2. 使用多个指标全面评估

python
# 组合多个指标 model.compile( optimizer='adam', loss='categorical_crossentropy', metrics=[ 'accuracy', Precision(name='precision'), Recall(name='recall'), AUC(name='auc'), TopKCategoricalAccuracy(k=5, name='top5_accuracy') ] )

3. 监控指标变化

python
# 自定义回调函数监控指标 class MetricsMonitor(tf.keras.callbacks.Callback): def on_epoch_end(self, epoch, logs=None): print(f"Epoch {epoch}:") print(f" Accuracy: {logs['accuracy']:.4f}") print(f" Precision: {logs['precision']:.4f}") print(f" Recall: {logs['recall']:.4f}") print(f" AUC: {logs['auc']:.4f}") # 使用监控回调 model.fit(x_train, y_train, validation_data=(x_val, y_val), callbacks=[MetricsMonitor()])

4. 可视化指标

python
import matplotlib.pyplot as plt # 绘制指标曲线 def plot_metrics(history): fig, axes = plt.subplots(2, 2, figsize=(15, 10)) # 准确率 axes[0, 0].plot(history.history['accuracy'], label='Training Accuracy') axes[0, 0].plot(history.history['val_accuracy'], label='Validation Accuracy') axes[0, 0].set_title('Accuracy') axes[0, 0].set_xlabel('Epoch') axes[0, 0].set_ylabel('Accuracy') axes[0, 0].legend() # 精确率 axes[0, 1].plot(history.history['precision'], label='Training Precision') axes[0, 1].plot(history.history['val_precision'], label='Validation Precision') axes[0, 1].set_title('Precision') axes[0, 1].set_xlabel('Epoch') axes[0, 1].set_ylabel('Precision') axes[0, 1].legend() # 召回率 axes[1, 0].plot(history.history['recall'], label='Training Recall') axes[1, 0].plot(history.history['val_recall'], label='Validation Recall') axes[1, 0].set_title('Recall') axes[1, 0].set_xlabel('Epoch') axes[1, 0].set_ylabel('Recall') axes[1, 0].legend() # AUC axes[1, 1].plot(history.history['auc'], label='Training AUC') axes[1, 1].plot(history.history['val_auc'], label='Validation AUC') axes[1, 1].set_title('AUC') axes[1, 1].set_xlabel('Epoch') axes[1, 1].set_ylabel('AUC') axes[1, 1].legend() plt.tight_layout() plt.show() # 使用 history = model.fit(x_train, y_train, validation_data=(x_val, y_val), epochs=50) plot_metrics(history)

总结

TensorFlow 提供了丰富的评估指标:

  • 分类指标:Accuracy、Precision、Recall、F1 Score、AUC-ROC
  • 回归指标:MSE、MAE、MAPE、R²
  • 其他指标:Top-K Accuracy、混淆矩阵、IoU、Dice
  • 自定义指标:可以创建自定义评估指标满足特定需求
  • 指标组合:可以组合多个指标全面评估模型性能

选择合适的评估指标需要考虑任务类型、数据特性和业务需求。通过多个指标的组合使用,可以更全面地评估模型性能。

标签:Tensorflow