P paper2skillsPlaybook
AI 路线图 →

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 个月营收区间,支撑融资/战略会议
业务痛点
增长放缓不知道问题在哪CAC 越来越高已经高于 LTV新市场要不要进没有数据支撑

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