You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

计算倾向得分时LogisticRegression完全拟分离及模型指标差的解决方法

解决Logistic回归完全拟分离与模型表现不佳问题

问题描述

为计算倾向得分,计划用statsmodels的Logistic回归逐年估计截面二元响应模型,解释变量为企业特征(总资产、增长率、市净率、总负债/普通股权益),被解释变量为处理组标识(是否入选)。但估计结果出现完全拟分离(complete quasi-separation),且模型评估指标(McFadden's R²、AUC-ROC等)表现不佳。

已尝试logit_model.fit(method='bfgs')和FirthLogisticRegression,均未解决问题。

代码示例

import pandas as pd
import statsmodels.api as sm
from sklearn.metrics import roc_auc_score

df = pd.read_excel("Posthoc/PSM_firms_combined.xlsx")
X_year = df[df['Year'] == 2015][['Total Assets', 'Growth', 'Price to Book Value per Share', 'Total Debt to Common Equity']]
y_year = df[df['Year'] == 2015]['Treatment']
logit_model = sm.Logit(y_year, X_year)
results = logit_model.fit()
print(results.summary())

# 计算卡方统计量
chi_squared = results.llr
print("卡方统计量:", chi_squared)
# 计算McFadden's R-squared
log_likelihood_model = results.llf  # 模型对数似然值
log_likelihood_null = results.llnull  # 空模型对数似然值
mcfadden_r2 = 1 - (log_likelihood_model / log_likelihood_null)
print("McFadden's R-squared:", mcfadden_r2)
# 计算AUC-ROC
y_pred_prob = results.predict(X_year)
auc_roc = roc_auc_score(y_year, y_pred_prob)
print("AUC-ROC:", auc_roc)

回归结果

Logit回归结果

解决方法

1. 定位数据分离根源

完全拟分离的核心是某个/多个解释变量能完美区分处理组和控制组,先排查:

  • 对每个解释变量,按处理组分组统计分位数(最小值、中位数、最大值),看是否存在某变量在两组中完全无重叠区间。
  • 若有分类变量,用交叉表分析其与处理组的关系,若某类别仅出现在单一组,就是分离来源。

2. 修正模型与变量处理

  • 补加常数项:你的代码里没加截距项!Logistic回归必须包含常数项,否则模型设定错误,修改代码:
    X_year = sm.add_constant(X_year)  # 添加常数项
    logit_model = sm.Logit(y_year, X_year)
    
  • 压缩极端值:对总资产这类规模变量取对数(np.log(X_year['Total Assets']));对增长率、负债率用Winsorize截断上下1%的极端值(借助scipy.stats.mstats.winsorize)。
  • 合并/删除极端样本:如果某变量存在极小样本分组(比如某资产规模区间只有处理组样本),合并到相邻组或直接删除该极端样本(注意避免样本偏差)。

3. 更换鲁棒性估计方法

  • 正则化Logistic回归:给模型加L1/L2正则,解决分离问题同时防过拟合:
    from statsmodels.discrete.discrete_model import Logit
    
    model = Logit(y_year, X_year)
    results = model.fit_regularized(method='l1', alpha=0.1)  # alpha为正则强度,可调整
    print(results.summary())
    
  • 精确Logistic回归:完全拟分离场景下的可靠选择,用lifelines库实现:
    from lifelines import ExactLogisticRegression
    
    model = ExactLogisticRegression()
    model.fit(X_year, y_year)
    print(model.summary())
    
  • 调整Firth回归实现:用statsmodels官方的Firth回归模块(需确保版本足够新):
    from statsmodels.discrete.firth_logit import FirthLogit
    
    model = FirthLogit(y_year, X_year)
    results = model.fit()
    print(results.summary())
    

4. 样本与模型替换

  • 平衡样本权重:如果处理组和控制组样本量差距极大,给小样本组加权重,或先做粗匹配缩小样本范围。
  • 改用机器学习模型:若Logistic回归始终表现差,试试XGBoost/LightGBM这类模型,对非线性关系和分离问题鲁棒性更强:
from xgboost import XGBClassifier

xgb_model = XGBClassifier(objective='binary:logistic', use_label_encoder=False, eval_metric='logloss')
xgb_model.fit(X_year, y_year)
propensity_scores = xgb_model.predict_proba(X_year)[:, 1]

内容的提问来源于stack exchange,提问作者Chris

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 06:50:01