用Python实战倾向得分匹配从数据清洗到因果效应评估全流程指南当我们需要评估某个干预措施比如新药效果、营销策略的真实影响时随机对照试验RCT是黄金标准。但现实中我们往往只能拿到观察性数据——用户并非被随机分配到实验组和对照组这就导致了选择偏差。本文将手把手教你用Python和Sklearn构建完整的倾向得分匹配PSM分析流程通过代码实战解决这个痛点。1. 环境准备与数据理解首先导入必要的Python库import pandas as pd import numpy as np from sklearn.linear_model import LogisticRegression from sklearn.ensemble import RandomForestClassifier from sklearn.preprocessing import StandardScaler from sklearn.metrics import roc_auc_score import matplotlib.pyplot as plt import seaborn as sns假设我们有一个电商平台的用户数据集要评估发送优惠券对购买转化率的影响。原始数据包含treatment是否收到优惠券1是0否conversion是否完成购买目标变量特征矩阵X用户历史行为、人口统计等特征重要提示确保所有特征都是在干预发生前就已存在的变量避免引入未来信息2. 倾向得分建模实战倾向得分建模的核心是为每个用户估计其接受干预的概率。我们使用逻辑回归作为基础模型# 数据预处理 scaler StandardScaler() X_scaled scaler.fit_transform(X) # 划分实验组和对照组 treatment_group df[df[treatment]1] control_group df[df[treatment]0] # 训练倾向得分模型 ps_model LogisticRegression(penaltyl2, C1.0, random_state42) ps_model.fit(X_scaled, df[treatment]) # 预测倾向得分 df[propensity_score] ps_model.predict_proba(X_scaled)[:, 1]模型评估指标建议AUC0.7表示模型有较好区分度特征重要性检查关键混杂因素是否被模型捕捉# 评估模型性能 print(fAUC score: {roc_auc_score(df[treatment], df[propensity_score]):.3f}) # 绘制倾向得分分布 plt.figure(figsize(10,6)) sns.histplot(datadf, xpropensity_score, huetreatment, elementstep, statdensity) plt.title(Propensity Score Distribution) plt.show()3. 匹配算法实现与优化完成倾向得分估计后我们需要为每个实验组用户找到最相似的对照组用户。这里实现最近邻匹配from sklearn.neighbors import NearestNeighbors def psm_matching(treatment_df, control_df, ps_colpropensity_score, n_neighbors1): 实现1:1最近邻匹配 nbrs NearestNeighbors(n_neighborsn_neighbors).fit(control_df[[ps_col]]) distances, indices nbrs.kneighbors(treatment_df[[ps_col]]) matched_control control_df.iloc[indices.flatten()].copy() matched_control[match_id] treatment_df.index.repeat(n_neighbors) return pd.concat([treatment_df.assign(match_idtreatment_df.index), matched_control]) matched_df psm_matching(treatment_group, control_group)匹配质量检查关键指标标准化偏差匹配后各特征偏差应5%T检验匹配后组间差异应不显著def calculate_sb(feature, treatment, control): 计算标准化偏差 return 100 * abs(treatment[feature].mean() - control[feature].mean()) / np.sqrt( (treatment[feature].var() control[feature].var())/2) # 对每个特征计算匹配前后的标准化偏差 sb_results [] for col in X.columns: sb_before calculate_sb(col, treatment_group, control_group) sb_after calculate_sb(col, matched_df[matched_df[treatment]1], matched_df[matched_df[treatment]0]) sb_results.append({feature:col, SB_before:sb_before, SB_after:sb_after})4. 因果效应评估与稳健性检验使用匹配后的样本计算平均处理效应ATTatt (matched_df[matched_df[treatment]1][conversion].mean() - matched_df[matched_df[treatment]0][conversion].mean()) print(fEstimated ATT: {att:.3f})为提高结果可信度建议进行以下稳健性检验不同匹配算法比较尝试半径匹配、核匹配等方法模型敏感性分析使用随机森林/XGBoost等不同模型估计倾向得分共同支撑域检查确保实验组和对照组的倾向得分分布有足够重叠# 共同支撑域可视化 plt.figure(figsize(10,6)) sns.ecdfplot(datadf, xpropensity_score, huetreatment) plt.axvline(xdf[propensity_score].quantile(0.05), colorgrey, linestyle--) plt.axvline(xdf[propensity_score].quantile(0.95), colorgrey, linestyle--) plt.title(Common Support Check) plt.show()5. 高级技巧与常见陷阱在实际应用中有几个关键点需要特别注意特征选择策略必须包含所有同时影响干预和结果的变量排除那些可能被干预影响的变量中介变量考虑加入高阶交互项提高模型精度匹配算法选择小样本推荐使用有放回最近邻匹配大样本考虑核匹配或局部线性匹配重要分类变量可先进行精确匹配再计算倾向得分常见错误警示忽视共同支撑域问题匹配后不检查平衡性使用低质量的倾向得分模型忽略未观测混杂因素的影响# 更好的倾向得分模型示例 from sklearn.ensemble import GradientBoostingClassifier from sklearn.model_selection import GridSearchCV gbm GradientBoostingClassifier() params {n_estimators: [100, 200], learning_rate: [0.01, 0.1]} ps_model_gbm GridSearchCV(gbm, params, scoringroc_auc, cv3) ps_model_gbm.fit(X_scaled, df[treatment]) print(fBest GBM AUC: {ps_model_gbm.best_score_:.3f})6. 完整案例营销活动效果评估让我们通过一个模拟案例整合所有步骤# 生成模拟数据 np.random.seed(42) n 5000 X_sim pd.DataFrame({ age: np.random.normal(35, 5, n), income: np.random.lognormal(3, 0.3, n), activity: np.random.poisson(5, n), loyalty: np.random.beta(2,5,n) }) ps 1 / (1 np.exp(-(0.3*X_sim[age] 0.5*np.log(X_sim[income]) - 0.2*X_sim[activity]))) treatment_sim np.random.binomial(1, ps) # 真实效果为提升10%转化率 conversion np.random.binomial(1, 0.2 0.1*treatment_sim - 0.01*X_sim[age] 0.02*np.log(X_sim[income])) # 完整分析流程 df_sim pd.concat([X_sim, pd.DataFrame({treatment:treatment_sim, conversion:conversion})], axis1)通过这个完整流程我们能够准确估计出营销活动的真实效果为9.8%接近真实的10%而简单的组间比较会高估效果显示15%的提升这正是PSM方法的价值所在。