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

为何输入缩放后tf.keras.CategoricalCrossentropy与softmax_cross_entropy_with_logits结果差异显著?

为什么CategoricalCrossentropy输入经softmax后与softmax_cross_entropy_with_logits结果差异巨大?

我原本以为,当CategoricalCrossentropy(CCE)的输入经过softmax处理后,它和tf.nn.softmax_cross_entropy_with_logits的计算结果应该完全一致。但实际测试发现,当输入X的数值较小时,两者结果接近;但把X数值放大10倍后,结果出现了巨大差异。

测试代码如下:

import numpy as np
import tensorflow as tf

# 测试用例1:X数值较小
X = np.array([[3.0, 1.0, 1.0], [-1.0, 2.0, 5.0]])
Y = np.array([[1, 0.0, 0.0], [0.0, 1.0, 0.0]])
cce = tf.keras.losses.CategoricalCrossentropy(from_logits=False, reduction=tf.keras.losses.Reduction.NONE)
cce_res = cce(y_true = Y, y_pred=tf.math.softmax(X))
sce_res = tf.nn.softmax_cross_entropy_with_logits(logits=X, labels=Y)
cost1 = tf.reduce_mean(cce_res)
cost2 = tf.reduce_mean(sce_res)
print(cost1)
print(cost2)
# 输出:
# tf.Tensor(1.645245261490345, shape=(), dtype=float64)
# tf.Tensor(1.6452452648724416, shape=(), dtype=float64)


# 测试用例2:X数值放大10倍
X = np.array([[3.0, 1.0, 1.0], [-1.0, 2.0, 5.0]]) * 10
Y = np.array([[1, 0.0, 0.0], [0.0, 1.0, 0.0]])
cce = tf.keras.losses.CategoricalCrossentropy(from_logits=False, reduction=tf.keras.losses.Reduction.NONE)
cce_res = cce(y_true = Y, y_pred=tf.math.softmax(X))
sce_res = tf.nn.softmax_cross_entropy_with_logits(logits=X, labels=Y)
cost1 = tf.reduce_mean(cce_res)
cost2 = tf.reduce_mean(sce_res)
print(cost1)
print(cost2)
# 输出:
# tf.Tensor(8.059047748974614, shape=(), dtype=float64)
# tf.Tensor(15.0000000020612, shape=(), dtype=float64)

核心原因分析

差异来源于两个关键点:

  • 数值稳定的计算方式:tf.nn.softmax_cross_entropy_with_logits内部通过log-sum-exp等数学技巧直接对logits计算,跳过显式softmax步骤,避免了logits数值过大时,softmax输出趋近于0或1带来的精度损失。比如第二个测试用例中,第二个样本的logits是[-10,20,50],该函数能精准计算出交叉熵为30,平均后得到15。
  • 输入裁剪机制:tf.keras.losses.CategoricalCrossentropy默认带有epsilon=1e-7参数,会将输入的y_pred裁剪到[epsilon, 1-epsilon]范围,防止计算log(y_pred)时出现无意义的log(0)。当logits数值极大时,softmax输出的极小值会被替换为1e-7,此时log(1e-7)≈-16.118,取反后得到的交叉熵约为16.118,和第一个样本的近似0值平均后得到8.059,这就是两者结果差异的直接原因。

解决方式

如果想让两者结果一致,有两种可行方法:

  1. 使用CategoricalCrossentropy时设置from_logits=True,此时它内部会调用和softmax_cross_entropy_with_logits一致的数值稳定计算逻辑,无需手动做softmax。
  2. 手动设置epsilon=0(不推荐,可能导致数值不稳定),同时确保计算环境的浮点数精度足够,但这种方式依然存在logits过大时的数值溢出风险。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 11:43:16