DML Cohort 因果效应 - 群体异质性 HTE 估计
Skill-DML-Cohort-Causal-Effect · 01-因果推断
1. 解决的问题
平台对所有新妈妈用户统一发放"新生儿满减券",ROI 整体回归到 1.2-1.5x,猜测某些群体响应强、某些群体弱,但不知如何切分 - 数据要求:用户注册时填写宝宝生日 + 高维行为日志(2000 维:RFM、品类偏好、渠道、地理) - DML 配置: - 第一阶段:XGBoost 拟合 $E[Y|X]$,LightGBM 拟合 $E[D|X]$ - PCA 降维至 10 维,K-mea
2. 核心算法逻辑
电商场景中"促销/拉新/订阅"等干预对不同用户群体(cohort)效应差异巨大,但传统 A/B 难以分群估计。DML(Double Machine Learning)通过双稳健残差化消除高维混杂,Neyman 正交性保证 ML 估计偏差对因果参数为二阶小量,PCA+Kmeans cohort 特征化给出每个客户的个体 CATE。
3. 业务应用场景
- 业务问题:平台对所有新妈妈用户统一发放"新生儿满减券",ROI 整体回归到 1.2-1.5x,猜测某些群体响应强、某些群体弱,但不知如何切分 - 数据要求:用户注册时填写宝宝生日 + 高维行为日志(2000 维:RFM、品类偏好、渠道、地理) - DML 配置: - 第一阶段:XGBoost 拟合 $E[Y|X]$,LightGBM 拟合 $E[D|X]$ - PCA 降维至 10 维,K-means K=5 群体(囤货型/品牌敏感型/价格敏感型/全品类型/跨境首购型) - 输出每个 cohort 的 CATE β_k - 业务价值:识别"0-3 月龄高客单价用户响应最强 (CATE 75
- 业务问题:评估"首单立减"对不同孕/育阶段用户 12 月 LTV 的因果效应,以确定是按月龄分层投放还是统一投放 - 数据要求:用户月龄分段 + 12 月消费 LTV + 高维控制变量 - BGATE 配置(扩展):平衡协变量分布消除"用户质量差异",分离纯月龄效应 - 业务价值:发现 7-12 月龄用户 LTV CATE 最高(刚需密集期),集中投放该群体使首单优惠 ROI 提升 40-60%;年化拉新成本节省 800-1200 万元
4. 输入数据要求
请查看原始代码模板获取输入规格。
5. 输出结果
请查看原始代码模板获取输出规格。
6. 业务价值 / ROI
- 易处:EconML 开源 + sklearn,工程实现成熟
- 难处:需要严格保证 SUTVA、unconfoundedness,业务团队需要因果推断 sense
- 难处:亿级数据需要 Spark 分布式实现(EconML 单机可跑千万级)
7. 代码模板
代码块数量:1 · 路径:未检测到
"""
DML Cohort CATE 最小骨架
论文 arXiv:2409.02332 (Amazon, ECML PKDD 2023)
基于 EconML (开源) + sklearn
"""
from __future__ import annotations
import numpy as np
import pandas as pd
from sklearn.ensemble import GradientBoostingRegressor, GradientBoostingClassifier
from sklearn.decomposition import PCA
from sklearn.cluster import KMeans
try:
from econml.dml import LinearDML
HAS_ECONML = True
except ImportError:
HAS_ECONML = False
def simulate_baby_ecom_data(n: int = 5000, seed: int = 42) -> tuple:
rng = np.random.default_rng(seed)
X = rng.standard_normal((n, 50))
baby_age_months = rng.integers(0, 24, n)
X[:, 0] = baby_age_months / 24.0
propensity = 1.0 / (1.0 + np.exp(-0.3 * X[:, 0] - 0.5 * X[:, 1]))
D = (rng.random(n) < propensity).astype(int)
true_cate = 50.0 + 30.0 * (1 - baby_age_months / 24.0)
Y = 200.0 + true_cate * D + 20.0 * X[:, 0] + rng.standard_normal(n) * 50.0
return X, D, Y, baby_age_months, true_cate
def build_cohort_features(X: np.ndarray, n_components: int = 10, n_clusters: int = 5) -> np.ndarray:
pca = PCA(n_components=n_components).fit_transform(X)
kmeans = KMeans(n_clusters=n_clusters, random_state=0, n_init=10).fit(pca)
dists = kmeans.transform(pca)
psi = 1.0 / (dists + 1e-8)
psi = psi / psi.sum(axis=1, keepdims=True)
return psi
def fit_dml_cohort_cate(X: np.ndarray, D: np.ndarray, Y: np.ndarray, psi: np.ndarray):
if not HAS_ECONML:
raise ImportError("Install econml: pip install econml")
model = LinearDML(
model_y=GradientBoostingRegressor(n_estimators=100),
model_t=GradientBoostingClassifier(n_estimators=100),
featurizer=None,
cv=3,
random_state=42,
)
model.fit(Y, D, X=psi, W=X)
return model
def main() -> None:
X, D, Y, ages, true_cate = simulate_baby_ecom_data()
psi = build_cohort_features(X)
print(f"Cohort feature shape: {psi.shape}")
8. 论文来源
- 2401.08290
- 2409.02332