statsmodels Logit表现优异但sklearn LogisticRegression仅达基线AUC的排查
问题定位与修复方案
核心错误:AUC计算使用硬分类标签
sklearn.linear_model.LogisticRegression的predict()返回0/1硬类别,而非连续概率。- ROC AUC必须用正类的连续预测概率计算,仅用两个取值的硬标签计算时,ROC曲线仅存在单阈值点,得到的AUC会天然接近0.5,无法反映模型真实性能。
- 你的statsmodels代码中
result.predict()返回0~1的连续概率,因此结果正常。
次要问题:训练测试集划分不统一
两段代码分别调用train_test_split()且未设置固定随机种子,导致两个模型使用的训练集、测试集完全独立,结果不具备可比性。
正则化问题:参数未对齐、特征未预处理
- sklearn的
LogisticRegression默认使用L2正则化,C=1.0(C与正则化强度成反比),正则化效果高度依赖特征量纲。若两个数值特征量纲差异极大(如一个为千元级、一个为0/1二值),未标准化的特征会导致正则化过度压制大量纲特征的系数,模型退化为基线水平。 - statsmodels的
fit_regularized()默认正则化参数(penalty类型、强度)与sklearn默认配置未对齐,两者拟合的模型本身存在参数差异。
修复后对齐代码
# 统一数据划分,固定随机种子 X = df_model.drop("6MonthOutcome", axis=1) y = df_model["6MonthOutcome"] X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42) # 特征标准化,适配正则化要求 from sklearn.preprocessing import StandardScaler scaler = StandardScaler() X_train_scaled = scaler.fit_transform(X_train) X_test_scaled = scaler.transform(X_test) # sklearn模型:对齐正则化配置,使用概率计算AUC logit_sklearn = LogisticRegression( max_iter=1000, penalty="l2", # 若statsmodels用L1则改为"l1" C=1.0, random_state=42 ) logit_sklearn.fit(X_train_scaled, y_train) # 取正类(标签为1)的预测概率 y_pred_sklearn = logit_sklearn.predict_proba(X_test_scaled)[:, 1] fpr_sk, tpr_sk, _ = metrics.roc_curve(y_test, y_pred_sklearn, pos_label=1) print("sklearn模型AUC:", metrics.auc(fpr_sk, tpr_sk)) # statsmodels模型:使用相同预处理、对齐正则化参数 import statsmodels.api as sm X_train_sm = sm.add_constant(X_train_scaled) X_test_sm = sm.add_constant(X_test_scaled) logit_sm = sm.Logit(y_train, X_train_sm) # 对齐正则化:alpha = 1/C(C为sklearn的正则化倒数参数) result_sm = logit_sm.fit_regularized( method="l2", # 与sklearn的penalty类型对齐 alpha=1.0 ) y_pred_sm = result_sm.predict(X_test_sm) fpr_sm, tpr_sm, _ = metrics.roc_curve(y_test, y_pred_sm, pos_label=1) print("statsmodels模型AUC:", metrics.auc(fpr_sm, tpr_sm))
验证要点
- 确认sklearn计算AUC时使用
predict_proba()返回的正类概率,而非predict()的硬标签。 - 两个模型必须使用完全相同的训练集、测试集、特征预处理流程、正则化配置。
- 若特征量纲差异极小,可跳过标准化步骤,但需手动对齐两者的正则化参数。
内容的提问来源于stack exchange,提问作者Paul M
相关产品推荐
相关产品推荐

