下载研究报告
CHAPTER 06 · TECHNICAL / DESIGN

核心技术模块(上):设计、分桶与统计

实验设计的核心不是选一个检验,而是让随机化单元、干扰结构与统计方法彼此匹配。

12,984 字 26 分钟 50 条引用

6.1 实验设计的决策树#

把十种实验类型排成一张菜单,是竞品文档最常见的写法;但真正有用的是菜单背后的约束求解。一个实验设计由四个变量决定:干扰结构、随机化单元、观测方式、时间尺度;类型只是这四个变量的常见组合——cluster 是「有溢出 + 簇单元」,switchback 是「有均衡效应 + 市场×时间」,interleaving 是「排序偏好 + 合并列表」,holdout 是「长期 + 小比例留出」。平台因此不必为每种类型写一套对象,而可以把它们表示为同一套 assignment / exposure / schedule / analysis 配置的不同取值。

A/B 测试的默认假设不是「随机化」,而是 SUTVA(stable unit treatment value assumption):一个单元的结果只取决于它自己的处理,单元之间没有交互。双边市场、社交网络、内容社区、广告竞价最容易违反它;Airbnb 的定价实验发现,用户级 Bernoulli 随机化下约 32.60% 的估计偏差来自干扰,而不是抽样误差 来源。所以决策树的第一层不该是「我有多少流量」,而该是「处理一个单元会不会改变另一个单元的结果」。

干扰不是二值变量,而是五种形态。把它们分开,才能解释为什么「同一个 A/B 框架」在某些业务上永远做不出可信结论。

表 6-1 五类干扰与对应设计

干扰形态 机制 例子 首选设计 代价
溢出 spillover 处理组行为直接改变对照组结果 社交邀请、共享库存、同城司机供给 Cluster randomization DEFF 膨胀;簇数少时推断难
均衡效应 equilibrium 处理改变市场价格、匹配概率或供给 定价、补贴、派单、费率 Switchback 有效样本等于切换次数
共同冲击 common shock 同一时段所有单元受同一事件影响 大促、天气、版本发布 Switchback + 时间固定效应 周期共振、carryover
组成变化 composition 长期看用户结构、留存或学习行为被改变 推荐策略、增长策略、会员权益 Holdout 样本小、周期长
偏好异质 heterogeneity 排序质量因人、因 query 而异 搜索、推荐排序 Interleaving 只测偏好,不测业务价值

决策树的四条剪枝规则。 第一,先问干扰,再问流量:有溢出且 cluster 足够,优先 cluster;不够再看市场×时间切换;都不行才考虑准实验或放弃。第二,再问「要估计还是优化」:要回答「大多少」必须固定分配;要最小化 regret 才用 MAB;MAB 的自适应分配破坏 i.i.d.,它的定位是优化器,不是测量仪 来源。第三,再问「短期还是长期」:短期赢不等于长期赢,holdout 是叠加层,不是替代品。第四,排序类先 interleaving、后 A/B:interleaving 换敏感度,但只测偏好,不能直接当 ship 决策。

走完规则,落地的不是「一个类型名」,而是一组配置:Assignment(随机化单元、盐、比例、层/互斥域)、Exposure(谁真的被处理、触发条件)、Schedule(一次性、时间块、序列、长期 holdout)、Analysis(分析单元、方差估计、CUPED、序贯、多重比较、SRM)。同一个 Assignment 可以配不同的 Analysis:cluster 分配既能按 cluster 聚合,也能在用户级回归上用 cluster-robust 方差;同一个 Analysis 可以服务多种设计:Delta method 既算比率指标,也算 cluster 的「分子求和 / 分母去重」。平台把「设计」和「分析」解耦,才能避免类型数量爆炸;反过来,把 switchback 做成一个下拉框、却复用了用户级方差,是这类平台最常见的伪产品化。

6.2 随机化单元与实验类型#

随机化单元是整份设计里唯一不能事后修补的选择。分析可以换估计器,方差可以换方法,CUPED 可以后补;但「按 session 随机」一旦发生,没有任何统计技巧能把用户级因果效应救回来——同一用户今天在新版、明天在旧版,留存和复购会被系统性稀释。

表 6-2 九种随机化单元

单元 稳定性 覆盖 主要风险 适用
user_id 高(登录后) 仅登录用户 匿名流量丢失、多端不一致 长期指标、账户级功能
account_id 高 B2B/组织 单元少、同事间干扰 席位定价、组织级功能
device / installation ID 中(重装重置) 全部设备 一人多设备、IDFA/GAID 受限 匿名 App、UI
cookie 中(可清除) Web 清 cookie 后重抽、跨端不通 Web 实验
session 低 全部会话 同一用户跨会话看到不同版本 纯 UI、文案、加载动画
geo / cluster 高 地理/集群 单元极少、需 cluster 推断 marketplace、供给网络
market×time 由调度决定 单市场 切换次数决定功效 定价、派单、补贴
query 高(单次) 搜索/推荐 只覆盖排序场景 Interleaving
conversation 中 LLM 多轮 样本少、组内相关大 助手、客服、agent

选择原则:随机化单元决定方差的分母,分析单元可以更细但必须折算,曝光单元可以更粗但会稀释。 三者不必字面相同,但必须显式声明关系。Google 的 cookie 取模实验以 cookie 为随机化单元、query 为分析单元,同一 cookie 的多个 query 不独立,必须用 Delta method 把方差折算到 cookie 级 来源。反过来,按用户随机却把没曝光的用户算进分母,曝光率 10% 时观测效应大约只剩 10%;但稀释的前提是曝光与处理独立,如果某一臂加载更慢、崩溃更多,那是选择偏差,不是稀释。

字节 DataTester 的做法值得单独提:它把 decision_id(只算命中)与 track_id(只做上报)分开,让匿名期用设备 ID 分流、登录后用 uid 统计时不跳组 来源 来源。这是「随机化单元、分析单元、曝光单元」三者关系的一个工程解:不强行让三个 ID 相等,而是让它们可追溯、可对齐。移动端更复杂,至少还有 installation ID、设备 ID、账号、会话四种单元;UI 实验用 installation ID 够了,权益/钱包必须用账号,跨端体验必须用账号,推送则要用账号或 token,并记录「是否实际送达」,否则打开率会被分母污染。

三种并行设计。 A/B/n 对 unit_id 加盐哈希到 k 个桶,每臂样本约 16σ²/Δ²(95% 置信、80% 功效),总样本约 k×n,再叠加多重比较校正。Factorial 全析因需要 2^k 个格子,总样本 2^k × n_cell,交互检验功效远低于主效应;NIST 手册明确说 5 个及以上因素时全析因不再高效 来源,DoorDash 用部分析因研究留存,说明「多因素、低成本、可接受别名」是它的边界 来源。实施上必须「联合分配」:平台把因素组合作为一个 variant 下发,否则交互效应无法识别。

