为何调整惩罚与截距参数后Sklearn逻辑回归结果远差于StatsModels
结果差异的核心原因
你已经对齐的penalty=None、fit_intercept=False参数并不是结果偏差的来源,核心问题出在求解器对特征尺度的适配能力差异上:
- 你的输入是4次多项式特征,不同次项的数值量级差距极大:如果年龄范围在20-80岁,常数项为1、一次项为20-80、二次项为400-6400、四次项最高可达4000万以上,跨了8个数量级。
- Sklearn的
LogisticRegression默认使用lbfgs拟牛顿求解器,这类求解器对输入特征的尺度非常敏感,在特征尺度差异过大的场景下,容易出现收敛路径偏移、迭代停滞,甚至因数值精度问题收敛到完全错误的参数,最终输出毫无逻辑的预测曲线。 - StatsModels的
Logit类默认使用Newton-Raphson牛顿法求解,这类基于精确Hessian矩阵的优化算法对特征尺度的鲁棒性远高于LBFGS,就算特征量级差异极大,也能稳定收敛到全局最优的最大似然解。
另外你设置的max_iter=300数值偏低,在特征尺度差异大的场景下,LBFGS往往还没走到收敛就提前停止,进一步放大了结果偏差。
Sklearn端的调整方案
方案1:更换适配的求解器(最直接,无需改动现有特征逻辑)
在初始化LogisticRegression时,将求解器替换为和StatsModels逻辑同源的牛顿类求解器,完整配置如下:
clf = LogisticRegression( penalty=None, fit_intercept=False, solver="newton-cg", # 替换默认lbfgs,使用对特征尺度不敏感的牛顿共轭梯度法 max_iter=1000 # 适当提高迭代次数,确保完全收敛 ).fit(X=X_poly, y=y_bool)
这种调整不需要改动特征构造流程,得到的模型参数会和StatsModels的输出几乎完全一致。
方案2:保留默认LBFGS求解器,对多项式特征做尺度对齐
如果一定要用默认的LBFGS求解器,需要先消除不同次项之间的尺度差异:
- 因为
PolynomialFeatures默认生成的第一列是全1的常数项(和你设置的fit_intercept=False逻辑对齐),标准化时要排除这一列,避免常数项被缩放为全0破坏偏置项:from sklearn.preprocessing import StandardScaler scaler = StandardScaler() # 复制原多项式特征,仅缩放非常数项 X_poly_scaled = X_poly.copy() X_poly_scaled[:, 1:] = scaler.fit_transform(X_poly[:, 1:]) # 对预测用的年龄网格特征做完全相同的缩放 age_grid_poly_scaled = age_grid_poly.copy() age_grid_poly_scaled[:, 1:] = scaler.transform(age_grid_poly[:, 1:]) - 用缩放后的特征训练模型即可,LBFGS会因为特征尺度统一正常收敛。
注意:这种方式得到的系数是针对缩放后特征的,不再和原始多项式特征直接对应,但最终输出的预测概率结果和StatsModels是一致的。
内容的提问来源于stack exchange,提问作者szantamano
相关产品推荐
相关产品推荐

