scikit-learn无惩罚逻辑回归输出截距为真实值一半如何解决
问题原因
你在传入特征给scikit-learn的逻辑回归模型前,已经通过sm.add_constant()手动给特征矩阵加了一列全1的常数列,而LogisticRegression默认通过fit_intercept=True参数自动拟合独立截距项,相当于模型同时接收到两个完全共线、作用完全等价的截距项:
- 手动添加的全1常数列会被识别为普通特征,对应系数存放在
log.coef_数组的常数列位置 - 模型自动拟合的截距存放在
log.intercept_中
由于你设置了penalty='none'无正则约束,两个共线的截距项会平分真实截距的总权重,你看到的14.3569刚好是正确截距28.7140的一半,就是权重拆分导致的。其余特征不存在共线性问题,因此系数和statsmodels、SPSS的结果完全一致。你提到的「不设置截距项时模型运行结果正常」,本质是关闭自动截距后,手动添加的常数列单独承担了全部截距权重,没有拆分效应,因此结果正确。
修复方案
两种方式二选一即可,不要同时保留手动加常数列+自动拟合截距的设置:
- 方案1(推荐,符合scikit-learn默认使用习惯):删除
x_train = sm.add_constant(x_train)、x_test = sm.add_constant(x_test)两行手动加常数列的代码,直接用原始特征矩阵传入模型拟合,此时log.intercept_输出的就是完整正确的截距值。 - 方案2:保留手动添加的常数列,初始化模型时关闭自动截距拟合,将模型初始化代码改为
log = LogisticRegression(penalty="none", fit_intercept=False),此时手动添加的常数列对应的log.coef_位置的数值就是正确截距,log.intercept_返回值为0。
快速验证
你可以直接打印当前问题代码中的log.coef_,找到常数列对应的系数值,和log.intercept_的数值相加,结果必然等于statsmodels输出的28.7140,和SPSS验证的正确值完全匹配。
内容的提问来源于stack exchange,提问作者mdiramali
相关产品推荐
相关产品推荐