Crossover 让每个用户做自己的对照:按随机顺序接受两种处理(TC 或 CT),比较同一用户两阶段的差异,消掉用户间的稳定差异。微软的 FORME 论文证明,在相同流量和时长下,crossover 的方差通常不高于并行设计,并提出 re-randomized design 检验 carryover 来源。它的代价是学习/习惯化会破坏可逆性,两阶段之间需要 washout;序列随机化只平衡顺序,不消除时间趋势。它适合 UI 响应、延迟、推荐点击这类可逆的短期处理,不适合留存、付费、不可逆的功能。

把 6.1 的四变量与本节九种单元组合,十种实验类型可以在一张表里定位;平台的产品化重点不是类型数量,而是单元注册表 + 分析插件。建实验时强制声明随机化、分析、曝光三个单元并校验关系,比事后做 SRM 排查便宜得多。美团 BETA 把 CUPED、Delta、Bootstrap、Fisher/Neyman、SRM、MDE 做成方法库,而不是把统计写死在某个实验类型里,也是同一个思路 来源。

6.3 正交分层、互斥与 Holdout#

分层、互斥、holdout 常被并列成三个功能,其实它们管的是三种不同资源:分层管并行度,互斥管参数冲突,holdout 管长期总量。三者叠加,才构成一个平台的「流量账本」。

Google 2010 年的重叠实验设施把系统拆成三个概念:domain(域,流量的一份划分)、layer(层,参数的子集)、experiment(在某个流量划分上修改若干参数)。规则是:一个请求每层最多进一个实验;同层实验互斥,不同层用 layer_id 作盐、近似正交。分桶写成 f(cookie, layer_id) % 1000,而不是 f(cookie) % 1000,这是层间独立的关键 来源。Google 还引入了 launch layer(发布层):它永远在默认域、拥有全量流量,把实验参数写成「新的默认值」,普通层实验仍可覆盖;这样灰度发布和实验共用一套设施,发布过程本身也可被度量。

容量账。 若有 L 个层、每层覆盖 c_l、实验在本层占 s,则样本期望是 N × c_l × s;一个用户最多同时进入 L 个实验。分层的本质是用流量换并行度:层数越多,单实验能拿到的流量越少;一个需要 50% 流量才能检出 1% 效应的实验,在 10 层结构里可能永远拿不到足够样本。

正交性是假设,不是保证。不同盐、不同 layer_id 理论上独立,但短 key、相似 key、弱雪崩会让相关性浮现;工程上不能只靠假设,要用 2×2 卡方、Cramér's V,或用两套盐跑 A/A,确认两个层的分组没有关联。

互斥的两种实现。 区间互斥让每个实验占一段 [start, end),简单、可计算容量,但不能表达复杂的「部分重叠」约束;过滤器/排除组更灵活,但需要共享状态、顺序敏感,边缘/无状态 SDK 很难做。GrowthBook 用 filters 和 namespace 来源,Google 用区间 + 层,Optimizely 用 mutex group,Statsig 用 layer 并锁定运行中的实验 来源。两者本质相同:用确定性的区间划分代替运行时状态,代价是每实验只能拿 1/k 流量。

Holdout 是长期对照资产,不是实验类型。 它留出一小部分用户,在较长时间内看不到一组新功能/新策略,再从非 holdout 用户中抽等规模样本对照,比较累计指标差异。三家头部平台的默认值差异很大:

表 6-3 三家平台的 holdout 设计

平台 默认比例 对照构造 周期建议 关键限制
Statsig 1%–2% 从非 holdout 随机抽等规模样本 3–6 个月 holdout 内 gate 返回 false;层内实验返回 layer defaults
GrowthBook 默认 5% 非 holdout 中取同样 5% 做 measurement 冻结后再跑 2–4 周 不能给带 conversion window 的指标;需 lookback
Eppo 客户在 withheld traffic 内设定 status_quo vs all_shipped 客户定义 需把 holdout 作为 experiment 记录,并链接子实验

来源:Statsig 来源;GrowthBook 来源;Eppo 来源。

Holdout 的功效由 holdout 组大小封顶,不由总流量决定。 1% holdout 在 1000 万 DAU 上是 10 万人;若对照也抽 10 万人,等于每臂 10 万。以 10% 基线转化率为例,80% 功效下这个样本只能检出约 0.38pp 的绝对提升(相对 3.8%),检不出 1% 的相对变化——后者需要约 142 万人/臂。所以 1% holdout 适合看方向性、大效应,不适合验证精细提升;要检测小效应,要么把 holdout 扩到 5% 以上,要么接受更粗的决策阈值。统计上还有两个难点:holdout 可能被社交、广告的间接接触污染,效应是「直接 + 部分间接」的混合;带 conversion window 的指标需要回看历史,冻结时点与测量窗口必须提前写死。

表 6-4 三层流量账本

机制 资源单位 解决什么 主要代价 失效模式
分层 层内流量 多实验并行 单实验样本稀释 层间相关、层数过多
互斥 互斥域内桶 同参数/同界面冲突 每实验 1/k 流量 运行中换层、容量硬约束
Holdout 全局保留比例 长期累计增量 功效、周期 太小/太短/污染/漏 gate

6.4 Switchback / Cluster / Interleaving / MAB#

当 SUTVA 被违反,标准 A/B 的对照组就不再是对照组。四种设计分别对付四类违反:cluster 对付溢出,switchback 对付均衡效应与共同冲击,interleaving 对付排序偏好的异质性,MAB 对付「多臂、快速反馈、以累计收益为目标」的场景。它们不是四个可以随便替换的「实验类型」,而是四种不同的兑换关系。

表 6-5 四种非标准设计的对照

设计 干扰类型 随机化单元 分析单元 有效样本 核心假设 产品化程度
Cluster 溢出 城市/卖家/创作者/社群 cluster 或用户级 + CRVE 簇数 簇内相关、簇间无溢出 中(GrowthBook、Airbnb、LinkedIn)
Switchback 均衡、共同冲击 市场×时间段 block 切换次数 非预期、m 阶 carryover、时间平稳 低中(Eppo closed Beta)
Interleaving 偏好异质 query/session query 非平局 query 数 合并算法与 credit 规则无偏 低(多为专用系统)
MAB 无干扰但自适应 用户/上下文 臂 无固定每臂样本 平稳、即时反馈、单目标 中(部分平台以 bandit 提供)

Cluster randomization。 以 cluster(城市、卖家、创作者、listing 簇、学校、家庭)为单位随机分配,簇内所有单元接受同一版本。分析时在 cluster 层聚合,或在单元层用 cluster-robust 方差;样本量用 DEFF = 1 + (m - 1) × ρ,m 是簇平均大小,ρ 是 ICC。若 m=100、ρ=0.05,DEFF≈5.95,10 万用户只相当于约 1.7 万独立用户。簇只有十几个时,CRVE 本身不可靠,应改用 wild cluster bootstrap 或 randomization inference。

