AUC因果推断入门指南:从理论到Python实战

1次阅读
没有评论

共计 2547 个字符,预计需要花费 7 分钟才能阅读完成。

image.webp

传统 AB 测试在非随机实验中的局限性

在电商推荐系统场景中,我们经常需要评估新推荐算法对用户购买行为的因果效应。传统 AB 测试要求用户完全随机分配到实验组和对照组,但在实际业务中,这种随机性难以保证。例如:

AUC 因果推断入门指南:从理论到 Python 实战

  • 用户可能基于自身偏好选择是否查看推荐商品(选择偏差)
  • 高频用户更可能同时暴露于新旧算法(混杂因素)
  • 节假日等外部因素影响购买决策(时间效应)

这种非随机实验条件下,直接比较两组用户的转化率会得到有偏的因果效应估计。

因果推断核心概念与 AUC 评估

关键术语定义

  1. ATE(Average Treatment Effect):总体平均处理效应,E[Y(1)-Y(0)]
  2. ATT(Average Treatment Effect on the Treated):处理组的平均处理效应,E[Y(1)-Y(0)|T=1]
  3. 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

生产环境注意事项

倾向得分模型验证

  1. 平衡性检验 :匹配后协变量的标准化差异应 <0.1

    psm.effect_size_plot()

  2. 重叠性检查 :倾向得分分布应有足够重叠区域

    psm.plot_match(Title='PS Distribution', Ylabel='Count', Xlabel='PS')

  3. 敏感性分析 :使用不同匹配算法(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

开放性问题与延伸思考

  1. 连续处理变量扩展 :当干预强度为连续值时,可考虑:
  2. 剂量响应曲线的 AUC 分析
  3. 广义倾向得分方法

  4. 与 Uplift Modeling 结合

  5. 将 AUC 作为模型评估指标
  6. 开发因果感知的排序指标(如 Qini 曲线)
  7. 异质处理效应的可视化分析

  8. 领域知识整合

  9. 如何结合业务理解选择混杂变量
  10. 潜在结果框架下的敏感性分析
  11. 动态处理效应的时变分析
正文完
 0
评论(没有评论)