智能体总选当前回报最高的动作,可能永远错过真正更好的选择;如果一直尝试未知动作,又会浪费已经学到的信息。探索与利用的矛盾,就是在“获取信息”和“使用信息”之间分配有限交互次数。

多臂老虎机去掉了完整强化学习中的状态转移和延迟回报,保留这组矛盾的最小形式。它很适合用来理解探索策略,因为每种方法为什么有效、又会在哪里失效,都能被直接观察。

1. 多臂老虎机模型

设有 k 个动作。每次选择动作 a,环境从该动作未知的奖励分布中给出奖励。动作的真实期望奖励记为 q*(a),智能体只能维护估计值 Q_t(a)

若动作 a 已被选择 N_t(a) 次,新奖励为 R_t,样本均值可以增量更新:

1
Q_{t+1}(a) = Q_t(a) + 1 / N_t(a) × [R_t - Q_t(a)]

括号中的差叫估计误差。这个公式不必保存全部历史奖励,每一步只需维护次数和当前均值。

除了平均奖励,还可以考察累积遗憾:每一步没有选择真实最优动作时,损失了多少期望奖励。

1
Regret(T) = Σ(q*(a*) - q*(A_t)),  t = 1 ... T

真实任务里通常不知道 q*,因此遗憾更适合模拟实验;线上系统会改用点击、转化、约束违反等可观测指标。

2. ε-greedy:给随机探索留一个固定入口

ε-greedy 以 1-ε 的概率选择当前估值最高的动作,以 ε 的概率随机选择:

1
2
概率 1 - ε:argmax Q(a)
概率 ε :随机动作

优点是实现简单,所有动作始终有机会被尝试。缺点也很直接:随机探索不区分“很少试过的动作”和“已经证明很差的动作”,即使估计已经稳定,固定 ε 仍会持续付出探索成本。

常见改进是让 ε 随时间衰减,但不要过快降到零。过早停止探索,早期噪声造成的错误排序可能再也无法被纠正。

3. 乐观初值:让未知本身具有吸引力

把所有 Q(a) 初始化为明显偏高的值,智能体使用纯贪心也会依次尝试动作:选过的动作在得到普通奖励后估值下降,尚未尝试的动作仍显得更好。

这种方法适合稳定环境中的早期探索,但它不是持续探索机制。所有动作试过之后,乐观性会逐渐消失;如果奖励分布后来变化,智能体不会自动恢复探索。

4. Softmax:按相对偏好分配概率

Softmax(Boltzmann)探索把估值转换为概率:

1
P(a) = exp(Q(a) / τ) / Σ exp(Q(b) / τ)

温度 τ 较高时,各动作概率接近;温度较低时,分布集中到高估值动作。它比 ε-greedy 更愿意探索“看起来次优但仍有希望”的动作,而不是平均随机。

实现时应先减去最大估值再计算指数,避免数值溢出。Softmax 的尺度也依赖奖励大小:同一个 τ 在奖励范围 [0, 1][0, 100] 下意义完全不同。

5. UCB:同时考虑估值与不确定性

Upper Confidence Bound(UCB)给每个动作一个探索奖励:

1
选择 argmax [Q_t(a) + c × sqrt(ln(t) / N_t(a))]

第一项利用当前估值,第二项偏向选择次数少的动作。随着总步数 t 增长,长期没被选择的动作会重新获得注意;随着 N_t(a) 增长,对该动作的不确定性奖励下降。

尚未尝试的动作分母为零,实际实现通常先让每个动作至少执行一次。系数 c 控制探索强度,它仍需要结合奖励尺度调整。

UCB 的价值在于把“为什么探索这个动作”写进指标:不是无差别随机,而是因为它的上限仍可能很高。在经典随机老虎机假设下,UCB1 还能得到对数级遗憾界;这依赖奖励独立、分布稳定等条件,不能不加检查地搬到任意复杂环境。

6. 四种策略怎样选择