Airbnb 的定价 meta 实验用观测数据构造 listing 簇,与 Bernoulli 随机化并列比较,发现 Bernoulli 估计中 32.60% 来自干扰偏差 来源。LinkedIn 用 ego-cluster 随机化 ego 的邻居,约 20 万 ego 需要处理约 1000 万个体;loss rate 会带来保守偏差,作者用 degree 分层控制 来源。这说明 cluster 不是「更保守的 A/B」,而是「换一个随机化单位重新定义 estimand」。

Switchback。 把一个聚合单元(城市、市场、区域)在时间上切成若干 block,每个 block 随机分配 treatment 或 control;该单元、该时段的所有用户接受同一版本,共享供给、价格均衡、司机/骑手池的干扰被「同一时段的同一市场」吸收。Bojinov、Simchi-Levi、Zhao 把设计形式化:在 carryover 阶数 m 下,block 长度、切换次数、carryover 假设必须一起定 来源。关键参数是:block 长度大于 carryover 阶数;切换后加 burn-in/burn-out;时间趋势用随机化时点和固定效应处理。

分析单位是 block(市场×时间段),不是用户:先按 block 聚合,再做配对/固定效应回归;标准误 cluster 到市场或 block。有效样本是切换次数,不是用户数;把用户级 n 代进功效公式,是这类实验最常见的统计错误。ABAB 固定交替在有周内周期时会和周期共振,更稳的是在 strata 内随机化切换顺序,或随机化 block 长度。Eppo 已把 switchback 做成 closed Beta:environment entity、带时间窗的 assignment 表、burn-in/out,以及 join 诊断 来源。

Interleaving。 把两个 ranker 的结果合并成一个列表呈现给同一用户,按点击/转化把 credit 分给两个 ranker,再用「用户偏好哪个 ranker」的比例做检验。经典 Team Draft 每个位置抛硬币决定本轮谁选,被选中的 ranker 给出最靠前且未用过的 item;统计单位是 query/session,不是用户,同一列表内竞争消掉了用户间、query 间方差,所以敏感度远高于用户级 A/B。

Airbnb 在 KDD 2025 报告:搜索排序场景下,interleaving 与反事实评估结合,可把敏感度提升到传统 A/B 的最多 100 倍(取决于方法与指标)来源。但论文另一处写「达到同等统计功效所需流量约为 A/B 的 1/50」,叠加反事实评估后部分指标可达 1/100;二手转述常把两者合并成「100 倍」,存在不同说法。选型时要问「在哪个指标、哪种合并算法、什么 query 分布下测得的倍数」,而不是记一个常数。

检验通常从符号检验开始:每个 query 记 A 赢/B 赢/平,在非平局样本上做二项检验(p=0.5)。要检测 55% vs 50% 的偏好差,单侧 0.05、80% 功效约需 620 个非平局 query;若平局率 40%,实际要跑约 1,030 个 query。更精细的是对 credit 差值做配对 t 检验或 bootstrap,并对长尾 query 加权;ECIR 2023 的 Stat-weight 指出,TD 在均匀 query 上不错,但真实搜索是长尾,少数高频 query 会主导总 credit,按 query 的统计检验结果分配权重更准、更敏感 来源。

MAB。 在实验过程中根据观测 reward 动态调整各臂流量,把更多流量给当前看起来更好的臂,以最大化累计收益、最小化 regret。常见策略是 Thompson Sampling 和 UCB。它与 A/B 的根本区别是:A/B 的目标是「估计效应」,MAB 的目标是「优化决策 policy」;自适应分配破坏 i.i.d.,朴素 t 检验有偏,需 IPW/DR/Bayesian。Spotify 明确不在实验平台用 MAB,理由是单指标、反馈慢、多目标配置复杂 来源。

表 6-6 四种设计的兑换关系

设计 换到 付出
Cluster 抗溢出、可解释的整组效应 DEFF 膨胀、簇数少时推断难
Switchback 吸收均衡效应与共同冲击 有效样本=切换次数、周期与 carryover 设计复杂
Interleaving 敏感度提高 1–2 个数量级 外部效度:只测排序偏好,不测收入/留存
MAB 累计 regret 最小 不可估计 ATE、推断复杂、易被干扰误导

这张表是本章的第一个结论:实验设计没有免费午餐,只有「用哪种方差/偏差换哪种决策速度」。平台的价值不是把四种设计都做成按钮,而是让实验 owner 看清每种选择在兑换什么,并在分析侧强制配套的方差方法。

6.5 分桶与哈希工程#

分桶的本质,是把「用户身份 + 实验盐 + 算法版本」映射成一个稳定、可复现的伪随机数。多数的分流事故不是哈希不够随机,而是盐、桶数、版本、分流单元和曝光口径在变更中被悄悄破坏。把分桶写成纯函数 bucket = H(salt ‖ unit) mod N,它必须同时满足四条不变量:确定性、均匀性、单调性、稳定性;最难的是后两条,因为它们取决于分桶空间如何被切分,而不是哈希函数本身。

  1. 确定性:同样的 (salt, unit, N, version) 在任何语言、任何机器、任何时间都得到同一个结果。跨语言一致性比均匀性更难,因为字符串编码、整数位宽、取模语义都可能不同。
  2. 均匀性:大量 unit 落入每个桶的概率近似 1/N。有限哈希空间对 N 取模必然有微小偏差,关键是偏差要远小于实验要检测的效应。
  3. 单调性:覆盖度从 10% 扩到 20% 时,原来在 10% 里的用户必须全部保留。这条不变量决定「放量」会不会变成「重洗」。
  4. 稳定性:改文案、改定向条件、改指标定义,都不应该改变用户的桶;只有显式修改 salt、权重或算法版本才允许重洗。

四条里最难的是第三、四条,因为它们不是哈希函数本身的性质,而是分桶空间如何被切分的性质。很多平台在覆盖度上做对了,在权重上却做不到。

分桶是一份跨端契约。 契约字段是 (hash_algorithm, salt, bucket_count, hash_version, unit_type, encoding, separator, range_rule);它至少出现在 SDK 求值、服务端兜底、离线复盘、曝光日志校验四个地方,每多一个位置就多一份「契约漂移」风险。防御只能靠金标测试向量:固定几百组 (salt, unit),把期望桶值写进 JSON,所有语言的 CI 跑同一份文件;GrowthBook 有 400+ 条语言无关用例 来源。

哈希选型:不是越强越好。 分桶不是密码学场景,真正重要的是跨语言可复现、分布均匀、计算便宜、永不回退。SHA-256 的价值在抗碰撞,不在均匀性;MurmurHash3、FNV-1a 在非对抗场景下完全够用。换一个更快的哈希,通常不会改变实验结果,却能把单次求值从几十微秒压到几微秒。

表 6-7 五种哈希的工程对比

