从零实现二元交叉熵逻辑回归训练损失出现波动的原因是什么
逻辑回归损失波动问题解答
代码正确性判断
你的逻辑回归实现没有原则性错误,二元交叉熵损失计算、梯度下降更新权重与偏置的逻辑完全符合公式要求,所以参数可以正常收敛。
损失大幅波动的核心原因
- 损失函数特性差异:线性回归使用的均方误差损失是全域平滑的凸函数,任意位置梯度变化平缓,梯度下降每一步都能稳定朝向全局最小值移动,因此损失呈平稳下降趋势。而二元交叉熵损失包含对数运算,当sigmoid输出的预测值接近0或1时,对数项的数值变化会非常剧烈,导致梯度量级突变,参数更新步长不稳定,容易出现震荡。
- 学习率与特征缩放不匹配:你当前使用的0.01学习率如果没有搭配输入特征归一化操作,当输入特征x的数值范围较大时,计算得到的梯度量级也会被同步放大,实际参数更新步长会超过最优步长,每次更新直接跨过损失最低点,下一轮迭代又往回调整,就会表现为损失大幅波动。
- 数值稳定性不足:当前损失函数没有做数值截断处理,当sigmoid输出极接近0或1时,
np.log(yhat)或者np.log(1-yhat)会出现接近负无穷的极端值,也会导致单轮损失计算结果异常波动。
优化方案
- 对输入特征x做标准化或归一化处理,将特征数值缩放到统一区间,降低梯度量级波动
- 适当下调学习率,比如调整为0.001、0.0005,避免参数更新步长过大
- 在损失函数中加入数值裁剪,优化后代码如下:
def binary_crossentropy(y, yhat): no_of_samples = len(y) # 裁剪避免对数运算溢出 yhat = np.clip(yhat, 1e-15, 1 - 1e-15) numerator_1 = y*np.log(yhat) numerator_2 = (1-y) * np.log(1-yhat) loss = -(np.sum(numerator_1 + numerator_2) / no_of_samples) return loss
- 可改用带动量的梯度下降优化器,平滑参数更新过程,抵消震荡影响
内容的提问来源于stack exchange,提问作者Muhammad Ardi Putra
相关产品推荐
相关产品推荐

