LTV Prediction BTYD — BG/NBD + Gamma-Gamma 客户生命周期价值预测
Skill-LTV-Prediction-BTYD · 06-增长模型
causalexperimentforecasting广告与投放客服与VOCWF-B 广告优化WF-C 客服分诊WF-D 选品扫描WF-H 复购增长WF-J DTC 独立站增长WF-L 内容营销增长
年化 ROI¥30-100 万
实现难度⭐⭐☆☆☆
业务视角
适用角色CEO / 增长负责人 · CMO · 财务负责人
适用平台Amazon · TikTok Shop · DTC 独立站 · 多市场
什么情况下用公司增长放缓,不知道是市场饱和还是产品问题还是获客太贵;老板要 12 个月 GMV 预测,只能靠感觉
成功是什么样的建立增长拆解模型找到瓶颈,预测未来 6-12 个月营收区间,支撑融资/战略会议
业务痛点
1. 解决的问题
母婴品牌把「3个月没复购」的用户一律当流失发EDM轰炸,浪费营销预算在已流失用户身上——BG/NBD模型给出每位用户的P_alive活跃概率,精准区分沉睡高价值用户与真实流失,复购激活ROI从1.2x提升到3-4x,年化增益30-100万元
2. 核心算法逻辑
BTYD(Buy Till You Die) 模型族解决一个核心问题:在用户从未明确"取消订阅"的情况下,如何判断他是否已经流失? 跨境电商是典型的非合约场景——用户买了吸奶器之后,可能6个月后再买配件,也可能再也不回来,但他不会告诉你他走了。
3. 业务应用场景
业务问题:有 5,000 名历史买家,其中哪些是"沉睡的高 LTV 用户"(还活跃但3个月没买),哪些是"真正流失"(已经永久离开)?两种人的激活策略完全不同——沉睡用户发优惠券有效,真流失用户发再多也没用(浪费营销预算)。
数据要求: - Amazon/Shopify 订单历史:customer_id, order_date, order_value - 观测期:建议18-24个月历史数据 - 至少3-6个月的稳定数据(新品牌数据不足时模型效果差)
预期产出: - 每位用户的:活跃概率(P_alive)、预测未来12月购买次数、预测 CLV - 高价值沉睡用户名单(P_alive > 0.5, CLV > $50,近3月无购买) - RFM + CLV 四象限分析(Star/Cash Cow/Question Mark/Dog)
4. 输入数据要求
请查看原始代码模板获取输入规格。
5. 输出结果
请查看原始代码模板获取输出规格。
6. 业务价值 / ROI
- ROI 预估:
- 精准识别沉睡高 CLV 用户并激活(vs 全量营销):Email 营销 ROI 提升 2-3×,年增收 ¥10-30 万
- 渠道预算重分配(将 CAC 投向高 CLV 渠道):年增 LTV ¥15-50 万
- 停止向低 p_alive 用户浪费广告再营销预算:节省 ¥5-15 万/年
- 高 CLV 用户优先客服资源:留存提升1%对应 LTV ¥5 万/年
- 年化综合 ROI:¥30-100 万
7. 代码模板
代码块数量:1 · 路径:paper2skills-code/06-增长模型/ltv_prediction_btyd
"""
LTV Prediction using BG/NBD + Gamma-Gamma (BTYD Framework)
不依赖外部 lifetimes 库的纯 Python 实现(简化版)
"""
import numpy as np
import pandas as pd
from scipy.optimize import minimize
from scipy.special import gammaln, betaln
def generate_sample_customer_data():
"""生成模拟母婴电商客户 RFM 数据"""
np.random.seed(42)
n_customers = 500
# 模拟不同用户群体
data = []
for i in range(n_customers):
customer_type = np.random.choice(['loyal', 'occasional', 'one_time'],
p=[0.20, 0.35, 0.45])
T = np.random.uniform(12, 24) # 观测期(月)
if customer_type == 'loyal':
freq = np.random.poisson(8)
recency = np.random.uniform(T * 0.5, T)
monetary = np.random.lognormal(np.log(75), 0.4)
elif customer_type == 'occasional':
freq = np.random.poisson(2)
recency = np.random.uniform(T * 0.2, T)
monetary = np.random.lognormal(np.log(45), 0.5)
else:
freq = 0
recency = 0
monetary = np.random.lognormal(np.log(35), 0.6)
data.append({
'customer_id': f'C{i+1000}',
'frequency': max(0, freq),
'recency': recency if freq > 0 else 0,
'T': T,
'monetary_value': monetary,
'acquisition_channel': np.random.choice(['tiktok', 'google', 'amazon_organic'],
p=[0.3, 0.35, 0.35]),
})
return pd.DataFrame(data)
def bgnbd_log_likelihood(params, frequency, recency, T):
"""BG/NBD 对数似然函数(简化实现)"""
r, alpha, a, b = params
if any(p <= 0 for p in params):
return 1e10
ln_A0 = betaln(a, b + frequency) - betaln(a, b)
ln_A1 = (gammaln(r + frequency) - gammaln(r) - gammaln(frequency + 1)
+ r * np.log(alpha) - (r + frequency) * np.log(alpha + T))
# 处理有复购的用户
if frequency > 0:
ln_A2 = (gammaln(r + frequency) - gammaln(r)
+ r * np.log(alpha) - (r + frequency) * np.log(alpha + recency))8. 论文来源
- 2501.04719