算法 输出位宽 相对速度 典型使用者 工程注意点
MurmurHash3 x86_32 32 bit 很快 Optimizely、Unleash 有符号整数溢出;不同语言的 32 位实现要统一
SHA-1 160 bit(常截断) 快 LaunchDarkly 取前 15 个十六进制字符(60 bit);大小写要统一
SHA-256 256 bit 中等 Statsig 取前 8 字节时注意大小端;不要用字符串比较
FNV-1a 32 32 bit 极快、实现最短 GrowthBook(v2 双重 FNV) 雪崩性弱,单次哈希易有偏,必须二次混淆
MD5 128 bit 中等 早期自研系统 除历史包袱外没有理由继续用

GrowthBook 的案例最值得研究:v1 是 fnv32a(value + seed) % 1000,官方注释直言「在并行实验时有偏」;v2 改成 fnv32a(fnv32a(seed + value) + "") % 10000,用双重哈希改善雪崩性,并把桶数从 1000 提到 10000 来源。这段历史说明两件事:FNV 单次哈希对拼接字符串混合不够,二次哈希是廉价补救;算法升级必须版本化,否则所有在线实验会在发布瞬间被重洗。

表 6-8 六家平台的分桶机制(仅列官方文档/源码可确认者)

平台 哈希与桶数 盐/版本 分层与互斥
GrowthBook FNV-1a 32,v2 双重哈希,10000 桶(v1 为 1000) 实验 key 或显式 seed;hashVersion 版本化 namespace + filters;区间不重叠即互斥
LaunchDarkly SHA-1 前 15 hex(60 bit),权重分母 100000 flag 自带 salt;rollout 可带独立 seed segment + rollout;无显式分层
Statsig SHA-256,实验 10000 / 层 1000 每条规则唯一 salt;可复制 salt layer + holdout
Optimizely MurmurHash3,bucketing ID;桶数未公开(待核实) experiment ID + bucketing ID mutex group
Eppo 未公开具体算法,按实验 key 加盐的确定性哈希 allocation key allocation + entry point
Unleash 归一化 MurmurHash 按 flag/环境 无分层,靠 strategy 组合

这张表最重要的不是参数,而是公开程度的差异。GrowthBook、Statsig、LaunchDarkly 的文档或源码足以复刻其分桶;Eppo 只说「deterministic hashing function salted with the experiment key」,没有给位宽和取模方式 来源;Optimizely 的文档入口在 2026 年迁移,从 Go SDK 源码可确认 MurmurHash 和 bucketing ID,但桶数未公开 来源。对标时不能把「文档没写」当「没有」,也不能把「有这个名字」当「实现相同」。

模运算偏差:桶数必须远小于哈希空间。 设哈希空间 H、桶数 B,最大相对偏差约 B/H。32 位哈希配 10000 桶,B/H ≈ 2.3×10⁻⁶,可以忽略;8 位哈希配 100 桶,偏差高达 50%,绝对不能接受。结论不是「取模一定有偏」,而是「桶数必须远小于哈希空间」;小哈希应改用乘移法或拒绝采样。

盐的语义:一个实验一个盐。 盐不是加密,而是去相关。两个实验用同一个盐、同一个 unit、同一个桶数,桶值完全相同,分组高度相关,差异方差被低估、显著性被高估;极端情况下两个实验其实是同一批人。LaunchDarkly 用 SHA1("{flagKey}.{salt}.{contextValue}");Statsig 每条规则生成唯一 salt,复用同一条规则时 50%→0%→50% 会回到同一批人 来源;GrowthBook 默认用 experiment key 作 seed;Google 把 layer 编进哈希。

拼接时用 \x1f 分隔、长度前缀,避免 ("ab","c") 与 ("a","bc") 的歧义;编码统一 UTF-8,ID 统一 trim、lowercase、NFC——Python 的 UTF-8 字节、JS 的 UTF-16 码元、Java 的代理对,都可能让同一字符串产生不同哈希。

空 ID 的处理,三家平台完全不同。

表 6-9 空 unit 的行为差异

平台 空 ID 行为 后果
GrowthBook hashValue == "" 时直接不入组 匿名流量不进实验,样本少但干净
Statsig 空 unitID 仍会被分桶 空 ID 全进同一桶,可能静默污染对照组
LaunchDarkly context value 为空时返回 0.0 永远落在第一个桶

来源:GrowthBook 来源;Statsig 来源;LaunchDarkly 来源。三种行为没有对错,但如果业务侧不 guard,空 ID 会静默地把所有匿名流量塞进对照组或第一桶;平台应把「空 ID 策略」做成显式配置,并在曝光日志里带上 is_empty_id 标记。

桶数与版本:一旦上线就不能悄悄改。 100 桶只能表达 1% 的粒度,10000 桶可以表达 0.01%;LaunchDarkly 用 100000 作权重分母,GrowthBook v2 和 Statsig 实验用 10000,Statsig 的 layer 用 1000。桶数不是越大越好:卡方拟合优度要求每桶期望频数 ≥5,10000 桶至少需要 5 万样本。工程折中是:权重用万分比整数存储,桶数固定 10000,永远不改。要改必须走「双写 + 对比 + 切换」:两套哈希都算但只用旧版结果,写进曝光日志跑 1–2 周,对比桶分布与指标差异,再灰度切换。直接改常量会让所有在线实验瞬间重洗。

扩量:coverage 可以单调,weights 不行。 这是分桶工程里最反直觉、也最值得写进规范的一条。GrowthBook 的 getBucketRanges 是这样切的:

cumulative = 0
for w in weights:
    start = cumulative
    cumulative += w
    ranges.push([start, start + coverage * w])

注意 start 是权重累加起点,不随 coverage 变化;只有区间右端随 coverage 缩放。以 50/50、coverage 0.5 为例,A 是 [0, 0.25),B 是 [0.5, 0.75);coverage 调到 1.0 后,A 是 [0, 0.5),B 是 [0.5, 1.0)。原来在 [0.5,0.75) 的 B 用户仍是 B,[0.25,0.5) 的用户从「未入组」变成 A——没有任何已入组用户翻转 来源。

但这个结论依赖「锚定式」切分:每个变体的起点由权重累加决定,coverage 只拉长右端。如果平台把区间整体连续缩放,扩量仍会移动边界;选型或自研时,必须把切分逻辑写成单元测试,而不是假设「扩量天然安全」。权重一变就不行了:50/50 → 70/30 时,A 的区间从 [0,0.5) 变成 [0,0.7),原本在 [0.5,0.7) 的 B 用户会翻成 A——在同一个 [0,1) 空间里改变占比,必然移动边界。

所以工程规范是:放量只改 coverage,不改 weights;必须改比例时,上新实验(新 salt)或开 sticky bucketing(把用户→变体映射持久化,配置变更时保持老用户分组);绝不在实验中途改桶数或哈希版本。 新实验意味着新 cohort,历史数据不能直接比;sticky 能保住体验,但实际比例会偏离计划值,分析时要按实际曝光比例做 SRM 检查。

