欢迎光临
我们一直在努力

AI 智能营销数据分析:RFM + 聚类 + 推荐的全链路方案

AI 智能营销数据分析:RFM + 聚类 + 推荐的全链路方案

一、营销数据分析的三个阶段

做营销数据分析久了,你会发现大部分公司的营销分析都停留在"第一阶段"——算算 ROI、看看转化率、出个周报。但实际上,真正能驱动业务增长的营销分析应该走完三个阶段:

  • 用户分层:谁是你的高价值用户?谁快流失了?谁还有挖掘潜力?
  • 精准推荐:知道用户是谁之后,给他推什么产品/活动最有效?
  • 效果闭环:推完之后,用户有没有转化?没转化的原因是什么?
  • 这篇文章就把这三个阶段串起来,用一套"RFM + 聚类 + 推荐"的全链路方案,从数据到决策到执行,一气呵成。

    为什么大多数公司的营销分析都停留在第一阶段? 原因不是技术能力不够,而是组织惯性。用户分层需要数据分析师跑 SQL,精准推荐需要算法工程师训练模型,效果闭环需要产品和运营配合设计 AB 测试。三个阶段涉及三个角色,任何一个环节掉链子,整个链路就断了。RFM + 聚类的优势在于:数据分析师或熟练的 Python 工程师一个人就能跑通全流程,不需要专门的算法团队——K-Means 够用了。跑通一次链路后,用数据结果去说服业务方配合做 AB 测试,阻力会小得多。先用轻量方案快速出成果,再用成果推动深度合作,这是在资源有限情况下的最佳实践。

    二、RFM 模型:经典但不过时

    RFM(Recency 最近一次消费、Frequency 消费频率、Monetary 消费金额)是用户分层的经典模型,简单好用,解释性极强。

    为什么 30 年前的 RFM 模型到今天仍然管用? 因为这三个维度直接对应了消费行为的三个底层驱动力:Recency 衡量用户的"记忆热度"(刚买过的人最容易再次购买),Frequency 衡量"习惯程度"(买得越多越容易接着买),Monetary 衡量"投入程度"(花得越多越不会轻易离开)。这三件事不随行业变化,电商、游戏、SaaS、金融都适用。RFM 的另一个巨大优势是"可解释"——你对着老板说"这是一个 R=5, F=1, M=5 的用户",老板可能听不懂;但你说"这个用户最近花了大钱但只买了一次",老板立刻知道该怎么运营。**

    import pandas as pd
    import numpy as np
    from datetime import datetime, timedelta
    from sklearn.preprocessing import StandardScaler
    from sklearn.cluster import KMeans
    import warnings
    warnings.filterwarnings('ignore')

    # ==================== 第1步:计算RFM指标 ====================

    # 模拟交易数据
    np.random.seed(42)
    n_users = 1000

    transactions = pd.DataFrame({
    'user_id': np.random.choice([f'U{i:04d}' for i in range(1, n_users + 1)], 5000),
    'order_date': pd.to_datetime([
    datetime(2026, 7, 1) – timedelta(days=np.random.randint(0, 365))
    for _ in range(5000)
    ]),
    'order_amount': np.random.lognormal(mean=4.0, sigma=0.8, size=5000), # 对数正态分布模拟交易金额
    'order_id': [f'ORD{i:06d}' for i in range(1, 5001)]
    })

    # 设置分析基准日期(比如今天是2026-07-23)
    REFERENCE_DATE = datetime(2026, 7, 23)

    # 计算每个用户的RFM指标
    rfm = transactions.groupby('user_id').agg(
    # Recency: 最近一次购买距离今天的天数(越小越好)
    recency=('order_date', lambda x: (REFERENCE_DATE – x.max()).days),

    # Frequency: 购买次数(越多越好)
    frequency=('order_id', 'count'),

    # Monetary: 总消费金额(越多越好)
    monetary=('order_amount', 'sum')
    ).reset_index()

    print("=== RFM指标统计 ===")
    print(rfm.describe())

    # —- 给RFM打分(1-5分制) —-
    # 按分位数将每个指标分为5个等级

    def rfm_score(series: pd.Series, ascending: bool = True) -> pd.Series:
    """
    将连续值映射到1-5的评分

    参数:
    series: 需要评分的序列
    ascending: True表示值越小分数越高(适用于Recency),
    False表示值越大分数越高(适用于Frequency和Monetary)
    """
    labels = [5, 4, 3, 2, 1] if ascending else [1, 2, 3, 4, 5]
    return pd.qcut(series, q=5, labels=labels, duplicates='drop').astype(int)

    rfm['R_score'] = rfm_score(rfm['recency'], ascending=True) # R: 越近分数越高
    rfm['F_score'] = rfm_score(rfm['frequency'], ascending=False) # F: 越多分数越高
    rfm['M_score'] = rfm_score(rfm['monetary'], ascending=False) # M: 越多分数越高

    # RFM总分
    rfm['RFM_score'] = rfm['R_score'] + rfm['F_score'] + rfm['M_score']

    print(f"\\n=== RFM评分分布 ===")
    print(rfm[['R_score', 'F_score', 'M_score', 'RFM_score']].describe())

    三、K-Means 聚类:从 RFM 到用户画像

    RFM 打分是一种粗分类,想得到更精细的用户画像,需要对 RFM 的原始值做聚类:

    为什么不能直接用 RFM 打分,还要做 K-Means? RFM 打分的本质是"等分"——把用户按 R/F/M 三个维度分别切成 5 等份,然后组合出 125 种可能(5×5×5)。问题是:等分不反映数据的真实分布。如果 80% 的用户 Frequency=1(只买过一次),那你把"买过一次"的用户硬切成 5 组毫无意义。K-Means 的聚类是基于实际数据密度的——用户群在哪聚集,边界就在哪,不是人为硬分。另外,K-Means 前必须做 StandardScaler 标准化,原因是 recency(0-365 天)、frequency(1-50 次)、monetary(10-100000 元)这三个特征的量纲完全不同,如果不标准化,monetary 几乎会完全主导聚类结果,recency 和 frequency 的信息被淹没。这一点 90% 的新手会忽略,结果得出一个只有金额维度的分群。**

    # ==================== 第2步:K-Means聚类 ====================

    # 选择聚类特征:使用RFM原始值
    cluster_features = rfm[['recency', 'frequency', 'monetary']].copy()

    # —- 特征标准化(K-Means对尺度敏感) —-
    scaler = StandardScaler()
    features_scaled = scaler.fit_transform(cluster_features)

    # —- 确定最佳聚类数(手肘法) —-
    # 计算不同K值下的SSE(误差平方和)
    sse_list = []
    k_range = range(1, 11)

    for k in k_range:
    kmeans = KMeans(n_clusters=k, random_state=42, n_init=10)
    kmeans.fit(features_scaled)
    sse_list.append(kmeans.inertia_)

    # 找到手肘点(简化:选择SSE下降变缓的位置)
    # 实际项目中建议用轮廓系数(Silhouette Score)更严谨

    # —- 使用K=5进行聚类 —-
    optimal_k = 5
    kmeans = KMeans(n_clusters=optimal_k, random_state=42, n_init=10)
    rfm['cluster'] = kmeans.fit_predict(features_scaled)

    # —- 分析每个聚类的特征,给分群命名 —-
    cluster_profile = rfm.groupby('cluster').agg(
    avg_recency=('recency', 'mean'),
    avg_frequency=('frequency', 'mean'),
    avg_monetary=('monetary', 'mean'),
    user_count=('user_id', 'count'),
    avg_rfm_score=('RFM_score', 'mean')
    ).round(1)

    print("\\n=== 聚类特征画像 ===")
    print(cluster_profile)

    # —- 根据聚类特征自动打标签 —-
    def label_cluster(row):
    """
    根据RFM均值给聚类打标签

    判断逻辑:
    – 高Monetary + 高Frequency → 高价值用户
    – 高Monetary + 低Frequency → 大单客户
    – 低Monetary + 高Frequency → 活跃小客户
    – 低Recency + 中低Frequency → 潜力用户(最近活跃但频次不高)
    – 高Recency + 低Frequency → 流失风险用户
    """
    r, f, m = row['avg_recency'], row['avg_frequency'], row['avg_monetary']

    # 判断标准(相对于整体均值的比较)
    r_median = rfm['recency'].median()
    f_median = rfm['frequency'].median()
    m_median = rfm['monetary'].median()

    if m > m_median and f > f_median:
    return "高价值用户"
    elif m > m_median and f <= f_median:
    return "大单低频客户"
    elif m <= m_median and f > f_median:
    return "高频小单客户"
    elif r < r_median and f <= f_median:
    return "潜力新用户"
    else:
    return "流失风险用户"

    cluster_profile['segment_name'] = cluster_profile.apply(label_cluster, axis=1)

    # 将标签映射回用户表
    segment_map = cluster_profile['segment_name'].to_dict()
    rfm['user_segment'] = rfm['cluster'].map(segment_map)

    print("\\n=== 用户分群结果 ===")
    print(rfm['user_segment'].value_counts())
    print(f"\\n各分群人数占比:")
    for seg, count in rfm['user_segment'].value_counts().items():
    print(f" {seg}: {count}人 ({count/len(rfm):.1%})")

    四、个性化推荐:基于分群的协同过滤

    有了用户分群之后,推荐就不再是盲目的了:

    为什么分群推荐比全局统一推荐效果好得多? 全局推荐的问题是"平均化"——对所有用户推一样的东西,结果是高价值用户觉得"太 low"、新用户觉得"太贵"、流失用户无感。分群推荐的核心逻辑是:同群用户有相似的消费能力和偏好。高价值用户群里的用户 A 买了某款高端产品,用户 B 很可能也会感兴趣——即使他们俩的历史行为完全不同。这就是"分群协同过滤"比"全局协同过滤"更精准的原因。更进一步,不同群的推送文案也该不同:高价值用户看到"为您臻选"会觉得被尊重,流失用户看到"好久不见,送你一张优惠券"才会点开。一句话总结:精准的秘密不在算法复杂度,而在"谁"收到"什么"的匹配度。

    # ==================== 第3步:基于分群的推荐策略 ====================

    class SegmentBasedRecommender:
    """
    基于用户分群的推荐引擎

    根据不同用户群的特性,采用差异化的推荐策略
    """

    # 各分群的推荐策略
    SEGMENT_STRATEGIES = {
    "高价值用户": {
    "priority": "vip_exclusive", # 优先推VIP专属/高客单价商品
    "price_range": (200, 10000), # 价格区间
    "discount_sensitivity": "low", # 对折扣不敏感,更关注品质
    "channel": "push + sms", # 推送渠道
    "message": "为您臻选的品质好物" # 文案风格
    },
    "大单低频客户": {
    "priority": "similar_upsell", # 推相似品类的高端款(升单)
    "price_range": (100, 5000),
    "discount_sensitivity": "medium",
    "channel": "sms + in_app",
    "message": "基于您的偏好,这些好物值得一试"
    },
    "高频小单客户": {
    "priority": "bundle_deal", # 推组合套餐/凑单优惠
    "price_range": (10, 200),
    "discount_sensitivity": "high", # 凑单敏感,适合推满减
    "channel": "in_app + coupon",
    "message": "凑单满99减20,这些好物加购立减"
    },
    "潜力新用户": {
    "priority": "new_user_bundle", # 推新人专享/入门爆款
    "price_range": (10, 300),
    "discount_sensitivity": "high",
    "channel": "push + coupon",
    "message": "新人专属福利,首单立减30元"
    },
    "流失风险用户": {
    "priority": "recall_coupon", # 推大额召回优惠券
    "price_range": (10, 500),
    "discount_sensitivity": "very_high",
    "channel": "sms + push",
    "message": "好久不见,送你一张50元优惠券"
    },
    }

    def get_strategy(self, user_segment: str) -> dict:
    """根据用户分群获取推荐策略"""
    return self.SEGMENT_STRATEGIES.get(
    user_segment,
    self.SEGMENT_STRATEGIES["潜力新用户"] # 默认策略
    )

    def generate_recommendations(self, user_id: str, user_segment: str,
    user_history: list, top_n: int = 5) -> list:
    """
    生成个性化推荐列表

    参数:
    user_id: 用户ID
    user_segment: 用户分群标签
    user_history: 用户历史购买商品ID列表
    top_n: 推荐数量
    """
    strategy = self.get_strategy(user_segment)

    # 实际生产环境中,这里会调用协同过滤或内容推荐算法
    # 简化示意:
    recommendations = []
    priority = strategy['priority']
    price_range = strategy['price_range']

    # 根据策略筛选候选商品
    # (实际会用向量检索或矩阵分解)
    # …

    return {
    'user_id': user_id,
    'segment': user_segment,
    'strategy': priority,
    'message': strategy['message'],
    'channel': strategy['channel'],
    'candidates': recommendations # 推荐商品列表
    }

    # —- 使用示例 —-
    recommender = SegmentBasedRecommender()

    # 为不同分群的用户生成推荐
    test_users = [
    ("U0001", "高价值用户"),
    ("U0500", "流失风险用户"),
    ("U0800", "潜力新用户"),
    ]

    print("\\n=== 个性化推荐策略 ===")
    for uid, seg in test_users:
    result = recommender.generate_recommendations(uid, seg, user_history=[])
    print(f"\\n{uid} ({seg}):")
    print(f" 推荐策略: {result['strategy']}")
    print(f" 推送文案: {result['message']}")
    print(f" 推送渠道: {result['channel']}")

    踩坑提醒

    • 坑1:RFM 基准日期选错导致用户分群全歪 — 如果你用"今天"作为基准日期来计算 Recency,但你的交易数据只到 3 天前(数据延迟),那么所有用户的 Recency 都会多了 3 天。高价值用户可能因此被错分到流失风险群。基准日期应该是"数据的最新日期"而不是代码的执行日期。
    • 坑2:K-Means K 值拍脑袋选 5 — 手肘法虽然简单,但很多数据集的肘点并不明显。真正的金标准是轮廓系数(Silhouette Score)和业务可解释性的折中。K=5 是一个经验值,但如果轮廓系数在 K=6 时明显更高,就应该用 K=6。
    • 坑3:聚类标签生成后不验标,直接推给运营 — 自动打的标签(如"潜力新用户")跑出来后,必须人工抽样验标,确认标签和实际用户画像一致。否则运营按错误标签发了错误优惠券,效果为负还伤了用户体验。

    五、总结

    营销数据分析的"三段论"——用户分层、精准推荐、效果闭环——缺一不可。

  • RFM + 聚类是用户分层的黄金组合。RFM 提供可解释的业务标签,K-Means 做精细化分群,两者结合比单一方法效果好几倍。
  • 不同用户群要用不同的推荐策略。高价值用户推品质,流失用户推优惠券,新用户推爆款。千篇一律的推荐 = 没有推荐。
  • 推荐必须有反馈闭环。AB 测试是标配,实验组和对照组的转化率差异,才是衡量推荐策略有没有用的唯一标准。
  • 分群标签要定期更新。用户的行为模式会变,上个月的高价值用户这个月可能就流失了。建议至少每周做一次 RFM 重算。
  • 不要只有标签,还要有画像。标签告诉你"用户属于哪个群",画像告诉你"这个群的用户喜欢什么",后者才是推荐的基础。
  • 从"拍脑袋做营销"到"数据驱动做营销",这条路一旦走通,ROI 的提升是肉眼可见的。

    赞(0)
    未经允许不得转载:171主机测评 » AI 智能营销数据分析:RFM + 聚类 + 推荐的全链路方案
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址