主题
第13章 进阶演进方向
13.1 概述
前 12 章实现了一个完整的优惠券发放系统。但这只是起点——工业界的发券系统在持续演进。本章讨论几个重要的演进方向,帮你理解从"能用"到"好用"还有多远的路。
13.2 Meta-Learner 全家族
第 6 章实现的 T-Learner 是最简单的 Uplift 建模方法。实际上,Meta-Learner 有一个完整的家族,每个成员有不同的优缺点。
S-Learner (Single Model)
思路:只训练一个模型,把 treatment 标记
python
# S-Learner 伪代码
X_with_T = np.column_stack([X, treatment])
model = LGBMClassifier()
model.fit(X_with_T, y)
# 预测增量
X_treat = np.column_stack([X, np.ones(len(X))])
X_ctrl = np.column_stack([X, np.zeros(len(X))])
uplift = model.predict_proba(X_treat)[:, 1] - model.predict_proba(X_ctrl)[:, 1]优点:样本利用率高(全部数据训练一个模型) 缺点:如果 treatment 效果弱,模型可能忽略
T-Learner (Two Models) — 本项目采用
思路:分别训练 treatment 和 control 两个模型。
优点:简单直接,各组独立建模 缺点:两个模型分别在一半数据上训练,样本量减半;各自的预测误差累加
X-Learner
思路:用对方组的模型来估计个体的 treatment effect,然后在各自组上训练增量模型。
第一步:和 T-Learner 一样训练两个基模型
第二步:计算伪标签
第三步:训练两个增量模型
第四步:加权融合
其中
优点:在 treatment 组和 control 组样本量不均衡时特别有效 缺点:实现复杂,需要额外训练倾向性得分模型
R-Learner
思路:直接对残差建模,去除混淆效应。
其中
优点:理论性质好,在观察性数据中更鲁棒 缺点:实现复杂,需要自定义损失函数
DR-Learner (Doubly Robust)
思路:结合结果模型和倾向性得分,具有"双重鲁棒性"——两个模型中只要一个接近正确,估计就是一致的。
优点:统计性质最优,对模型误设定更鲁棒 缺点:倾向性得分接近 0 或 1 时数值不稳定
对比总结
| 方法 | 模型数 | 样本效率 | 实现复杂度 | 适用场景 |
|---|---|---|---|---|
| S-Learner | 1 | ★★★★★ | ★ | 效果强、数据充足 |
| T-Learner | 2 | ★★★ | ★★ | 通用首选 |
| X-Learner | 4+ | ★★★★ | ★★★ | 样本不均衡 |
| R-Learner | 3 | ★★★★ | ★★★★ | 观察性数据 |
| DR-Learner | 3 | ★★★★★ | ★★★★ | 高精度需求 |
推荐路线
T-Learner → X-Learner → DR-Learner。T-Learner 是 MVP 首选(本项目已实现),随着数据和工程能力的增长逐步升级。
13.3 Causal Forest
Causal Forest(因果森林)是非参数异质性因果效应估计的前沿方法(Athey & Imbens, 2018)。
核心思想:在随机森林的基础上,对每次分裂进行修改——不是最大化预测准确度,而是最大化子节点间 treatment effect 的差异。
python
# 使用 econml 库
from econml.dml import CausalForestDML
cf = CausalForestDML(
model_t=LGBMClassifier(), # treatment 模型
model_y=LGBMRegressor(), # outcome 模型
n_estimators=1000,
min_samples_leaf=10,
)
cf.fit(Y=y, T=treatment, X=X)
uplift = cf.effect(X)优点:
- 非参数方法,不需要假设函数形式
- 自带置信区间(可以知道 uplift 估计的不确定性)
- 自动发现异质性子群
缺点:
- 计算成本高,不适合百万级实时场景
- 需要
econml库,依赖较重
13.4 多目标优化
当前系统只优化增量 GMV。但实际业务中,优惠券的效果是多维度的:
max α × 增量GMV + β × 7日留存提升 + γ × 品类渗透率
s.t. 总成本 ≤ 预算Pareto 最优
多目标优化没有唯一的最优解,而是一组 Pareto 最优解(帕累托前沿):
┌──────────────────────────┐
│ ● │
留存提升 │ ● ● │ ← Pareto 前沿
│ ● ● │
│ ● ● │
│ ● ● │
└──────────────────────────┘
增量 GMVPareto 前沿上的点,不存在另一个解能同时在所有目标上更好。业务方在前沿上选择一个符合当前阶段的权衡点。
实现方向
- 加权求和法:最简单,
,通过调整权重实现不同侧重 - 约束法:将部分目标转为约束(如"留存提升不低于 x%"),只优化 GMV
- 进化算法:NSGA-II 等多目标进化算法,直接求 Pareto 前沿
13.5 强化学习方向
Contextual Bandit
将面额选择建模为 Contextual Bandit 问题:
- Context:用户特征
- Action:面额
- Reward:增量 GMV(或转化)
每次发券后观察真实奖励,更新策略。这天然解决了 exploration-exploitation 问题。
python
# 伪代码:LinUCB
class LinUCB:
def select_action(self, x):
"""对每个面额计算 UCB 上界,选最大的."""
best_a, best_ucb = None, -float("inf")
for a in actions:
theta = self.theta[a]
ucb = theta @ x + alpha * sqrt(x @ self.A_inv[a] @ x)
if ucb > best_ucb:
best_ucb = ucb
best_a = a
return best_a
def update(self, x, a, reward):
"""观察奖励后更新参数."""
self.A[a] += np.outer(x, x)
self.b[a] += reward * x
self.A_inv[a] = np.linalg.inv(self.A[a])
self.theta[a] = self.A_inv[a] @ self.b[a]对比当前方案
| 维度 | Uplift + 贪心(当前) | Contextual Bandit |
|---|---|---|
| 训练 | 离线批量 | 在线增量 |
| 探索 | 固定探索组 15% | 自动平衡探索/利用 |
| 面额选择 | 启发式规则 | 直接优化 |
| 延迟反馈 | 需等 7 天观察窗口 | 可处理延迟奖励 |
| 工程复杂度 | 简单 | 复杂(需要实时反馈流) |
13.6 实时化演进
当前系统是离线 + 在线查表模式。下一步演进方向是实时化:
mermaid
graph LR
A[用户浏览事件] -->|Kafka| B[Flink 实时特征]
B --> C[实时模型推理]
C --> D[预算实时管控]
D --> E[发券]
E -->|反馈| F[在线学习更新模型]
F --> C实时特征计算
用 Flink 替代 Pandas 做特征计算,支持滑动窗口聚合:
每个用户维护一个实时特征向量:
- 近 1 小时 PV
- 近 1 小时详情页浏览数
- 当前 session 浏览商品数
- 最近浏览商品的均价实时预算管控
离线预算优化是"一次性分完当天预算"。实时化后需要分时段管控:
日预算 100 万,按小时分配:
00:00-06:00 → 5% (低流量时段)
06:00-10:00 → 15%
10:00-14:00 → 25% (午间高峰)
14:00-18:00 → 20%
18:00-22:00 → 30% (晚间高峰)
22:00-24:00 → 5%每小时结束时,如果预算有剩余,顺延到下一小时。如果超支,降低 Uplift 阈值(让更少的人收到券)。
13.7 模型升级路线图
综合以上演进方向,推荐的升级路线是:
Phase 1(当前): T-Learner + 贪心/拉格朗日 + 离线分配
↓
Phase 2: X-Learner + 多面额响应曲线 + 实时特征
↓
Phase 3: DR-Learner + Contextual Bandit 探索 + 实时预算管控
↓
Phase 4: Causal Forest + 多目标 Pareto 优化 + 在线学习每个阶段的升级都建立在前一个阶段的基础上。不要跳步——Phase 1 的基础设施(AB 实验、风控、配置管理)是后续所有升级的前提。
本章小结
- Meta-Learner 家族:S / T / X / R / DR-Learner,T-Learner 是通用首选,X/DR 适合高级场景
- Causal Forest:非参数因果推断方法,自带置信区间,但计算成本高
- 多目标优化:从单纯的增量 GMV 扩展到 GMV + 留存 + 品类渗透的 Pareto 优化
- Contextual Bandit:把面额选择建模为在线决策问题,自动平衡探索和利用
- 实时化:Flink 实时特征 + 分时段预算管控 + 在线学习
- 演进路线:T-Learner → X-Learner → DR-Learner → Causal Forest,基础设施先行
思考题
- X-Learner 在 treatment/control 比例为 90/10 时比 T-Learner 好多少?为什么?
- 如果业务方要求"留存提升不低于 5%",如何把这个约束加入到当前的预算优化框架中?
- Contextual Bandit 的一个挑战是"延迟奖励"——发券后 7 天才知道用户有没有转化。你会如何处理这个问题?