曝光日志与 assignment 分开建模。 三个事件必须区分:assignment(分桶函数算出了变体,可以在用户还没看到任何东西时发生)、exposure(用户真的有机会看到变体)、metric(曝光后的行为)。三者是 eligible → assigned → exposed → converted 的漏斗,任何一层漏了都会变成 SRM 或稀释。最常见的错误是把 assignment 当曝光:只要调用 getAssignment 就打点,不管用户有没有进入实验路径;后果是大量「分配了但没看到」的用户被算进分母,效应被稀释。Eppo 的 assignment logger 只在 get<Type>Assignment 被调用时触发,建议把调用点放在「代码分叉处」;需要预取时用 Entry Point 在分析侧过滤 来源。

Google 的论文专门讨论了「触发」:实验可能分配了全部流量,但只有条件满足时才真正展示。只在触发时记录事实,对照组没有对应记录,就无法比较;正确做法是同时记录 factual 和 counterfactual(对照组「本可以被触发」时的行为),分析只在触发集合上进行。这就是 ITT 与 TAT 的取舍:ITT 无偏但稀释,TAT 更接近真实但曝光是事后变量。触发分析的价值在于把「曝光」定义成分配前就能确定的触发条件,既聚焦又保持随机性。

曝光表的主键应该是 (unit_id, experiment_key, config_version) 的第一次曝光,而不是每次渲染都写一行。重复曝光不只是存储膨胀:如果某一臂页面更慢、重试更多,重复行会更多,指标被系统性高估。Eppo 允许表里有重复行、分析时自动去重;同一个 subject 出现在多个变体里,直接移除 来源。这条规则应写进所有曝光表 ETL:一个 unit 在一个实验里只能有一个变体,多变体视为数据错误,不是「取最新」。

6.6 统计引擎:频率派#

统计引擎不是「选一个检验」,而是一条五层管线。很多平台把它做成 frequentist / Bayesian / sequential 三选一的下拉框,真正决定结果可信度的是下拉框背后的五层是否对齐。

表 6-10 统计引擎的五层

层 解决什么 典型实现 常见事故
指标语义 随机化单元、分析单元、曝光口径、聚合方式 用户级均值、比例、比率、分位数;winsorization 用户随机化却按 session 分析
估计器 点估计与 estimand 双样本比例 z、Welch t、Delta method、分位数、CUPED 比率指标当均值算
方差 估计不确定性 解析方差、Delta、cluster robust、bootstrap CUPED 点估计配未调整方差
有效性 结果是否可信 SRM、A/A、前置期平衡、多重比较、序贯 α SRM 不拦截、peeking 不校正
决策 是否上线/回滚 p 值/CI、chance-to-beat、expected loss、guardrail 把「显著」当「有效」

一条设计原则:估计器、方差和决策规则必须成对出现。CUPED 的点估计必须配 CUPED 的方差;序贯的 p 值必须配 always-valid 的置信区间;Bayesian 的后验必须配事先约定的决策阈值。平台上最常见的错误不是公式写错,而是把不同层的部件拼在一起。

转化率、留存率这类 0/1 指标,用双样本比例 z 检验。检验用 pooled 方差,CI 用 unpooled 方差:检验在原假设 p_T = p_C 下构造,CI 不在原假设下构造。数值例:各 5 万人、10% vs 10.5%,p_pool=0.1025,SE=0.001918,z=2.607,双侧 p=0.0091——5% 显著、1% 不显著。小样本或极端比例(期望频数 <5)改用 Fisher 或 Beta-Binomial 精确区间。

均值型指标用 Welch t,不假设两组方差相等,自由度用 Welch-Satterthwaite 近似;GrowthBook 官方明确用这套 来源。均值型指标的方差通常远大于比例指标:同样 5% 的相对提升,客单价所需样本可能是转化率的几倍到几十倍;这也是收入类指标必须做 CUPED 或 winsorization 的原因。

Delta method 是比率指标的正确打开方式。 人均 GMV = GMV / 用户数、CTR = 点击 / 曝光、客单价 = 收入 / 订单数,分子分母都随机,不能把比值当成普通均值。一阶近似是:

R = Ȳ / X̄
Var(R) ≈ (1/(n X̄²)) * [ Var(Y) - 2R*Cov(Y,X) + R²*Var(X) ]

数值例:10 万用户,人均收入 Ȳ=50 元,人均 session X̄=5,R=10 元/次;Var(Y)=900、Var(X)=4、Cov(Y,X)=1.5。代入得 Var(R)=0.000508,SE(R)=0.02254;忽略分母随机性会得到 0.01897,低估 15.8%,t 值高估约 19%。失效场景:分母接近 0 或为负时改用 Fieller 区间或 bootstrap;重尾先 winsorize;分母是「事件」而单元是「用户」时,必须先在用户级聚合再套公式 来源。

分位数指标(P90/P99 延迟、头部用户消费)的 estimand 是 Δ_ν = Q_T(ν) - Q_C(ν)。分位数没有闭式方差,工业界用「顺序统计量 + 二项分布」构造 CI;要估 P99 至少需要 n > 4p/(1-p) ≈ 396 个样本,P99.9 约需 4,000 个。工程限制:事件级 P50 与用户级 P50 可能差一倍(GrowthBook 例子是 2 与 5);含零/不含零、capping 都会改变结果;GrowthBook 明确分位数不支持 CUPED 和序贯,Eppo 也把 percentile 排除在 CUPED 外 来源。

表 6-11 指标类型与估计器

指标 估计器 方差 不能做什么
比例 双样本 z(pooled 检验 / unpooled CI) p(1-p)(1/n_T+1/n_C) 小样本正态近似
均值 Welch t s_T²/n_T + s_C²/n_C 重尾不做处理
比率 Delta method 一阶泰勒,含协方差 分母近 0/负
分位数 顺序统计量 + 二项 秩 CI CUPED/序贯
聚类 cluster 级或 CRVE DEFF / sandwich 少簇不校正

整条管线的顺序是:先 SRM,再估计,再方差缩减,最后决策规则。顺序反了,后面所有计算都建立在不可信样本上。

6.7 CUPED 与方差缩减#

CUPED(Controlled-experiment Using Pre-Experiment Data)的核心只有两步:找一个实验前就能观测、且与实验期指标高度相关的协变量 X,用回归系数把 Y 中可由 X 解释的部分扣掉。

θ = Cov(Y, X) / Var(X)
Y_cv = Y - θ * (X - X̄)
τ̂ = mean(Y_cv | T) - mean(Y_cv | C)

若 θ 已知,Var(Y_cv) = Var(Y)(1 - ρ²),其中 ρ = Corr(Y,X)。因此方差缩减比例是 ρ²,等效流量倍数是 1/(1-ρ²),MDE 缩小 sqrt(1-ρ²)。数值:ρ=0.5 → 方差缩减 25%、等效多 33% 流量、MDE 缩到 86.6%;ρ=0.7 → 缩减 49%、等效 1.96 倍、MDE 71.4%;ρ=0.3 → 只缩减 9%、等效 1.10 倍。这就是为什么 CUPED 对高频、强自相关的指标(活跃天数、停留时长、GMV)效果最好,对低频、偶发指标(首次购买、流失)效果有限:不是方法不行,是 ρ 上不去。

