自定义Categorical Focal Loss训练中损失近乎恒定但精度提升,是否需担忧?
问题分析与解决建议
首先看你的自定义Focal Loss实现,存在几个可能导致损失恒定的问题,同时精度提升说明模型仍在学习,但需要排查隐患:
1. 损失函数的计算逻辑问题
你的代码里有两个关键问题:
- Focal Loss未正确聚合:当前
FL是和y_true同形状的张量(每个类别对应一个损失值),没有对样本或类别维度做求和/平均,直接和全局的L1/L2正则项相加,导致损失维度不符合Keras要求,框架隐式聚合的逻辑会掩盖Focal Loss本身的变化。 - 正则项作用对象错误:你现在是对模型输出
y_pred加L1/L2正则,这不是常规的权重正则(约束模型参数),而是约束输出数值范围,可能导致损失被正则项主导,掩盖了Focal Loss的波动。
2. 损失恒定但精度提升的原因
这种情况不用过度恐慌,精度提升说明模型确实在优化分类能力,可能的原因包括:
- Focal Loss的
gamma=2设置,让模型对易分类样本的损失权重极低,训练后期Focal Loss的下降空间很小,但模型仍在专注优化难分类样本,所以精度持续提升。 - 正则项权重(
l1=0.01、l2=0.01)过高,导致损失主要由正则项贡献,Focal Loss的变化被掩盖,看起来损失近乎恒定。
3. 修正建议
修正Focal Loss的实现
调整计算逻辑,确保正确聚合样本损失:
class CategoricalFocalLoss(tf.keras.losses.Loss): def __init__(self, alpha=0.25, gamma=2, **kwargs): super(CategoricalFocalLoss, self).__init__(**kwargs) self.alpha = alpha self.gamma = gamma def call(self, y_true, y_pred): # 防止log(0)出现数值不稳定 y_pred = tf.clip_by_value(y_pred, 1e-7, 1 - 1e-7) # 计算每个样本对应真实类别的预测概率 p_t = tf.reduce_sum(y_true * y_pred, axis=-1) # 计算Focal Loss并对batch样本取平均 fl_loss = -self.alpha * tf.pow(1 - p_t, self.gamma) * tf.math.log(p_t) fl_loss = tf.reduce_mean(fl_loss) return fl_loss
正确添加权重正则
如果需要对模型参数做L1/L2正则,直接在层中设置kernel_regularizer,而非在损失函数中处理输出:
# 示例:在Dense层添加权重正则 tf.keras.layers.Dense( num_classes, activation='softmax', kernel_regularizer=tf.keras.regularizers.l1_l2(l1=0.001, l2=0.001) )
调整超参数
- 降低正则项权重(比如从0.01改为0.001或更小),观察损失是否开始出现正常波动。
- 尝试调整
gamma值(比如1.5或2.5),看损失和精度的变化是否更匹配。
总结
当前精度提升说明模型在有效学习,但损失恒定是由损失函数实现或超参数设置导致的,建议按照上述方案修正,避免后续训练出现收敛停滞或数值异常。
内容的提问来源于stack exchange,提问作者Mojtaba Abdi Khassevan
相关产品推荐
相关产品推荐