策略 探索来源 优点 主要局限
ε-greedy 固定概率随机 简单、稳健、易作为基线 探索不看不确定性
衰减 ε 逐渐减少随机 后期探索成本较低 衰减过快会锁定错误动作
乐观初值 未尝试动作估值高 无需额外随机机制 非平稳环境中难以重新探索
Softmax 按相对估值采样 概率平滑、少选极差动作 对温度和奖励尺度敏感
UCB 置信上界 定向探索、理论清楚 假设较强,复杂场景估计不确定性困难

7. 一个可复现的纯 Python 实验

下面比较 ε-greedy 与 UCB。每次运行使用固定随机种子,并重复多个独立实验;环境奖励来自均值未知、方差相同的高斯分布。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
import math
import random
from statistics import mean


def choose_epsilon_greedy(estimates, epsilon, rng):
if rng.random() < epsilon:
return rng.randrange(len(estimates))
return max(range(len(estimates)), key=estimates.__getitem__)


def choose_ucb(estimates, counts, step, c):
for action, count in enumerate(counts):
if count == 0:
return action
scores = [
estimate + c * math.sqrt(math.log(step) / count)
for estimate, count in zip(estimates, counts)
]
return max(range(len(scores)), key=scores.__getitem__)


def run_once(strategy, seed, steps=2000):
rng = random.Random(seed)
true_values = [rng.gauss(0.0, 1.0) for _ in range(10)]
best_value = max(true_values)
estimates = [0.0] * len(true_values)
counts = [0] * len(true_values)
rewards = []
regret = 0.0

for step in range(1, steps + 1):
if strategy == "epsilon-greedy":
action = choose_epsilon_greedy(estimates, 0.1, rng)
else:
action = choose_ucb(estimates, counts, step, c=2.0)

reward = rng.gauss(true_values[action], 1.0)
counts[action] += 1
estimates[action] += (reward - estimates[action]) / counts[action]
rewards.append(reward)
regret += best_value - true_values[action]

return mean(rewards), regret


def evaluate(strategy, runs=200):
results = [run_once(strategy, seed) for seed in range(runs)]
return mean(x[0] for x in results), mean(x[1] for x in results)


for name in ("epsilon-greedy", "ucb"):
average_reward, cumulative_regret = evaluate(name)
print(name, round(average_reward, 3), round(cumulative_regret, 1))

这里固定种子是为了复现,而不是只挑对某个算法有利的一次运行。真正比较时还应报告不同随机种子之间的波动,并改变步数、奖励噪声和超参数,检查结论是否稳定。

8. 非平稳环境:旧经验需要逐渐过期

若动作的真实回报随时间改变,样本均值会让很久以前的数据持续占据同等权重。可改用固定步长 α

1
Q_{t+1}(a) = Q_t(a) + α × [R_t - Q_t(a)]

越近的奖励权重越大,估计能够跟踪变化。这时固定 ε 也不再只是浪费:持续探索可能帮助发现曾经较差、后来变好的动作。策略优劣始终与环境假设绑定。

9. 从老虎机走向完整强化学习

老虎机只优化即时奖励,没有状态转移。完整强化学习中的探索更难:一个动作可能眼下没有回报,却把智能体带到未来的重要状态;不同状态中的访问次数也不能简单共享。

价值型方法常沿用 ε-greedy,策略梯度方法通过随机策略产生探索,SAC 则把策略熵直接放进优化目标。无论方法多复杂,都应区分两件事:

  • 训练策略需要探索,以收集有信息的数据;
  • 评估策略通常关闭或固定探索噪声,以测量已经学到的能力。

如果还不熟悉状态、回报、Bellman 关系和 Q-learning,可先读 强化学习入门:从 MDP、价值函数到 Q-learning。进一步阅读可参考 Sutton 与 Barto 的教材页面Auer 等人的 UCB1 论文OpenAI Spinning Up 的 SAC 说明