每天中午打开外卖 App,你总面临同一个难题:那家吃了一个月的黄焖鸡味道稳定,可新开的那家川菜馆评分 4.9,万一更好吃呢?点熟悉的店,是“利用”——把确定的好处攥在手里;试试新店,是“探索”——冒险换取可能更高的回报。如果这个选择要重复整整一年,怎么点才最划算?这就是“多臂老虎机”(Multi-Armed Bandit, MAB)问题的本质:你面前有一排老虎机,每台的中奖率未知,如何一边试一边赌,让总收益最大?互联网公司恰好把这个问题用在了“流量分配”上——新老页面、推荐算法、广告物料到底该给多少流量、怎么分,本质上就是一次外卖级别的决策。这篇文章将带你认识三种主流解法:稳妥的 epsilon-greedy、乐观的 UCB、高效又优雅的 Thompson 采样,并聊聊它们如何落地成一套真正的智能流量分配系统。
掌握 MAB 能让你从“跑完 A/B 再下结论”的线性思维,升级为“边学边调、动态优化流量”的在线学习思维,这正是现代推荐系统和增长实验的核心能力。
目录
可视化演示
动态演示多臂老虎机MAB的核心机制,通过概览/流程/对比/趋势四种模式展示关键概念与交互流程。
本节配有交互动效(进入视口后自动加载,约 3KB)。
多臂老虎机MAB:多臂老虎 多臂老虎机问题模型与探索利用权 epsilon-greedy算 核心机制可视化 多臂老虎机MAB整体架构与关键组件
初识多臂老虎机:一顿外卖的抉择
假如你被派去开发一款外卖 App 的新用户推荐页,每天有 10 万次曝光机会,候选是三家不同风味的店铺。你不知道哪家最受欢迎,但每把一次展示浪费给差店,就损失一份用户好感——这和“多臂老虎机”场景一模一样。赌场里有一排老虎机,每台中奖概率未知,你手里只有有限金币,如何分配投币次数让赢钱最多?其中“手臂”(arm)就是选项,“中奖”就是收益(reward),而 MAB 的数学框架,正是研究“在信息不全时如何边试边选”的学问。
这个问题的关键不是“哪台机器最好”——那是上帝视角。真实世界只能靠一次次试验逼近真相,而每次试验都有成本:试了差机器,这枚金币就白花了。于是一对天生的矛盾出现了:探索能收集新信息,但牺牲眼前收益;利用能守住已知优势,但可能错过潜在的更好选项。学术界用“累计遗憾”量化这个代价:上帝告诉你最佳选项后,你原本能赚到的最大收益,与你实际赚到的之间的落差,就是遗憾。
MAB 的经典应用遍布互联网:推荐系统给新内容分配曝光量、广告平台决定展示哪版创意、电商平台调整商品首页位置。它们共享同一套逻辑——把流量当金币,把点击、转化率当收益,在线实时决定每个选项拿多少流量。遗憾的数学定义如下:
回到点外卖的场景,如果目标是一年里吃到的满意餐最多,那么“中午纠结一下”本质上就是在算遗憾:永远选对的那家是天花板,但现实里你需要用几次踩雷去换取发现神店的可能。后面三种算法,就是三套不同的“纠结策略”。
- 遗憾总量\(\text{Regret}_T\) 表示 \(T\) 轮决策之后,累计下来的遗憾总和。
- 理想收益上限\(T \mu^*\) 是假设每轮都选中最佳选项时,\(T\) 轮的总期望收益。
- 实际收益累计\(\sum_{t=1}^{T} \mu_{a_t}\) 是把每一轮实际选中的臂的均值加起来。
- 落差即遗憾理想减实际,差值越小说明策略越接近最优。
epsilon-greedy策略:偶尔尝鲜的稳妥派
小林是个保守的干饭人,他的原则是“九成把握加一成惊喜”:90% 的时间继续点自己最满意的那家店,剩下 10% 的时间,闭眼随机点一家没吃过的。这就是 epsilon-greedy 的处世哲学——用一个固定的概率 epsilon 做探索,其余时间全部用来利用当前看起来最好的选项。
算法每天维护两本“账本”:每家店被点过多少次 \(n_i\),以及累计获得的奖励(满意记 1,不满意记 0)。于是“最满意的那家”对应一个经验均值 \(\hat{\mu}_i = \text{累计奖励}_i / n_i\)。决策时生成一个随机数,小于 \(\epsilon\) 就探索(均匀随机选一家),否则利用(选均值最高的店)。写成数学形式:
收到奖励后,算法只需更新对应的 \(n_i\) 和累计奖励,下轮再算均值即可,实现非常简洁。参数 \(\epsilon\) 是性格旋钮:设成 0 变成纯利用,永远守着眼前最优,可能错过神店;设成 1 变成纯探索,天天随机踩雷。实际生产常取 0.1~0.2,或采用“衰减 epsilon-greedy”——初期多探索,后期多利用。
epsilon-greedy 就像一位“偶尔抽风的稳妥型干饭人”,简单管用,风险可控。但它的探索是乱枪打鸟——那 10% 的时间里,连已经验证过难吃的店也会被再次光顾,白白浪费金币。下一节的 UCB,就是一位“有脑子的探索者”。
- 决策变量\(a_t\) 表示第 \(t\) 次选择的是哪家店。
- 利用分支\(\arg\max_i \hat{\mu}_i\) 表示选出平均收益估计最高的那家店。
- 探索分支以概率 \(\epsilon\) 随机选一家,给未知选项一个机会。
- 分段决策整个大括号表示按概率在不同分支之间切换。
UCB置信上界:给未知加上“信用额度”
这位“有脑子的探索者”其实是个信用额度评估师。他还没吃过街角那家新开的火锅店,但会想:万一它是满分神店呢?于是先给每家店设一个“信得过的最高可能评分”——没吃过的店,额度拉到无限乐观;吃过的店,随着评价数据增多,额度慢慢回落到真实水平。每次出手,他选“信用额度最高”的那家。
这就是 UCB(Upper Confidence Bound,置信上界)的核心直觉:每个选项的价值不能只看平均收益,还要加上一个代表不确定性的“乐观加成”。没试过几次的店,我们不确定它到底多好,于是把这个加成抬得很高,吸引算法去试;试得多了,加成逐渐缩小,最终由真实平均收益主导决策。公式如下:
理解这个公式的关键在于“加成衰减的速度”:分母的 \(\sqrt{n_i}\) 随采样次数快速增大,每多试一次,我们对这家店的评价就越有底气;而分子的 \(\ln t\) 意味着“总时间越长,越值得再给未充分探索的店一次机会”。被冷落的店因为 \(n_i\) 很小而加成很大,迟早会被翻牌子,这就是 UCB 永不饿死任何臂的自我修养。
UCB 就像一位聪明的食客:新店因为“未知光环”被优先宠幸几次,但尝过发现一般后,信用额度迅速缩水,评分回归真实。相比 epsilon-greedy 的盲试,UCB 把探索资源精准投向“最值得怀疑”的选项,效率自然更高。
- 最优选择\(a_t^*\) 是第 \(t\) 次决策最终选中的臂。
- 平均收益估计\(\hat{\mu}_i\) 用历史数据估算出这家店的真实水平。
- 乐观加成项\(\sqrt{\frac{2\ln t}{n_i}}\) 对数据不足的店做“加分补偿”。
- 总评分排序均值与加成相加,选总和最大的店。
Thompson采样:贝叶斯高手的心里账本
还有一位“心里有本账”的贝叶斯信徒。他吃每顿饭前,心里都揣着一张“好吃程度分布图”:A 店吃了 20 次,15 次满意,分布图尖尖地堆在 0.75 附近;新店只吃过 2 次,1 次满意,分布图又矮又扁,从 0.1 到 0.9 都可能。他每次选择前,从每家店的分布里随机抽一个“可能是真实的成功率”,然后选抽出来的值最大的那家。
这就是 Thompson 采样,也叫贝叶斯采样。它假设每个选项的成功率服从 Beta 分布 \(\text{Beta}(\alpha, \beta)\),其中 \(\alpha\) 可以理解为“成功的次数 + 先验中的成功量”,\(\beta\) 是“失败的次数 + 先验中的失败量”。没有数据时,用中性的先验 \(\text{Beta}(1,1)\)(均匀分布);每得到一次成功就 \(\alpha+1\),失败就 \(\beta+1\)。随着数据积累,后验分布逐渐尖峰化,逼近真实成功率:
每次决策时为每家店独立抽一个 \(\theta_i\),然后选择 \(\theta\) 最大的店。抽样动作天然兼顾探索与利用:均值高的店,抽出来的值大部分时候都大,被选概率就高;但方差大的新店,偶尔会抽出一个极端大的值,从而获得被尝试的机会。相比 epsilon-greedy 的随机探索、UCB 的确定性上限,Thompson 用随机抽样把不确定性揉进决策,既不需要显式设置探索率,也不容易陷入局部最优。
这位贝叶斯信徒的可爱之处在于“越吃越有谱”:新店因为谱子宽,总有机会被翻牌;一旦数据积累,谱子变窄,好店稳定胜出,差店自然失宠。他不需要刻意规定“哪天探索”,因为每一次抽样本身,就是对未知做出概率上的尊重。
- 抽样对象\(\theta_i\) 是对第 \(i\) 家店“真实水平”的一次随机猜测。
- Beta 分布\(\text{Beta}(\alpha, \beta)\) 是一个只输出 0~1 之间值的分布,适合描述概率。
- 成功侧更新\(\alpha_i + s_i\) 把历史成功次数加进分布的左侧参数。
- 失败侧更新\(\beta_i + f_i\) 把历史失败次数加进分布的右侧参数。
- 抽样符号\(\sim\) 表示从右边的分布中随机抽取一个值。
策略对比选型:三位选手的擂台赛
三种干饭策略放在一起,就像公司的三个员工:epsilon-greedy 是执行力强的老实人,按固定比例轮换着试,稳定但笨拙;UCB 是精明的分析师,把每家的数据量算进评分,理性冷静;Thompson 是直觉派高手,心里装着分布,用运气模拟真相。
从收敛速度看,在真实推荐场景中,UCB 和 Thompson 通常比 epsilon-greedy 更快逼近最优选项,因为它们会把探索火力集中到“最有机会翻盘”的臂上,而不是均匀撒网。从实现复杂度看,epsilon-greedy 只需几行代码;UCB 需要维护累计次数、计算对数平方根;Thompson 需要引入 Beta 分布采样(现代框架里往往一行代码即可)。三者都不涉及复杂模型训练,都算轻量级选手。
选型有一个经验法则:系统极度冷启动、选项多且奖励噪声大时,Thompson 采样因为天然建模不确定性往往最稳;团队刚起步想快速验证,epsilon-greedy 几乎零门槛;追求严谨理论边界且环境不支持贝叶斯采样,UCB 是严谨之选。业界常采用“两段式启动”:先用 epsilon-greedy 收集几天数据,再切换 UCB 或 Thompson 精调。三种策略其实都可以统一到一个评分框架下:
说到底,三种策略都在回答同一个问题:“未知选项值不值得冒一次险?”老实人用固定概率回答,分析师用数学上限回答,贝叶斯高手用随机抽样回答。没有绝对王者,只有适合你餐厅客流——也就是业务场景的答案。
- 策略评分\(\text{Score}_i\) 是给每家店打的综合分,按分排序选最优。
- 经验均值\(\hat{\mu}_i\) 代表“已知的确定性收益”。
- 探索加成\(\text{Bonus}_i\) 是“未知的潜在收益”——UCB 用置信上界,Thompson 用随机采样。
工程落地实战:从算法到智能流量分配
把“点外卖的智慧”搬进公司,就是一套智能流量分配系统:首页 banner 有新旧两个方案,让 MAB 决定流量比例,而不是人工拍脑袋 5:5 对半分。系统像一个灵活的饭店领班——新菜单先给一桌客人试试,好评多了就加量,差评多了就撤下。
落地的第一步是定义“臂”和“收益”:臂是候选方案(新老页面、不同商品排序、多版广告文案),收益是要优化的业务指标(点击率、转化率、GMV)。第二步是流量切分——MAB 给出动态比例,而非固定分桶。早期让探索组流量大些,比如把 epsilon 从 0.3 慢慢衰减到 0.05。一个常用的衰减配方是:
工程上还有几个坑要避开:指标要选“可实时回流”的,算法才能快速更新;必须按唯一用户 ID 分配流量,防止同一用户反复被探索骚扰;收益要归一化,避免高价值用户权重失衡。上线前可以用历史日志做离线回放,模拟两种策略的收益差,再决定长期发布。系统运行后,还要定期监控每个臂的曝光量,防止某个臂因为探索不足被“饿死”。
这套系统就像一个越用越懂事的领班:新菜单先小范围试(探索),老菜单根据翻台率自动加量(利用),等哪道菜稳定火爆,领班就把它升为招牌——流量自动向最优方案倾斜。这就是“智能流量分配新范式”的真正含义。
- 当前探索率\(\epsilon_t\) 表示第 \(t\) 轮决策时用多大的概率探索。
- 初始探索率\(\epsilon_0\) 通常设为 0.2~0.3,保证冷启动阶段有足够尝试。
- 指数衰减\(e^{-\lambda t}\) 让探索率随时间逐渐缩水。
- 衰减速率\(\lambda\) 越大越早转向纯利用,需要根据业务节奏调。
AI 应用场景
推荐系统的冷启动流量分配
阶段:在线学习 / 模型上线
解决的问题:传统推荐系统对没有行为记录的新用户只能推热门内容,转化率低。MAB 可以把每个候选内容当作一个“臂”,用实时点击反馈动态调整曝光量,让新用户更快找到感兴趣的内容。
具体案例:某资讯 App 在新用户前 50 次曝光中引入 Thompson 采样,在“热点池”里选文章。每个文章维护一组 Beta 分布,点击则 \(\alpha+1\),未点击则 \(\beta+1\)。上线两周后,新用户次日留存提升 12%,人均点击文章数提升 23%。
广告落地页的快速优选
阶段:策略优化 / 创意优选
解决的问题:传统 A/B 测试一次只能对比一个落地页变体,周期长、流量浪费大。MAB 可以同时试跑多版落地页,快速淘汰差版本,把流量集中到赢家。
具体案例:某广告投放平台用 epsilon-greedy 在 5 版文案间分配流量,epsilon 从 0.3 随曝光次数衰减到 0.05。10 天内完成 3 轮迭代,最终点击率比固定人工分配提升 15%,且全程没有显著的流量浪费。
电商大促的 Banner 动态切量
阶段:流量调控 / 实时决策
解决的问题:大促期间用户偏好瞬息万变,人工拍板 banner 比例风险高。MAB 能每 30 分钟根据点击数据重新计算各 banner 的置信上界,动态调整展示比例。
具体案例:某电商平台在双 11 预热期用 UCB 管理 8 个活动 banner 的流量分配,配合实时监控大盘。相比手动固定比例,大促期间整体点击率提升 9%,GMV 提升约 8%。
Python 演示
import randomimport math class EpsilonGreedy: def __init__(self, n_arms, epsilon=0.1): self.n_arms = n_arms self.epsilon = epsilon self.counts = [0] * n_arms self.rewards = [0] * n_arms def select(self): # 以固定概率 epsilon 随机探索 if random.random() < self.epsilon: return random.randrange(self.n_arms) # 否则选平均收益最高的臂 best = 0 for i in range(1, self.n_arms): avg_i = self.rewards[i] / self.counts[i] avg_best = self.rewards[best] / self.counts[best] if avg_i > avg_best: best = i return best def update(self, arm, reward): self.counts[arm] += 1 self.rewards[arm] += reward class UCB1: def __init__(self, n_arms): self.n_arms = n_arms self.counts = [0] * n_arms self.rewards = [0] * n_arms def select(self): # 每个臂至少尝试一次 for i in range(self.n_arms): if self.counts[i] == 0: return i total = sum(self.counts) ucb = [0.0] * self.n_arms for i in range(self.n_arms): avg = self.rewards[i] / self.counts[i] bonus = math.sqrt(2 * math.log(total) / self.counts[i]) ucb[i] = avg + bonus best = 0 for i in range(1, self.n_arms): if ucb[i] > ucb[best]: best = i return best def update(self, arm, reward): self.counts[arm] += 1 self.rewards[arm] += reward def simulate(algorithm, n_arms, true_probs, n_steps): algo = algorithm(n_arms) total_reward = 0 for _ in range(n_steps): arm = algo.select() reward = 1 if random.random() < true_probs[arm] else 0 algo.update(arm, reward) total_reward += reward return total_reward if __name__ == "__main__": true_probs = [0.3, 0.55, 0.8] steps = 2000 random.seed(42) reward_eps = simulate(EpsilonGreedy, 3, true_probs, steps) reward_ucb = simulate(UCB1, 3, true_probs, steps) print("epsilon-greedy 累计奖励:", reward_eps) print("UCB1 累计奖励:", reward_ucb)
if random.random() < self.epsilon:抛硬币决定是否探索,概率由 epsilon 控制。avg_i = self.rewards[i] / self.counts[i]用累计奖励除以选择次数,估算每家店的平均收益。if avg_i > avg_best:找出当前看起来最好的店,作为利用对象。bonus = math.sqrt(2 * math.log(total) / self.counts[i])计算 UCB 的不确定性加成,试得越少加成越大。ucb[i] = avg + bonus平均收益加乐观加成,构成最终评分。reward = 1 if random.random() < true_probs[arm] else 0按真实成功率生成一次奖励,模拟用户点击。algo.update(arm, reward)把本次结果写回统计账本,供后续决策使用。
常见误区
误区MAB 不就是 A/B 测试的升级版吗?跑一段时间,看看哪版数据好,然后全量切换不就行了?
正解MAB 与 A/B 测试有本质区别。A/B 测试是离线决策:先均分流量,实验结束后做显著性检验,再一次性切换;MAB 是在线学习:没有“结束”时刻,它边分配流量边根据反馈动态调整比例,始终把更多流量导向当前表现好的方案。就像点外卖:A/B 测试是把所有人分成两组,固定吃 A 店和 B 店,两周后投票定胜负;MAB 则是每天都根据前一天的反馈重新决定几家店的点单比例,越吃越精准。
为何常见:两者都做流量实验和页面比较,表面上很像,工具和平台也常混着用,容易让人混淆。
误区epsilon 设得越大越好,多探索能发现更多好店,以后利用起来收益更高。
正解探索不是免费的。每次探索,如果试到差店,当次收益就损失了。epsilon=0.5 意味着半数流量随机浪费,即使发现了神店,前期亏损也难追回。行业经验常设 0.1~0.2,或采用衰减版本,让探索率随决策次数逐渐降低,既保留初见期的学习能力,又不至于长期浪费流量。
为何常见:人们常把探索等同于“见识多”,忽略了在固定预算下,每次尝试都有机会成本。
误区UCB 里的置信上界就是真实收益的数学上限,算出多少就绝不会超过。
正解UCB 的置信上界是从霍夫丁不等式等统计工具推导出的“乐观估计”,不是真实收益的精确边界。它更像银行给你的信用额度,不代表你真能赚那么多,只是“合理期待的上限”。当采样次数足够多时,这个额度会收窄到接近真实均值。
为何常见:术语叫“上界”,又和统计里的置信区间相近,让人误以为是数学上锁死的边界。
误区Thompson 采样用到贝叶斯,肯定要在服务器上跑马尔可夫链,又慢又重,生产环境扛不住。
正解Thompson 采样的实现非常轻量:Beta 分布的抽样只需要生成一个随机数,现代编程语言一行代码搞定,与 epsilon-greedy 的均值计算开销几乎相当。它被广泛部署在广告、推荐等毫秒级响应系统里。真正昂贵的是通用贝叶斯近似推断(如 MCMC),与 Thompson 采样用的共轭分布更新是两码事。
为何常见:看到“贝叶斯推断”就想到了 MCMC 等复杂算法,产生了不必要的性能恐惧。
面试题
Q1. MAB 问题要解决的核心矛盾是什么?
- A.计算开销与收益回报的权衡
- B.探索未知与利用已知的权衡← 正确答案
- C.过拟合与欠拟合的权衡
- D.特征选择与降维的权衡
答案:B。MAB 的核心矛盾是既想多试未知选项(探索)以发现更好的选择,又想守住已知最优(利用)以获取确定收益。A 是工程成本问题,C 是监督学习问题,D 是特征工程问题,都与 MAB 的本质无关。
Q2. 在 epsilon-greedy 中,若 epsilon 设为 0,代表什么?
- A.每次都随机尝试新店
- B.每次都选当前最优店← 正确答案
- C.永远选择评分最差的店
- D.按热度轮流点外卖
- E.已确认的收益估计值
- F.对未知的乐观估计加成
- G.探索次数的硬性上限
- H.用户原始偏好权重
答案:B。这项是一个随采样次数 \(n_i\) 增大而衰减的“不确定性加成”,衡量对该选项估计的置信程度:数据越少,加成越大,越值得一探。它不是收益的确认值,也不是硬性上限或用户偏好权重。
Q3. Thompson 采样的理论根基包括以下哪些?
- A.频率学派统计推断
- B.贝叶斯后验推断← 正确答案
- C.蒙特卡洛随机采样← 正确答案
- D.小批量梯度下降
答案:BC。Thompson 采样从贝叶斯后验分布中随机抽取参数,然后基于抽取结果做决策,随机抽取这一步体现出蒙特卡洛采样思想。频率学派和梯度下降与它的核心机制无关。
Q4. 以下哪种行动体现“探索”?
- A.继续点熟悉老店的外卖
- B.尝试评分未知的新店← 正确答案
- C.删除自己的历史订单
- D.只买销量榜首的商品
答案:B。探索的本质是在信息不足时尝试未知选项。B 是典型探索,A 和 D 是典型利用,C 与决策无关。
Q5. 关于 UCB 策略,下列说法正确的有哪些?
- A.置信区间随采样增加而收窄← 正确答案
- B.未采样的臂上界视为无穷← 正确答案
- C.总是选择置信下界最高的臂
- D.采样越多不确定性反而越大
答案:AB。UCB 会优先尝试未采样的臂(相当于上界无穷大),且已采样臂的置信区间随数据变多而收窄。UCB 选的是上界最高的臂而非下界最高,且采样越多不确定性越小,所以 C、D 错误。
Q6. 固定 epsilon 与衰减 epsilon 相比,以下说法正确的是?
- A.衰减版本后期更偏利用← 正确答案
- B.固定版本收敛速度更快
- C.两者实际效果完全相同
- D.衰减版本探索次数更多
答案:A。衰减 epsilon 的探索率随时间下降,后期更多选择当前最优,因而后期更偏利用、前期保留探索能力。固定 epsilon 全程保持相同探索率,收敛不一定更快,探索次数也不一定更少。
Q7. MAB 适用于以下哪些互联网场景?
- A.推荐系统的冷启动场景← 正确答案
- B.广告点击率的动态优化← 正确答案
- C.大数据量的离线备份
- D.新旧页面流量的分配← 正确答案
答案:ABD。冷启动、广告点击率优化、新旧页面流量切分都面临“未知选项 + 实时反馈 + 收益最大化”的 MAB 场景。离线备份是数据处理工程,没有在线决策与收益反馈。
Q8. A 店已验证 50 次、平均收益 0.6;B 店只试了 5 次,平均收益 1.0。UCB 可能选 B 店的原因?
- A.B 的可信上限高于 A 店← 正确答案
- B.B 的真实均值必然高于 A
- C.A 店采样过多应当停止
- D.UCB 完全忽略历史数据
答案:A。B 店只试了 5 次,不确定性加成很大,即使平均收益高,其置信上界也往往超过 A 店,所以 UCB 可能选 B。UCB 并不认为 B 的真实均值必然更高,也没有“采样过多应停止”的概念,更不会忽略历史数据。
Q9. 以下哪种方法不属于“探索与利用”的平衡策略?
- A.完全随机地选择选项← 正确答案
- B.固定比例混合探索利用
- C.乐观估计区间选择
- D.后验分布随机采样选择
答案:A。完全随机选择是纯探索,没有利用成分,不算平衡策略。B 是 epsilon-greedy,C 是 UCB,D 是 Thompson 采样,三者都在两者之间做了折中。