Keras中指标(含自定义)的计算方式及批量计算逻辑问询
嘿,这个问题问到点子上了——很多人刚开始用Keras写自定义指标时都会搞不清这个逻辑,我给你理得明明白白:
一、默认行为:小批量计算后取平均值
不管是你写的这种函数式自定义指标(比如max_error),还是Keras的大部分内置指标(像mae、accuracy),默认逻辑都是先在每个小批量(batch)上计算出指标值,然后对所有batch的结果取算术平均,最终输出这个平均值作为整个训练/验证集的指标结果。
举你的例子来说:假设你的训练集被分成了3个batch,每个batch计算出的max_error分别是2.5、3.0、2.0,那Keras最终输出的指标就是 (2.5 + 3.0 + 2.0) / 3 = 2.5,而不是整个数据集所有样本的真实最大误差。
二、如何实现「全数据集计算」的指标?
如果你想要的是整个数据集上的真实最大误差(而不是batch结果的平均),那就要用Keras的「状态式指标」——也就是继承tf.keras.metrics.Metric类来实现,它会帮你累积每个batch的中间结果,最后在epoch结束时计算全局指标。
比如针对你的需求,我们可以写这样一个自定义指标类:
import tensorflow as tf from tensorflow.keras import backend as K class MaxError(tf.keras.metrics.Metric): def __init__(self, name='max_error', **kwargs): super().__init__(name=name, **kwargs) # 初始化一个变量来保存全局最大误差 self.max_error = self.add_weight(name='max_err', initializer='zeros') def update_state(self, y_true, y_pred, sample_weight=None): # 计算当前batch的最大误差 batch_max_err = K.max(K.abs(y_true - y_pred)) # 更新全局最大误差:取当前保存的最大值和batch结果的较大者 self.max_error.assign(K.maximum(self.max_error, batch_max_err)) def result(self): # 返回最终的全局最大误差 return self.max_error def reset_state(self): # 每个epoch开始前重置状态,避免影响下一轮计算 self.max_error.assign(0.0)
用这个类代替函数式的max_error,Keras就会在每个batch计算当前batch的最大误差,然后不断更新全局的最大值,epoch结束时返回整个数据集的真实最大误差,而不是batch结果的平均。
三、内置指标的特殊情况
有些内置指标本身就是状态式的,比如AUC、Precision、Recall这类需要全局统计的指标,Keras会自动用累积的方式计算,而不是简单平均batch结果——这是因为这类指标的计算逻辑本身就不能通过平均batch结果得到正确值。
内容的提问来源于stack exchange,提问作者floflo29