表 6-12 CUPED 家族

方法 协变量 模型 适合 代价
经典 CUPED 同一指标的前置期值 线性回归,单个 θ 高频、自相关指标 新用户/无历史指标无效
CUPAC 前置期指标 + 用户属性/行为 任意 ML 模型预测 Y 非线性、多源协变量 训练/推理复杂,过拟合风险
CUPED++ 多个前置期指标 + assignment properties 每个变体分别做 ridge,再用预测值调整 转化/留存等无前置期类比的指标;新用户 计算量大;Eppo 只在高层次结果页用
CURE 跨指标、跨人群的前置期信息 回归/机器学习扩展 新用户、非自相关指标 需要 warehouse-native 数据

同名不同物。 Statsig Cloud 版自动应用 CUPED,前置期是「每个用户曝光前 7 天」,没有前置期数据的用户用 stratification 分 strata 后组内估计再聚合 来源。GrowthBook 默认 14 天,做 CUPED + post-stratification,并排除分位数、bandit 目标比率、legacy ratio 来源。Eppo 的 CUPED++ 把多指标前置值和 assignment properties(≤100 个取值)放进 ridge,分别对每个变体拟合;计算量大,所以只在 metrics overview 页应用,模型每天更新一次 来源。对比平台时不能只问「支不支持 CUPED」,要问协变量、窗口、更新频率、哪些指标被排除。

数值示例。 沿用 6.6 的例子:基线 10%、实验组 10.5%、每组 5 万人,SE=0.1918pp,z=2.607。若 ρ=0.5,SE_cv=0.1661pp,z_cv=3.010,p≈0.0026——原本在 1% 水平不显著的结果,CUPED 后变成 1% 显著;等效流量从 10 万降到 7.5 万,MDE 从 0.532pp 降到 0.460pp。这个计算假设 ρ 已知且稳定;真实场景中 ρ 会随指标、人群、季节变化,上线前应用历史实验回测「方差缩减比例」,而不是看「p 值变小」。

判断:CUPED 不是免费午餐,是用数据工程换方差。 你要为每个用户、每个指标维护前置期聚合,保证前置期与实验期口径一致,还要处理新用户、指标变更、数据回填。没有数仓和指标治理的团队,CUPED 的维护成本会超过收益。

6.8 序贯检验与贝叶斯#

固定样本的 p 值只在一个预先定好的样本量上有效。如果你每天看、看到显著就停,实际假阳性率会远高于 5%。Evan Miller 的经典模拟:A/A 测试、真实转化率 50%、连续监控并在首次显著时停止,假阳性率约 26.1%,是名义 5% 的 5 倍多;如果偷看 10 次,想让实际显著性维持在 5%,单次报告的显著性要做到约 1% 来源。Optimizely 的模拟更激进:5,000 访客的 A/A 测试,若每个访客后都看一次,至少一次错误宣布赢家/输家的概率约 57%;每 500 人看一次约 26%,每 1,000 人看一次约 20%;用他们的 sequential 方法后降到约 3% 来源。这些数字依赖模拟设定,不能当成 universal constant,但方向是确定的:peeking 的代价随查看次数和停止规则放大。

Alpha spending / group sequential 预先定好 K 个看点,把总 α 按 spending function 分配。Pocock 早期更容易停,O'Brien-Fleming 早期极难停、后期接近 1.96,对最终功效损失最小。两看、α=0.05、t=0.5:OBF 的 α*(0.5)=0.00557,第一次需 z>2.77;Pocock 的 α*(0.5)=0.0310,第一次需 z>2.16。限制是只能在预定看点看:计划 3 次、第 4 次偷看并停,α spending 的保证就破了。

mSPRT 与 confidence sequence 不预设看点,任意时刻看都有效。mSPRT 把效应量当成先验分布,对每个可能效果计算似然比再混合;Statsig 给出完整 CI 公式,τ 是 mixing parameter,CI 始终比固定样本宽。Confidence sequence 用时间均匀的边界:Eppo 默认 Howard 等(2021)的 time-uniform CS,N_tune=10,000 来源;GrowthBook 用 Waudby-Smith 等(2023)的 asymptotic CS,N*=5,000,并明确 sequential CI 一致地宽于 fixed CI,N* 越接近决策样本量损失越小、且必须实验前固定 来源。Eppo 的 sequential hybrid 运行期用 sequential、结束切回 fixed,CI 约宽 10–15%。

表 6-13 五种读数方式的取舍

方法 允许的查看时点 能否早停 代价 适用
固定样本 只在预定样本量 否 最大功效 计划稳定、样本充足
Group sequential 只在预定 K 个看点 可以 少量功效损失;需提前设计 临床/高风险、中期分析
mSPRT / always-valid p 任意时刻 可以 CI 更宽;τ 需调 持续监控、早停收益大
Confidence sequence 任意时刻 可以 CI 更宽;N* 需调 同上,工程实现更简单
Bayesian 任意时刻(模型内) 可以,但决策规则要校准 先验敏感;频率派 error 无保证 低样本、决策者要概率读数

贝叶斯:先验、后验与决策规则。 转化率用 Beta-Binomial:先验 Beta(α0,β0),数据 s/f,后验 Beta(α0+s, β0+f)。数值:每组 1 万、10% vs 10.5%、均匀先验,P(p_T>p_C)≈87.9%,95% 可信区间约 [-0.34pp,+1.34pp],期望损失约 0.026pp。「87.9% 概率更好」和「CI 跨 0」不矛盾:CTW 只看方向,期望损失看幅度。

均值型指标用 Normal-Normal 共轭:后验精度是 1/τ² + 1/σ²,后验均值是先验与数据的精度加权;把后验均值写成 Δ_post = Δ̂ - [σ²/(σ²+τ²)](Δ̂ - μ0),就能看出「收缩」:数据越吵、先验越强,后验越向 μ0 收缩;样本足够大时,先验被数据淹没。决策规则有四种:chance to beat(P(Δ>0) ≥ 阈值)、expected loss(E[max(0,-Δ)] ≤ 阈值)、credible interval(95% CI 排除 0)、ROPE(P(|Δ|<δ) < ε)。常见错误是把「CTW = 95%」当成「有 95% 概率赚 5%」:前者只说明方向,不说明幅度;另一个错误是只看 CTW 不看 expected loss——一个 96% 概率微赚、4% 概率巨亏的变体,CTW 很好看,但期望损失可能不可接受。

