You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Keras自定义损失函数输出负值,原因不明求助

分析Keras自定义损失出现负值的原因及排查方案

这种情况确实有点反直觉——毕竟从公式逻辑上看,所有项都是非负的,均值怎么会变成负数呢?我帮你梳理几个可能的原因,以及对应的排查步骤:

一、先确认:理论上损失应该是非负的

先拆解你的损失函数逻辑:

  • y_true归一化到0-1区间,加上K.epsilon()(Keras默认是1e-7,极小正数),结果必然是正数
  • K.square(y_pred - y_true)是平方项,结果非负
  • 正数×非负=非负,再取均值,结果肯定≥0

所以出现负值一定是某个环节出现了数值异常或者数据问题,下面逐一分析:

二、可能的原因及排查步骤

1. 低精度数据类型导致的数值溢出/下溢

如果你的模型开启了混合精度训练(比如用float16),或者数据被强制转换为低精度 dtype,就可能出现数值精度丢失的问题:

  • 极小的正数在float16中可能被截断为负数(因为float16的精度范围有限)
  • 计算过程中中间值的溢出也可能导致异常符号

排查方法:

  • 检查模型是否使用了tf.keras.mixed_precision.set_global_policy('mixed_float16')这类设置
  • 尝试将模型和数据都切换为float32(默认)或float64,重新训练看是否还会出现负值

2. y_true存在未被发现的异常负值

你说y已归一化到0-1,但可能预处理环节出现了疏漏:

  • 比如归一化时的计算错误(比如除以负数、或者数据本身存在极端值导致归一化后超出范围)
  • 或者数据集里混入了异常样本,导致y_true出现微小负值

排查方法:

  • 在数据加载后,用Numpy打印y_true的最小值:print(np.min(y_true_np)),确认是否严格≥0
  • 在损失函数中添加打印语句,实时查看训练时y_true的范围:
    def custom_loss(y_true, y_pred):
        tf.print("y_true min:", K.min(y_true), "y_true max:", K.max(y_true))
        # 原损失计算
        term1 = y_true + K.epsilon()
        term2 = K.square(y_pred - y_true)
        loss = K.mean(term1 * term2, axis=-1)
        return loss
    

3. TensorFlow计算中的数值异常(罕见但可能)

虽然前向计算逻辑没问题,但TensorFlow的延迟执行机制或者某些底层优化,可能在特定情况下出现数值异常:

  • 比如极端小的数值在自动微分过程中被错误处理
  • 或者张量的求值时机问题(比如你看到的是未完全计算的张量符号,而非实际值)

排查方法:

  • 用相同的测试数据,对比Keras和Numpy的计算结果,看是否一致:
    import numpy as np
    import tensorflow as tf
    from tensorflow.keras import backend as K
    
    # 生成和训练数据同分布的测试样本
    y_true_np = np.random.uniform(0, 1, size=(32, 10)).astype(np.float32)
    y_pred_np = np.random.uniform(0, 1, size=(32, 10)).astype(np.float32)
    
    # Keras计算
    y_true_tf = tf.convert_to_tensor(y_true_np)
    y_pred_tf = tf.convert_to_tensor(y_pred_np)
    loss_tf = K.mean((y_true_tf + K.epsilon()) * K.square(y_pred_tf - y_true_tf), axis=-1)
    print("Keras损失结果:", loss_tf.numpy())
    
    # Numpy计算
    loss_np = np.mean((y_true_np + np.finfo(np.float32).eps) * np.square(y_pred_np - y_true_np), axis=-1)
    print("Numpy损失结果:", loss_np)
    
    # 检查差异
    print("最大差值:", np.max(np.abs(loss_tf.numpy() - loss_np)))
    
    如果两者结果一致,说明问题出在训练数据或模型训练流程中;如果不一致,可能是TensorFlow版本或后端设置的问题,可以尝试更新Keras/TensorFlow版本。

三、总结建议

先从检查y_true的实际范围和数据类型入手,这两个是最常见的原因。如果这两步没问题,再用测试数据对比Keras和Numpy的计算结果,定位问题所在。

内容的提问来源于stack exchange,提问作者qry

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 07:33:30