共计 2547 个字符,预计需要花费 7 分钟才能阅读完成。
传统 AB 测试在非随机实验中的局限性
在电商推荐系统场景中,我们经常需要评估新推荐算法对用户购买行为的因果效应。传统 AB 测试要求用户完全随机分配到实验组和对照组,但在实际业务中,这种随机性难以保证。例如:

- 用户可能基于自身偏好选择是否查看推荐商品(选择偏差)
- 高频用户更可能同时暴露于新旧算法(混杂因素)
- 节假日等外部因素影响购买决策(时间效应)
这种非随机实验条件下,直接比较两组用户的转化率会得到有偏的因果效应估计。
因果推断核心概念与 AUC 评估
关键术语定义
- ATE(Average Treatment Effect):总体平均处理效应,E[Y(1)-Y(0)]
- ATT(Average Treatment Effect on the Treated):处理组的平均处理效应,E[Y(1)-Y(0)|T=1]
- CATE(Conditional ATE):基于协变量的条件平均处理效应,E[Y(1)-Y(0)|X=x]
AUC 的独特价值
AUC(曲线下面积)在因果推断中特别适用于:
– 存在严重样本选择偏差的场景
– 需要评估处理效应异质性的情况
– 关注排序效果而非绝对效应量的业务场景
Python 实战:基于 PSM 的 AUC 因果评估
环境准备
import numpy as np
import pandas as pd
from psmpy import PsmPy
from sklearn.metrics import roc_auc_score
from sklearn.ensemble import GradientBoostingClassifier
数据生成与预处理
def generate_synthetic_data(n_samples=5000):
"""生成包含混杂变量的模拟数据"""
np.random.seed(42)
age = np.random.normal(40, 10, n_samples)
activity = np.random.poisson(5, n_samples)
# 倾向得分模型(真实 PS)true_ps = 1/(1+np.exp(-(0.1*age + 0.3*activity - 5)))
treatment = np.random.binomial(1, true_ps)
# 结果变量(含处理效应)y = 0.5*treatment + 0.2*age + 0.1*activity + np.random.normal(0,1,n_samples)
return pd.DataFrame({'age':age, 'activity':activity,
'treatment':treatment, 'y':y})
倾向得分匹配实现
def perform_psm(df, covariates, caliper=0.2):
"""执行倾向得分匹配并返回平衡样本"""
psm = PsmPy(df, treatment='treatment', indx='patient_id')
psm.logistic_ps(covariates)
psm.knn_matched(matcher='propensity_score', replacement=False,
caliper=caliper)
return psm.df_matched
AUC 计算与检验
def evaluate_causal_auc(matched_df):
"""计算匹配样本的因果 AUC 并进行假设检验"""
# 分离处理组和对照组
treated = matched_df[matched_df['treatment']==1]['y']
control = matched_df[matched_df['treatment']==0]['y']
# AUC 计算(处理组 vs 对照组的区分能力)y_true = np.concatenate([np.ones(len(treated)), np.zeros(len(control))])
y_score = np.concatenate([treated.values, control.values])
auc = roc_auc_score(y_true, y_score)
# 显著性检验(置换检验)n_permutations = 1000
null_dist = []
for _ in range(n_permutations):
permuted = np.random.permutation(y_true)
null_dist.append(roc_auc_score(permuted, y_score))
p_value = (np.sum(null_dist >= auc) + 1)/(n_permutations + 1)
return auc, p_value
生产环境注意事项
倾向得分模型验证
-
平衡性检验 :匹配后协变量的标准化差异应 <0.1
psm.effect_size_plot() -
重叠性检查 :倾向得分分布应有足够重叠区域
psm.plot_match(Title='PS Distribution', Ylabel='Count', Xlabel='PS') -
敏感性分析 :使用不同匹配算法(knn/radius/optimal)验证结果稳健性
小样本解决方案
- Bootstrap 置信区间 :
def bootstrap_ci(data, func, n_boot=1000, ci=95): """计算统计量的 bootstrap 置信区间""" boot_samples = [] for _ in range(n_boot): sample = data.sample(frac=1, replace=True) boot_samples.append(func(sample)) lower = np.percentile(boot_samples, (100-ci)/2) upper = np.percentile(boot_samples, ci+(100-ci)/2) return lower, upper
开放性问题与延伸思考
- 连续处理变量扩展 :当干预强度为连续值时,可考虑:
- 剂量响应曲线的 AUC 分析
-
广义倾向得分方法
-
与 Uplift Modeling 结合 :
- 将 AUC 作为模型评估指标
- 开发因果感知的排序指标(如 Qini 曲线)
-
异质处理效应的可视化分析
-
领域知识整合 :
- 如何结合业务理解选择混杂变量
- 潜在结果框架下的敏感性分析
- 动态处理效应的时变分析
正文完