先验选择分三档:弱先验/无信息先验(Statsig 默认 N(0, ∞);GrowthBook 开启 proper prior 时默认 N(0, 0.3²))、经验贝叶斯(用历史同类实验的 AVG(ATE) 作 μ0、SD(ATE) 作 τ)、强先验(同一功能在别的 segment 做过,但必须做敏感性分析)。Eppo 的官方文档在这里有一个值得警惕的不一致:统计细节页写贝叶斯先验是 N(0, 0.05²),分析方法页又描述为「50% 的实验提升落在 ±21%,95% 落在 ±62%」(约 σ≈0.31),两者相差 6 倍,存在不同说法;实际生效的先验以租户的 Statistical Analysis Plan 配置为准,上线前应导出一次后验参数做 sanity check。另外,GrowthBook 官方默认 Bayesian、可在 org/project 切换,这与不少二手评测把它写成「频率派平台」不一致,存在不同说法 来源。

三种范式不是三个引擎,而是三种决策规则。 固定样本控制「计划样本量下的错误率」,序贯控制「任意停止下的错误率」,贝叶斯给「给定先验和模型下的后验概率」。同一实验可以有三个读数,但只能有一个预注册的主决策规则;今天看频率派显著就 ship、明天看 CTW 只有 88% 就继续跑、后天看序贯 CI 跨 0 又停,这不是「综合判断」,是用不同模型做多次检验,实际 error rate 无法控制。

6.9 多重比较、SRM、功效#

同时看 10 个指标、5 个变体对比,就有 50 个检验;即使每个都无效应,至少一个显著的期望个数是 50×0.05=2.5。两类错误率要区分:FWER = P(至少一个假阳性),FDR = E[假阳性数 / 显著结果数]。三种常用校正:Bonferroni(p_i ≤ α/m)、Holm(排序后依次检验 p_(k) ≤ α/(m-k+1),遇到第一个不满足就停止)、BH(找最大的 k 使 p_(k) ≤ kα/m,拒绝前 k 个)。

数值例:m=10、α=0.05,p 值排序为 0.001, 0.008, 0.012, 0.030, 0.031, 0.045, 0.060, 0.120, 0.300, 0.700。Bonferroni 阈值 0.005,只拒绝第 1 个;Holm 第 1 个 0.001<0.005 拒绝,第 2 个 0.008>0.00556 停止,只拒绝 1 个;BH 在 k=3 时 0.012≤0.015、k=4 时 0.030>0.020,拒绝前 3 个。BH 明显更宽松,因为它控的是 FDR 而不是 FWER;适合探索性、指标多的场景。FWER 更适合「一个错误就可能让公司付出巨大代价」的确认性决策。

工业界的实现差异很大:Eppo 用「preferential Bonferroni」,主指标拿 γα/k,其余指标拿 (1-γ)α/[k(m-1)],好处是主指标的 power 不随「加了多少个次要指标」而下降 来源;GrowthBook 提供 Holm(FWER)和 BH(FDR),校正家族是「所有 Goal 指标 × 变体 × 维度值」,并明确说 adjusted p 值没有严格对应的 CI 来源;Optimizely 的 Stats Engine 把 sequential testing 和 FDR control 组合,2015 年官方对比称,相比 fixed-horizon,FDR<0.1 的变体约少 20%、结论性结果约少 39%(厂商自述,需独立验证);Statsig 也提供 Benjamini-Hochberg 过程。

「家族」怎么定,比用哪种校正更重要。 主指标单独一个家族,用最宽松的 α(或 preferential 权重);次要指标用 BH 控 FDR;guardrail 用 Holm/Bonferroni 控 FWER,因为假阴性比假阳性更危险;子群/维度切片单独一个家族,且优先看交互检验,而不是在每个子群里各做一次检验。

SRM(Sample Ratio Mismatch) 检验「观测到的各组样本量是否符合预期分配」。对 k 个变体,χ² = Σ(O_i - E_i)² / E_i,df = k-1。两组 50/50、总样本 100 万:观测 498,800 / 501,200,χ²=5.76、p=0.016,在 α=0.001 下不告警、在 α=0.05 下会告警;观测 497,000 / 503,000,χ²=36、p≈2×10⁻⁹,明确 SRM。在 100 万样本、50/50 下,α=0.001 对应的绝对偏差约 0.33pp(约 3,291 人),α=0.0005 约 0.35pp。大样本下很小的偏差也会显著,所以平台通常再加一个「绝对偏差」阈值。

Eppo 用 Pearson 卡方,α=0.001,并对维度 SRM 做 Bonferroni 校正;它明确说 SRM 检验不是 sequentially valid,每次刷新都跑会抬高实际 α,所以用更低的 0.001 来补偿 来源。Statsig 用卡方独立性检验,并给出分档告警:p<0.001 且偏差 >0.1% 绝对值是红色,0.001<p<0.01 是黄色;它还检查 crossover units,同一用户被曝光到多个变体超过 0.1% 就警告、超过 1% 建议联系支持 来源。微软的 SRM 论文用 p<0.0005 的保守阈值;第三方综述称微软在 10,000+ 实验中约 6% 出现 SRM(第三方数字,需谨慎引用)来源。

排查时把实验交付拆成四段:Assignment(哈希偏差、ID 不稳定、用户自选、ramp 中途改比例)、Execution(重定向延迟、崩溃、缓存、变体性能差异、曝光未打点)、Log processing(埋点丢失、join 丢失、去重差异、管道 bug)、Analysis(触发式分析、后处理过滤、用户 vs session 口径)。分配平衡但曝光不平衡,说明问题在 execution/logging,不在分桶。SRM 门禁应该:每次刷新都跑但用低 α;SRM 未通过时隐藏 treatment effect,只显示样本量和诊断;分维度 SRM 用 Bonferroni;分配 vs 曝光分开监控;按小时/天画比例曲线找第一个失衡点;A/A 常驻;不要用重加权「修复」——重加权只能调整可见计数,不能重建缺失用户,只有在根因明确、受影响人群可机械识别、且排除规则不是看了结果才定的情况下,才允许受限分析,否则重跑。

功效与 MDE。 两组等样本、均值型指标:n_per_arm = (z_{1-α/2}+z_{1-β})²(σ_T²+σ_C²)/Δ²;比例型把 σ² 换成 p(1-p)。数值:基线 10%、相对提升 5%、α=0.05 双侧、power 80%,n_per_arm ≈ 57,760,总样本约 115,520。若 ρ=0.5 的 CUPED,样本量乘 (1-ρ²)=0.75,约 43,320/组;若 cluster 随机化、m=50、ICC=0.05,DEFF=3.45,膨胀到约 199,300/组。固定每组 5 万人、基线 10%,80% power 下 MDE 约 0.532pp;要检测 3% 的相对提升,这个样本量不够。

序贯检验不是「免费早停」:同样样本量下 power 低于固定样本。Eppo 说 sequential hybrid 的 CI 比固定样本宽约 10–15%;GrowthBook 说 sequential CI 一致地宽于 fixed CI。具体样本量膨胀必须用平台自己的模拟校准,不能抄一个「序贯要多 20% 样本」的常数。

