逻辑回归初始theta取值异常导致sigmoid输出全1/全0问题求解
问题成因及解决方案
根本原因
- 特征未做尺度归一化:你的输入特征包含总收入、贷款金额这类数值范围极大的特征(通常为几万到上百万量级),和性别、是否毕业这类0-1二值特征,不同特征的数值尺度差可达1e5甚至更高。当你初始化的theta值较大时,大尺度特征和对应theta的乘积就会达到几万甚至更高的数值,输入
calc_sigmoid的z值远大于5,sigmoid输出自然会饱和到0.9999;如果theta初始化极小,点积得到的z值会远小于-5,sigmoid输出就会饱和到0.0001。 - sigmoid函数饱和导致梯度消失:sigmoid函数在输入z的绝对值大于5时,导数
sigmoid(z)*(1-sigmoid(z))会小于0.01,几乎趋近于0。一旦初始输出进入饱和区,梯度下降的更新步长会极小,参数theta几乎不会被更新,模型就会一直输出全0或者全1的结果,无法正常收敛。 - 初始化和超参数设置不合理:你手动设置的theta初始值要么是1e-9级别的极小值,要么是几十的极大值,完全不符合逻辑回归要求的接近0的小值初始化逻辑;同时学习率0.2在特征未归一化的场景下过大,很容易导致参数更新震荡,进一步加剧输出饱和问题。
修复方案
- 先对输入特征做归一化处理:对数值型特征(总收入、贷款金额、贷款期限、家属人数)做Z-score标准化:
(特征值 - 特征均值)/特征标准差,把所有特征的数值尺度统一到相近范围,避免大数值特征主导点积结果。 - 修正theta初始化:直接用全0初始化,或者从均值为0、标准差为0.01的正态分布采样小数值初始化,不要手动设置量级极端的初始值。
- 调整学习率:特征归一化后尝试更小的学习率,比如0.01、0.001,避免步长过大导致参数更新震荡。
- 可选优化:给sigmoid函数增加数值稳定逻辑,避免z为大负数时
np.exp(-z)溢出:
def calc_sigmoid(z): # 数值稳定版sigmoid实现 p = np.where(z >= 0, 1 / (1 + np.exp(-z)), np.exp(z) / (1 + np.exp(z))) p = np.minimum(p, 0.9999) p = np.maximum(p, 0.0001) return p
内容的提问来源于stack exchange,提问作者Sarvagya Agrawal
相关产品推荐
相关产品推荐

