1. 实验分桶概述:为什么需要分桶?分桶在推荐系统中的核心作用

大家好,我是你们这堂课的主讲。做了这么多年推荐系统,我见过太多「拍脑袋上线、哭着回滚」的案例了。今天咱们聊聊实验分桶——这个看似基础、实则决定你实验结论生死的关键环节。

1.1 一个血淋淋的教训:没有分桶的后果

先讲个我亲身经历的事。几年前我负责一个短视频推荐项目,团队急着验证一个新召回模型。当时觉得「就改个召回逻辑,影响不大」,直接全量上线了。结果呢?

  • 次日留存掉了 0.8%
  • 人均观看时长跌了 12%
  • 用户投诉量翻了三倍

更可怕的是——我们花了整整两周才定位到问题。因为线上同时有多个策略在调整,根本分不清是哪个改动导致的。说白了,没有分桶,你连「锅该甩给谁」都不知道。

⚠️ 我曾经踩过的坑: 千万别以为「小改动不用分桶」。任何线上变更,哪怕只改一个阈值,都必须进实验分桶。否则你就是在拿用户数据赌博。

3. 分桶的核心作用:它到底解决了什么问题?

分桶,说白了就是把用户随机切分成多个互斥的组。每组看到不同的推荐策略,然后对比效果。它的核心作用我归纳为四点:

作用 解释 我见过的反面案例
因果推断 确保实验组和对照组只有策略不同,其他因素一致 某团队用新老用户做对比,结果偏差巨大
风险隔离 坏策略只影响小部分用户,不会炸全量 我见过一个排序 bug 只影响了 5% 用户,轻松回滚
并行实验 多个团队同时跑实验,互不干扰 某司 3 个实验共用同一批用户,指标全乱了
统计置信 保证样本量足够,实验结果可量化 分桶太小,跑了两周 p 值还是 0.3

1.3 分桶的底层逻辑:随机性与一致性

分桶听起来简单——把用户随机分到不同组就行。但这里有两个关键点,我当年也是吃了亏才搞明白的。

1.3.1 随机性:不是「看起来随机」就行

你想想看,如果分桶算法有偏差,比如某个桶里全是高活用户,那实验结果能信吗?我建议用 Hash 取模 或 Fisher-Yates 洗牌 来保证均匀分布。

// 一个简单的 Hash 分桶示例(伪代码)
def assign_bucket(user_id, experiment_id, num_buckets=100):
    hash_key = hash(f"{user_id}:{experiment_id}")
    bucket = hash_key % num_buckets
    return bucket
💡 我的个人习惯: 分桶数建议取 100 或 1000 的整数倍。这样后续扩量时,直接按「10%、20%」切分,计算方便,也容易跟业务方解释。

1.3.2 一致性:同一个用户不能反复跳桶

这个坑我踩过。早期我们用随机数分桶,结果用户每次刷新都进不同桶。实验组和对照组的用户一直在「串门」,指标根本没法看。

正确的做法是:用用户 ID 做确定性 Hash。同一个用户,在同一个实验里,永远进同一个桶。

1.4 分桶的常见分层模型

实际生产中,我们不会只有一个实验在跑。可能有推荐算法实验、UI 实验、推送实验……它们怎么共存?

我常用的分层模型长这样:

推荐系统实验分层分桶架构 全量用户(100%) 流量层(Hash 分桶,互斥) 推荐算法实验 实验A: 新召回模型 实验B: 排序权重调整 UI/UE 实验 实验C: 新推荐卡片样式 实验D: 按钮颜色测试 推送实验 实验E: 推送文案 A/B 实验F: 推送时机优化 关键原则:同一层内实验互斥,不同层间实验正交 用户在每个层内只属于一个实验,但可以同时参与多个层的实验 数据上报 → 指标计算 → 决策

这个图我建议你存下来。每次设计实验分桶方案时,先画这么一张图,把「流量怎么分、实验怎么放、数据怎么流」理清楚。

1.5 分桶的常见误区

最后,我总结几个新手最容易踩的坑:

  • 桶数太少:比如只分 2 个桶,实验组和对照组各 50%。这样一旦实验有问题,影响面太大。我建议至少分 10 个桶,灰度时先放 1 个桶(10%)。
  • 忽略用户重叠:同一个用户在不同设备上登录,可能被分到不同桶。要用「用户 ID + 设备 ID」联合 Hash。
  • 实验周期太短:分桶后至少要跑满一个完整的用户行为周期(比如一周),才能看到稳定的指标变化。
  • 只看均值不看分布:分桶实验的结论不能只看平均指标,还要看分位线。我见过一个实验均值涨了 5%,但 P50 跌了 10%——说明只对头部用户有效,对普通用户是伤害。

一句话总结: 分桶不是「把用户随便分一分」那么简单。它是推荐系统实验的基石,决定了你的实验结论是否可信、风险是否可控、团队协作是否高效。

我个人习惯是:每个新项目启动前,先花半天把分桶方案画清楚。磨刀不误砍柴工,这个时间省不得。