Softmax交叉熵损失解析梯度与数值梯度不匹配问题
Softmax交叉熵损失梯度解析解与数值解不匹配问题排查
你实现的Softmax交叉熵损失梯度中,解析解与数值解差异显著,代码及运行结果如下:
原代码
import numpy as np def softmax(z): expp = np.exp(z) return np.divide(expp, np.sum(expp)) def cost(z, y): s = softmax(z) return -np.sum(y * np.log(s)) / len(y) def costprime(z, y): prime = [] for i in range(len(z)): values = z.copy() values[i] += 1.0e-10 prime.append((cost(values, y) - cost(z, y)) / 1.0e-10) return prime z = np.array([1.1, 2.2, 0.3, -1.7]) y_expected = np.array([0, 0, 1, 0]) s = softmax(z) cost_gradient = s - y_expected numerical_derivative = costprime(z, y_expected) print(cost_gradient) print(numerical_derivative)
运行结果
[0.22151804 0.66547696 -0.90046553 0.01347053] [0.05538014491435206, 0.16636914068612896, -0.2251154818111445, 0.0033673064336881]
问题原因
核心差异来自损失函数的平均操作:
- 你的
cost函数对交叉熵损失做了平均(除以len(y),此处len(y)=4),计算的是单样本平均损失。 - 解析梯度公式
s - y_expected是针对未做平均的总损失(所有样本损失之和)推导的结果,没有考虑平均操作带来的缩放因子。
观察数值解和解析解的比值:0.22151804 / 0.05538014 ≈4,正好等于len(y),验证了这一点。
解决方法
将解析梯度也除以len(y),匹配cost函数的平均逻辑:
修改解析梯度的计算代码:
cost_gradient = (s - y_expected) / len(y)
修改后重新运行,输出结果会与数值梯度高度匹配(微小差异是数值梯度的有限差分近似误差,属于正常现象):
[0.05537951 0.16636924 -0.22511638 0.00336763] [0.05538014491435206, 0.16636914068612896, -0.2251154818111445, 0.0033673064336881]
内容的提问来源于stack exchange,提问作者Jawad Damir
相关产品推荐
相关产品推荐