Cluster robust SE。 随机化发生在组织、学校、城市、骑手站点,而分析发生在用户/订单级时,同一 cluster 内的观测相关,i.i.d. 方差会低估标准误。DEFF = 1+(m-1)ρ_intra,n_eff = n/DEFF;m=50、ρ=0.05 时 DEFF=3.45,「10 万用户」只相当于「2.9 万独立用户」。两条路线:cluster 级分析(先算 cluster 均值/总和再做 t 检验;简单稳健,但 cluster 大小差异大时要加权)、CRVE(个体级回归 + sandwich 估计;cluster 数 <50 时向下偏,需要 t(G-1) 临界值或 wild cluster bootstrap)。GrowthBook 用「比率指标 + Delta method」吸收 cluster 结构,要求 organization_id 与 user_id 一对多 来源。

6.10 常见统计陷阱#

把陷阱按「设计—分流—统计—解释」四层排,比列一张 20 条的清单更有用:同一症状在不同层的处置完全不同。

表 6-14 常见陷阱与处置

层 陷阱 症状 根因 处置
设计 双边市场按用户随机 对照组也被污染,效应符号可能反转 违反 SUTVA cluster/switchback;先画干扰图
设计 session 分桶测留存 留存被严重稀释 随机化单元跨会话不稳定 改用 user/account 单元
设计 holdout 太小/太短 只有方向性,检不出小效应 功效由 holdout 组封顶 1%–5%、3–6 个月,或放粗阈值
设计 MAB 当测量仪 效应估计有偏 自适应分配破坏 i.i.d. MAB 只做优化,ATE 用固定分配
分流 assignment 当曝光 效应被稀释,样本量不够 打点位置太早 代码分叉处打点;触发分析
分流 复用 salt 两个实验分组高度相关 盐未按实验隔离 一实验一盐;2×2 卡方验证
分流 中途改权重/桶数 老用户翻转、SRM 爆发 区间边界移动 只改 coverage;改权重上新实验
分流 空 ID/机器人只落一侧 匿名流量全进第一桶 空值策略/过滤顺序 显式空 ID 策略;分流前过滤 bot
统计 比率指标当均值 SE 低估约 15.8% 分母随机 Delta method;先聚合到单元
统计 pooled 方差构造 CI CI 偏窄、显著性虚高 检验与 CI 用了同一方差 检验 pooled、CI unpooled
统计 CUPED 点估计配未调整方差 CI 错、p 值错 部件错配 估计器、方差、决策规则成对
统计 peeking/早停 假阳性 26%–57% 固定样本看多次 预注册;序贯;监控与决策分开
统计 SRM 后重加权 「修好」了比例,结论仍错 缺失用户无法重建 阻断分析、排查、重跑
解释 子群显著当异质性 假阳性、过度个性化 未做交互检验 交互检验;预注册少量子群
解释 显著当有效 上线后收益不达预期 效应量小、成本高、guardrail 受损 看效应量、CI、成本、guardrail
解释 早停效应量做预测 高估真实效应(winner's curse) 在显著时停 早停只做 ship/no-ship,不估效应

这张表可以压成三句话:设计层的错误无法用统计修;分流层的错误无法用 CUPED 修;统计层的错误无法用更多流量修。 平台的价值,是把这三层的前置校验做成默认路径,而不是等分析师在结果页发现异常。

6.11 对我们的启示#

如果把本章压缩成可执行的建议,是六条。

第一,平台抽象用「四对象 + 注册表 + 插件」,不要用「实验类型枚举」。 Assignment、Exposure、Schedule、Analysis 四个对象,配合随机化单元注册表(user/account/device/session/geo/market×time/query/conversation)和可版本化的分析插件(比例、Welch、Delta、分位数、CUPED、序贯、贝叶斯、CRVE),可以覆盖本章十种设计。每加一种实验类型,只是加一组配置和一个分析插件,而不是改一遍主流程。

第二,分桶做成独立基础库,而不是平台的一个模块。 这个库只做三件事:哈希、区间切分、金标测试;它应该被 SDK、服务端、离线复盘、日志校验共同依赖,任何业务代码都不允许自己写 hash % 100。配置 schema 里显式写死 salt、bucket_count、hash_version 三个字段,禁止运行时静默变更;多语言实现用同一份 JSON 测试向量,CI 不通过不允许发版。

第三,扩量只改 coverage,不改 weights。 这是最便宜的一致性保障。产品经理要「从 50/50 改成 70/30」时,平台应该默认引导「新建实验」,而不是允许原地改比例;如果必须原地改,强制开启 sticky,并在报表上标注「实际比例偏离」。绝不在实验中途改桶数或哈希版本;迁移走双写 + 对比 + 灰度。

第四,统计默认组合是「频率派 + Welch/Delta + CUPED + SRM 门禁」。 这四件事覆盖了大多数实验场景;序贯只用于 guardrail 监控和止损,不用于「宣布胜利」;贝叶斯作为可选读数,必须绑定先验配置和敏感性分析。多重比较按指标分层:主指标 preferential α、次要指标 BH、guardrail Holm、子群单独家族。所有配置(引擎类型、窗口、先验、校正方法、N*/τ、CUPED 协变量列表)写进结果快照,保证半年后可复现。

第五,流量架构从 3–5 个层起步,holdout 放在最上层。 建议一个 UI/交互层、一个算法/排序层、一个增长/营销层、一个发布层;每层预留 20–30% 空白流量给临时实验。holdout 用 1%–5%、3–6 个月,冻结后再测量;它不替代单实验分析,只回答「所有已上线改动的总和」。层数太多会让单实验样本不足,反而降低实验吞吐。

第六,能力路线分三段。 0–90 天:用户级 A/B/n + 正交分层 + 互斥域 + 曝光日志 + SRM 日报;90–180 天:CUPED + 序贯监控 + cluster 分配与 CRVE + holdout;180–365 天:switchback 调度器、interleaving 专用通道、HTE 交互检验。switchback 和 interleaving 不要包装成通用实验类型,它们是「专用设计器 + 分析模板」,先服务定价/派单和搜索/推荐团队。

验收标准只需四条:A/A 上名义 5% 的检验实际假阳性率不超过 5.5%;已知效应仿真上 power 与设计值相差不超过 2pp;CUPED 的方差缩减比例可复现;SRM 告警误报率低于 0.1%。这四条过了,统计引擎才算「能用」;否则功能列表再长,也只是报表。

最后是与其他章节的接口:本章定义的 Assignment、Exposure、Analysis 三张表,会在第 7 章的数据链路与平台架构中落成 schema;第 9 章的选型矩阵应把「默认统计方法、CUPED 窗口、SRM 阈值、分桶版本化、配置可导出」作为可验证项,而不是只勾「支持 CUPED」;第 10 章的 90 天 MVP 应以 6.11 的优先级为输入,先做「单元注册表 + 分桶库 + 曝光表 + SRM 门禁」这四件地基,再谈高级实验类型。

NOTE本页内容来自《AB 测试平台全网竞品与方案调研》2026-10 版。价格、融资与产品状态以文中标注日期为准;采购前请以供应商最新报价与合同为准。