多臂老虎机问题入门:从‘摇臂’到代码,用Thompson Sampling搞定探索与利用的权衡
2026/6/1 20:22:05 网站建设 项目流程

多臂老虎机问题入门:从‘摇臂’到代码,用Thompson Sampling搞定探索与利用的权衡

想象你走进一家赌场,面前摆着五台老虎机。每台机器的中奖概率不同,但作为新手,你完全不知道哪台最慷慨。该把所有硬币投入第一台机器,还是轮流尝试?这就是多臂老虎机问题的核心——如何在探索未知选项利用已知最优解之间找到平衡。本文将用Python代码和可视化案例,带你理解Thompson Sampling如何像老练的赌徒一样,用数学优雅地解决这个难题。

1. 多臂老虎机:强化学习的"Hello World"

多臂老虎机(Multi-Armed Bandit)名称源自赌场中一排拉杆的老虎机。每个拉杆(臂)代表一个独立的选择,拉动后获得随机奖励。我们的目标是最大化N次尝试后的总收益。这看似简单的设定,却包含了**探索-利用困境(Exploration-Exploitation Dilemma)**这一强化学习核心问题。

举个现实例子:假设你是电商平台的推荐算法,面对:

  • 探索:给新用户推荐未经验证的新商品
  • 利用:继续推荐历史点击率高的商品

过度探索会浪费流量在低质量选项上,过度利用则可能错过潜在更优解。Thompson Sampling的魅力在于它能动态调整两者比例。

关键概念对照表

老虎机术语现实应用映射数学表示
摇臂可选择的行动方案动作(action)
奖励行动产生的收益随机变量X ~ P(r|a)
最优臂最佳策略argmax E[r|a]
累积遗憾与最优解的收益差距Σ(max E[r|a] - E[r|a_t])

2. Thompson Sampling的贝叶斯魔法

与ε-greedy等传统方法不同,Thompson Sampling采用概率反推的思路。其核心是:

  1. 为每个臂维护一个概率分布(通常用Beta分布)
  2. 每次从各分布随机采样一个值
  3. 选择采样值最大的臂
  4. 根据真实反馈更新分布参数
import numpy as np from scipy.stats import beta import matplotlib.pyplot as plt # 初始化三个臂的真实获胜概率(未知) true_probs = [0.3, 0.5, 0.7] # Beta分布参数 (α=成功次数+1, β=失败次数+1) priors = [[1, 1] for _ in true_probs] # 均匀先验 def thompson_sample(priors): samples = [beta(a, b).rvs() for a, b in priors] return np.argmax(samples) # 模拟1000次拉动 rewards = np.zeros(len(true_probs)) for _ in range(1000): chosen_arm = thompson_sample(priors) reward = np.random.binomial(1, true_probs[chosen_arm]) rewards[chosen_arm] += reward priors[chosen_arm][0] += reward priors[chosen_arm][1] += (1 - reward)

注意:Beta(1,1)等价于均匀分布,适合作为无信息的先验分布。随着数据积累,分布会逐渐集中到真实概率附近。

算法优势

  • 自动平衡:差臂的采样值大概率较小,但仍有探索机会
  • 计算高效:只需维护两个参数(α, β)
  • 适应性强:能处理非静态环境(变化概率)

3. 代码实战:可视化学习过程

让我们用Matplotlib动态展示Thompson Sampling的学习曲线:

plt.figure(figsize=(12, 8)) for i in range(len(true_probs)): x = np.linspace(0, 1, 200) plt.plot(x, beta(*priors[i]).pdf(x), label=f'Arm {i+1} (true={true_probs[i]})') plt.title('Beta分布随试验次数的演变') plt.legend(); plt.xlabel('获胜概率'); plt.ylabel('密度') plt.show()

随着试验次数增加,你会观察到:

  1. 最优臂(0.7)的分布越来越集中在右侧
  2. 次优臂(0.5)的分布保持较宽
  3. 最差臂(0.3)的分布逐渐左移

典型收敛过程

  • 前50次:频繁探索,各臂被选择次数相近
  • 50-200次:逐渐聚焦到0.7和0.5臂
  • 200次后:90%选择最优臂,偶尔验证其他臂

4. 高级技巧与工程实践

4.1 处理非静态环境

真实场景中,老虎机的概率可能随时间变化。解决方法:

# 添加遗忘因子 def update_with_forgetting(priors, arm, reward, gamma=0.99): priors[arm][0] = gamma * priors[arm][0] + reward priors[arm][1] = gamma * priors[arm][1] + (1 - reward)

4.2 上下文老虎机

当选择依赖额外信息时(如用户特征),可用:

from sklearn.linear_model import LogisticRegression class ContextualBandit: def __init__(self, n_arms): self.models = [LogisticRegression() for _ in range(n_arms)] def predict(self, context): samples = [model.predict_proba(context)[0][1] for model in self.models] return np.argmax(samples)

4.3 超参数调优

关键参数对效果的影响:

参数过高影响过低影响推荐范围
初始α探索不足收敛慢0.5-2
初始β探索过度过早收敛0.5-2
遗忘因子γ过度响应噪声无法适应变化0.9-0.999

在实际项目中,我发现先用小规模模拟实验(如100臂)快速验证参数效果,再应用到生产环境是最稳妥的做法。曾经有个A/B测试系统因为初始α设置过大,导致新选项几乎得不到曝光,损失了前两周的潜在收益。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询