探索与利用权衡:ε-greedy、UCB、Thompson Sampling
一句话概述
探索与利用(Exploration vs Exploitation)是强化学习的核心矛盾——利用是"做已知最好的事",探索是"尝试未知的事"。ε-greedy用简单的概率来平衡,UCB用不确定性来指导探索,Thompson Sampling用贝叶斯后验来采样。这个权衡决定了智能体是"保守的守成者"还是"冒险的探索者",直接影响学习效率和最终表现。
💡 核心要点:①探索-利用困境是多臂老虎机(Multi-armed Bandit)问题的核心,也是RL的基础挑战;②ε-greedy最简单——以概率ε随机探索,以概率1-ε选择最优;③UCB(置信上界)基于"乐观面对不确定性"原则,给探索少的动作一个"加分";④Thompson Sampling从贝叶斯后验分布中采样,天然平衡探索与利用。
教学与演示
一、多臂老虎机——探索与利用的经典问题
是什么(定义):多臂老虎机(Multi-armed Bandit)问题是一个简化的序列决策问题:有K个"手臂"(动作),每个手臂有一个未知的奖励分布。每次你拉一个手臂,获得一个随机奖励。目标是在T次拉动中最大化累积奖励。这个问题没有状态转移,只有动作选择,是探索-利用权衡的最纯粹形式。
大白话 想象你面前有K台老虎机,每台的中奖概率不同但你不知道。你的目标是玩100次后赢最多的钱。你是应该"专一"地玩看起来最好的那台(利用),还是"花心"地每台都试试(探索)?如果太早锁定一台,可能错过了更好的;如果一直试来试去,可能浪费了太多机会在烂机器上。
为什么(原理):多臂老虎机问题虽然简单,但它是理解探索-利用权衡的最佳模型。在RL中,智能体面临的每个状态都可以看作一个"情境老虎机"(Contextual Bandit)——在给定状态下,选择哪个动作类似于在给定情境下选择哪个手臂。因此,老虎机问题的探索策略(ε-greedy、UCB、Thompson Sampling)可以直接应用于RL。
怎么做(实现):
import numpy as np
# ==================== 多臂老虎机模拟 ====================
# 10台老虎机,每台有不同的中奖概率
np.random.seed(42)
n_arms = 10
true_probs = np.random.beta(2, 5, n_arms) # 真实中奖概率(偏低的Beta分布)
print("=== 多臂老虎机 ===")
print(f"{n_arms}台老虎机的真实中奖概率:")
for i, p in enumerate(true_probs):
print(f" 手臂{i}: {p*100:.1f}%")
best_arm = np.argmax(true_probs)
print(f"最优手臂是 #{best_arm},中奖概率 {true_probs[best_arm]*100:.1f}%")
# 模拟拉手臂
def pull_arm(arm):
"""拉一次手臂,返回奖励(0或1)"""
return 1 if np.random.random() < true_probs[arm] else 0
# 仅利用策略:估计每个手臂的概率,然后只拉最好的
print("\n=== 仅利用(贪心)策略 ===")
estimates = np.zeros(n_arms) # 估计概率
counts = np.zeros(n_arms) # 拉过的次数
# 先每台拉1次作为初始探索
for arm in range(n_arms):
r = pull_arm(arm)
estimates[arm] = r
counts[arm] = 1
total_reward = n_arms # 初始探索的奖励
for step in range(n_arms, 100):
best = np.argmax(estimates)
r = pull_arm(best)
total_reward += r
counts[best] += 1
estimates[best] += (r - estimates[best]) / counts[best]
print(f"仅利用策略: 100次拉动总奖励={total_reward}, 最优手臂#{best_arm}被拉{counts[best_arm]}次")
print(f"如果知道最优手臂,100次拉动期望奖励≈{true_probs[best_arm]*100+10:.0f}")
什么用(应用):多臂老虎机问题直接应用于A/B测试、在线广告投放、推荐系统的冷启动。在RL中,探索策略(ε-greedy)是DQN、Q-learning等算法的标准组件。Contextual Bandit(上下文老虎机)是推荐系统和在线广告的核心模型。
哪些坑(缺点):老虎机问题假设没有状态转移,这与MDP不同;贪心策略可能永远锁定在次优手臂上(如果初始估计偏差);探索策略的选择直接影响学习效率和最终表现。
二、ε-greedy——最简单的探索策略
是什么(定义):ε-greedy策略以概率ε随机选择一个动作(探索),以概率1-ε选择当前估计价值最高的动作(利用)。ε通常从较大值(如1.0)开始,随着学习进行逐渐衰减(如到0.01),即"先广泛探索,再专注利用"。
大白话 ε-greedy就像"偶尔任性"——大部分时间(1-ε)你按照"经验"选最好的,但偶尔(ε)你随机选一个试试。ε从大到小就像"从孩子到大人"的过程——小时候什么都想试试,长大了越来越保守。
为什么(原理):ε-greedy的优点是极其简单,不需要任何额外的统计信息。但它有一个致命缺陷:即使某个动作已经被证明非常差,它仍然有ε/n的概率被选中——探索是"盲目的"。这导致ε-greedy的遗憾是O(T)(线性增长),在理论上不如UCB和Thompson Sampling。
怎么做(实现):
import numpy as np
# ==================== ε-greedy 策略的完整实现 ====================
np.random.seed(42)
n_arms = 10
true_probs = np.random.beta(2, 5, n_arms)
def pull_arm(arm):
return 1 if np.random.random() < true_probs[arm] else 0
class EpsilonGreedy:
"""ε-greedy策略"""
def __init__(self, n_arms, epsilon=0.1, decay=0.999, min_eps=0.01):
self.n_arms = n_arms
self.epsilon = epsilon # 当前ε
self.decay = decay # 衰减系数
self.min_eps = min_eps # 最小ε
self.estimates = np.zeros(n_arms) # Q值估计
self.counts = np.zeros(n_arms) # 每个动作被选次数
def select_action(self):
"""选择动作:ε概率随机,1-ε概率贪心"""
if np.random.random() < self.epsilon:
return np.random.randint(self.n_arms) # 探索
else:
return np.argmax(self.estimates) # 利用
def update(self, action, reward):
"""更新估计值(增量式平均)"""
self.counts[action] += 1
# 增量更新:新估计 = 旧估计 + (奖励 - 旧估计) / 次数
self.estimates[action] += (reward - self.estimates[action]) / self.counts[action]
# 衰减ε
self.epsilon = max(self.min_eps, self.epsilon * self.decay)
# 运行对比实验
def run_experiment(strategy, n_steps=1000):
rewards = []
optimal_actions = 0
best_arm = np.argmax(true_probs)
for step in range(n_steps):
action = strategy.select_action()
reward = pull_arm(action)
strategy.update(action, reward)
rewards.append(reward)
if action == best_arm:
optimal_actions += 1
return rewards, optimal_actions
# 固定ε vs 衰减ε
eg_fixed = EpsilonGreedy(n_arms, epsilon=0.1, decay=1.0) # ε不变
eg_decay = EpsilonGreedy(n_arms, epsilon=1.0, decay=0.995) # ε衰减
rewards_fixed, opt_fixed = run_experiment(eg_fixed)
rewards_decay, opt_decay = run_experiment(eg_decay)
print("=== ε-greedy 策略对比 ===")
print(f"固定ε=0.1: 累积奖励={sum(rewards_fixed)}, 选最优动作{opt_fixed}次({opt_fixed/10:.1f}%)")
print(f"衰减ε=1.0→min: 累积奖励={sum(rewards_decay)}, 选最优动作{opt_decay}次({opt_decay/10:.1f}%)")
print(f"最优手臂真实概率: {true_probs[np.argmax(true_probs)]*100:.1f}%")
print(f"期望最优奖励≈{true_probs[np.argmax(true_probs)]*1000:.0f}")
print("\n衰减ε策略:前期大量探索,后期专注利用,总奖励更高")什么用(应用):ε-greedy是DQN、Q-learning等深度RL算法的默认探索策略。在Atari游戏DQN中,ε从1.0线性衰减到0.1(或0.01),智能体先在游戏里"乱玩"收集经验,然后逐渐利用学到的策略。在推荐系统中,ε-greedy用于平衡"推荐热门内容"和"探索用户新兴趣"。
哪些坑(缺点):探索是盲目的——即使某个动作已知很差,也有ε/|A|的概率被选中;ε衰减过快可能导致探索不足,过早锁定次优策略;ε衰减过慢则浪费太多时间在探索上;ε-greedy不考虑动作的不确定性,所有动作的探索概率相同。
三、UCB——基于不确定性的探索
是什么(定义):UCB(Upper Confidence Bound,置信上界)策略的核心思想是"乐观面对不确定性"——对于每个动作,我们不仅看它的估计价值,还加上一个"探索奖励"(bonus)。这个奖励与动作被选择的次数成反比:被选得越少的动作,bonus越大。动作选择规则:A_t = argmax_a [Q_t(a) + c·√(ln t / N_t(a))]。
大白话 UCB就像一个"乐观主义者"——对于没怎么试过的动作,它总是往好处想:"说不定这个动作特别好呢?"所以给它们一个"加分"。试得越多,加分越少。这样既不会错过好动作,也不会一直浪费在烂动作上。它比ε-greedy聪明的地方在于:探索是"有目的性的"——只探索"不确定性大"的动作。
为什么(原理):UCB的数学基础是Hoeffding不等式——它给出了样本均值偏离真实均值的概率上界。UCB的"探索奖励"就是Hoeffding置信区间的宽度。选择"估计值+置信上界"最大的动作,等价于"乐观地认为每个动作都在其置信区间的上界"。这种策略的遗憾是O(log T),理论上远优于ε-greedy的O(T)。
怎么做(实现):
import numpy as np
np.random.seed(42)
n_arms = 10
true_probs = np.random.beta(2, 5, n_arms)
def pull_arm(arm):
return 1 if np.random.random() < true_probs[arm] else 0
class UCB:
"""UCB策略"""
def __init__(self, n_arms, c=2.0):
self.n_arms = n_arms
self.c = c # 探索系数
self.estimates = np.zeros(n_arms) # Q值估计
self.counts = np.zeros(n_arms) # 被选次数
self.total_steps = 0 # 总步数
def select_action(self):
self.total_steps += 1
# 先确保每个动作至少被选一次
not_tried = np.where(self.counts == 0)[0]
if len(not_tried) > 0:
return not_tried[0]
# UCB公式:argmax_a [Q(a) + c * sqrt(ln(t) / N(a))]
ucb_values = self.estimates + self.c * np.sqrt(
np.log(self.total_steps) / self.counts
)
return np.argmax(ucb_values)
def update(self, action, reward):
self.counts[action] += 1
self.estimates[action] += (reward - self.estimates[action]) / self.counts[action]
# 运行UCB
ucb = UCB(n_arms, c=2.0)
rewards_ucb = []
best_arm = np.argmax(true_probs)
opt_count = 0
for step in range(1000):
action = ucb.select_action()
reward = pull_arm(action)
ucb.update(action, reward)
rewards_ucb.append(reward)
if action == best_arm:
opt_count += 1
print("=== UCB 策略 ===")
print(f"累积奖励: {sum(rewards_ucb)}")
print(f"选最优动作次数: {opt_count} ({opt_count/10:.1f}%)")
print(f"各动作估计值 vs 真实值:")
for i in range(n_arms):
bonus = ucb.c * np.sqrt(np.log(ucb.total_steps) / max(ucb.counts[i], 1))
print(f" 手臂{i}: 估计={ucb.estimates[i]:.4f}, 真实={true_probs[i]:.4f}, "
f"次数={int(ucb.counts[i])}, UCB bonus={bonus:.4f}")
print(f"\nUCB的优势:探索奖励随次数递减,")
print(f" 被选次数少的动作有更大的bonus,被选次数多的动作bonus小")什么用(应用):UCB在在线广告、推荐系统、A/B测试中广泛应用。在RL中,UCB的变体(如Bootstrapped DQN)用于深度探索。UCB的思想也启发了"好奇心驱动探索"——给"惊讶"的状态更多的探索奖励。在蒙特卡洛树搜索(MCTS)中,UCB1(UCT算法)用于选择搜索分支。
哪些坑(缺点):UCB假设奖励是有界的,对于无界奖励需要调整;探索系数c的选择需要调参;在非平稳环境(奖励分布随时间变化)中,UCB的"重选惩罚"机制不适用;对于连续动作空间,UCB难以直接应用。
四、Thompson Sampling——贝叶斯视角的探索
是什么(定义):Thompson Sampling(汤普森采样)是一种贝叶斯探索策略。它为每个动作维护一个奖励分布的后验分布(而非点估计),每次选择动作时,从每个动作的后验分布中采样一个值,然后选择采样值最大的动作。自然地在探索和利用之间取得平衡。
大白话 Thompson Sampling就像一个"赌徒"——它不直接说"这个动作好",而是说"这个动作有70%概率好,30%概率差"。每次决策时,它从这个概率分布中随机抽一个值,然后选抽到值最大的动作。如果某个动作的数据少,分布就宽,有时会抽到高值,自然就去探索了。
为什么(原理):Thompson Sampling的贝叶斯性质使得它能够自然地量化不确定性。每个动作被选中的概率等于"该动作是最优动作"的后验概率。这意味着:如果数据充分证明某个动作最优,它几乎总被选中;如果数据不足,最优动作不确定,其他动作也有机会被选中。Thompson Sampling在理论上和实践中都表现优异。
怎么做(实现):
import numpy as np
np.random.seed(42)
n_arms = 10
true_probs = np.random.beta(2, 5, n_arms)
def pull_arm(arm):
return 1 if np.random.random() < true_probs[arm] else 0
class ThompsonSampling:
"""Thompson Sampling策略(Beta-Bernoulli模型)"""
def __init__(self, n_arms):
self.n_arms = n_arms
# Beta分布的参数:α=成功次数+1, β=失败次数+1
# 先验:Beta(1,1) = 均匀分布
self.alphas = np.ones(n_arms) # 成功次数 + 1
self.betas = np.ones(n_arms) # 失败次数 + 1
def select_action(self):
"""从每个动作的后验分布中采样,选最大的"""
samples = np.random.beta(self.alphas, self.betas)
return np.argmax(samples)
def update(self, action, reward):
"""更新后验分布"""
if reward > 0:
self.alphas[action] += 1 # 成功
else:
self.betas[action] += 1 # 失败
# 运行Thompson Sampling
ts = ThompsonSampling(n_arms)
rewards_ts = []
best_arm = np.argmax(true_probs)
opt_count = 0
for step in range(1000):
action = ts.select_action()
reward = pull_arm(action)
ts.update(action, reward)
rewards_ts.append(reward)
if action == best_arm:
opt_count += 1
print("=== Thompson Sampling 策略 ===")
print(f"累积奖励: {sum(rewards_ts)}")
print(f"选最优动作次数: {opt_count} ({opt_count/10:.1f}%)")
print(f"\n各动作的后验分布(Beta分布):")
for i in range(n_arms):
mean = ts.alphas[i] / (ts.alphas[i] + ts.betas[i])
std = np.sqrt(ts.alphas[i] * ts.betas[i] /
((ts.alphas[i] + ts.betas[i])**2 * (ts.alphas[i] + ts.betas[i] + 1)))
print(f" 手臂{i}: Beta({ts.alphas[i]:.0f},{ts.betas[i]:.0f}), "
f"均值={mean:.4f}, 标准差={std:.4f}, 真实={true_probs[i]:.4f}")
print(f"\nThompson Sampling的优势:")
print(f" 不确定性大的动作(数据少),Beta分布宽,有机会被采样到")
print(f" 确定性高的动作(数据多),Beta分布窄,稳定地采样到其均值附近")什么用(应用):Thompson Sampling在在线广告、新闻推荐、A/B测试中广泛使用。在RL中,Bootstrapped DQN可以看作Thompson Sampling的深度版本——用多个Q网络头的分布来近似后验分布。在推荐系统中,Thompson Sampling用于平衡"探索用户新兴趣"和"推荐已知偏好"。
哪些坑(缺点):需要选择合适的先验分布和似然模型;对于复杂奖励分布,后验更新可能没有闭式解,需要近似推理(如MCMC);在深度RL中,维护完整的后验分布计算成本高;先验的选择会影响早期探索行为。
五、探索策略在RL中的应用——从Bandit到MDP
是什么(定义):在RL中,探索策略需要从Bandit问题推广到MDP。核心区别在于:MDP中的探索不仅影响即时奖励,还影响未来访问的状态分布。深度RL中的探索方法包括:ε-greedy(DQN)、熵正则化(SAC)、好奇心驱动探索(ICM)、参数噪声(Parameter Noise)等。
大白话 在Bandit中,探索就是"试试不同的动作"。在MDP中,探索更复杂——你需要探索的不仅是动作,还有"状态"本身。你可能需要故意走一些"弯路"来发现新的区域。这就是为什么在Atari游戏中,DQN一开始需要用ε-greedy"乱玩"来收集经验。
为什么(原理):MDP中的探索面临两个额外挑战:(1) 探索动作可能导致智能体进入之前从未访问过的状态,带来新的学习机会;(2) 探索的代价不仅仅是"少拿了一些奖励",还可能"掉入陷阱"导致episode提前结束。因此,深度RL中的探索策略通常需要更精巧的设计。
怎么做(实现):
import numpy as np
# ==================== RL中的探索策略对比 ====================
# 在网格世界上比较不同探索策略
n_states = 9
n_actions = 4
actions = [(-1, 0), (1, 0), (0, -1), (0, 1)]
def step(state, action):
row, col = state // 3, state % 3
dr, dc = actions[action]
nr = max(0, min(2, row + dr))
nc = max(0, min(2, col + dc))
next_state = nr * 3 + nc
if next_state == 8: r = 10.0
elif next_state == 7: r = -5.0
else: r = -0.1
return next_state, r
def q_learning_with_exploration(strategy_name, n_episodes=300, alpha=0.1, gamma=0.9):
"""Q-learning配合不同探索策略"""
Q = np.zeros((n_states, n_actions))
counts = np.zeros((n_states, n_actions)) # 用于UCB
total_steps = 0
episode_rewards = []
for episode in range(n_episodes):
state = 0
ep_reward = 0
while state != 8 and state != 7:
total_steps += 1
# 根据策略名称选择动作
if strategy_name == "egreedy":
epsilon = max(0.05, 1.0 / (episode + 1))
if np.random.random() < epsilon:
action = np.random.randint(n_actions)
else:
action = np.argmax(Q[state])
elif strategy_name == "ucb":
not_tried = np.where(counts[state] == 0)[0]
if len(not_tried) > 0:
action = not_tried[0]
else:
c = 2.0
ucb_vals = Q[state] + c * np.sqrt(np.log(total_steps+1) / counts[state])
action = np.argmax(ucb_vals)
elif strategy_name == "greedy":
action = np.argmax(Q[state])
# 执行动作
next_state, reward = step(state, action)
counts[state][action] += 1
# Q-learning更新
best_next = np.max(Q[next_state])
Q[state][action] += alpha * (reward + gamma * best_next - Q[state][action])
ep_reward += reward
state = next_state
episode_rewards.append(ep_reward)
return episode_rewards
np.random.seed(42)
rewards_eg = q_learning_with_exploration("egreedy")
rewards_ucb = q_learning_with_exploration("ucb")
rewards_greedy = q_learning_with_exploration("greedy")
print("=== Q-learning + 不同探索策略 ===")
print("前10个episode的奖励对比:")
print(f"{'Episode':<10} {'ε-greedy':<12} {'UCB':<12} {'Greedy':<12}")
for ep in range(10):
print(f"{ep+1:<10} {rewards_eg[ep]:>8.1f} {rewards_ucb[ep]:>8.1f} {rewards_greedy[ep]:>8.1f}")
print(f"\n最后10个episode的平均奖励:")
print(f" ε-greedy: {np.mean(rewards_eg[-10:]):.2f}")
print(f" UCB: {np.mean(rewards_ucb[-10:]):.2f}")
print(f" Greedy: {np.mean(rewards_greedy[-10:]):.2f}")
print(f"\n贪心策略没有探索,可能永远找不到最优路径")
print(f"ε-greedy和UCB通过探索找到了更好的策略")什么用(应用):探索策略是RL算法的重要组成部分。在DQN中,ε-greedy配合经验回放实现稳定学习;在SAC中,最大熵框架自动鼓励探索;在ICM(Intrinsic Curiosity Module)中,好奇心驱动探索让智能体在没有外部奖励时也能学习;在AlphaGo中,MCTS内置的探索机制平衡了广度和深度。
哪些坑(缺点):ε-greedy在深度RL中探索效率低(需要大量随机交互);UCB难以扩展到高维动作空间;Thompson Sampling需要维护不确定性估计,在深度RL中计算成本高;探索策略的选择需要根据具体任务调参。
六、实战:三种探索策略的全面对比
是什么(定义):本节将三种经典探索策略(ε-greedy、UCB、Thompson Sampling)在同一个多臂老虎机问题上进行系统对比,从累积奖励、遗憾曲线、最优动作选择率等多个维度评估它们的表现。
大白话 我们来当一回"裁判",让三种探索策略在同场竞技,看看到底谁更聪明。通过对比实验,你会直观地感受到"盲目探索"和"智能探索"的巨大差距。
怎么做(实现):
import numpy as np
np.random.seed(42)
n_arms = 10
true_probs = np.random.beta(2, 5, n_arms)
best_arm = np.argmax(true_probs)
def pull_arm(arm):
return 1 if np.random.random() < true_probs[arm] else 0
# 运行多次实验取平均
def run_multiple(strategy_class, n_runs=50, n_steps=1000):
all_rewards = np.zeros((n_runs, n_steps))
all_optimal = np.zeros((n_runs, n_steps))
for run in range(n_runs):
strategy = strategy_class(n_arms)
for step in range(n_steps):
action = strategy.select_action()
reward = pull_arm(action)
strategy.update(action, reward)
all_rewards[run][step] = reward
all_optimal[run][step] = 1 if action == best_arm else 0
return all_rewards.mean(axis=0), all_optimal.mean(axis=0)
# 定义三种策略
class EpsilonGreedyWrapper:
def __init__(self, n_arms):
self.estimates = np.zeros(n_arms)
self.counts = np.zeros(n_arms)
self.epsilon = 0.1
def select_action(self):
if np.random.random() < self.epsilon:
return np.random.randint(n_arms)
return np.argmax(self.estimates)
def update(self, a, r):
self.counts[a] += 1
self.estimates[a] += (r - self.estimates[a]) / self.counts[a]
class UCBWrapper:
def __init__(self, n_arms):
self.n_arms = n_arms
self.estimates = np.zeros(n_arms)
self.counts = np.zeros(n_arms)
self.total = 0
self.c = 2.0
def select_action(self):
self.total += 1
untried = np.where(self.counts == 0)[0]
if len(untried) > 0: return untried[0]
ucb = self.estimates + self.c * np.sqrt(np.log(self.total) / self.counts)
return np.argmax(ucb)
def update(self, a, r):
self.counts[a] += 1
self.estimates[a] += (r - self.estimates[a]) / self.counts[a]
class TSWrapper:
def __init__(self, n_arms):
self.alphas = np.ones(n_arms)
self.betas = np.ones(n_arms)
def select_action(self):
return np.argmax(np.random.beta(self.alphas, self.betas))
def update(self, a, r):
if r > 0: self.alphas[a] += 1
else: self.betas[a] += 1
# 运行实验
rewards_eg, opt_eg = run_multiple(EpsilonGreedyWrapper)
rewards_ucb, opt_ucb = run_multiple(UCBWrapper)
rewards_ts, opt_ts = run_multiple(TSWrapper)
cum_eg = np.cumsum(rewards_eg)
cum_ucb = np.cumsum(rewards_ucb)
cum_ts = np.cumsum(rewards_ts)
# 理论最优
optimal_reward = true_probs[best_arm] * np.arange(1, 1001)
print("=== 三种探索策略全面对比(50次实验平均)===")
print(f"\n累积奖励(1000步):")
print(f" ε-greedy: {cum_eg[-1]:.0f}")
print(f" UCB: {cum_ucb[-1]:.0f}")
print(f" Thompson Sampling: {cum_ts[-1]:.0f}")
print(f" 理论最优: {optimal_reward[-1]:.0f}")
print(f"\n遗憾(Regret):")
print(f" ε-greedy: {optimal_reward[-1] - cum_eg[-1]:.0f}")
print(f" UCB: {optimal_reward[-1] - cum_ucb[-1]:.0f}")
print(f" Thompson Sampling: {optimal_reward[-1] - cum_ts[-1]:.0f}")
print(f"\n最后100步最优动作选择率:")
print(f" ε-greedy: {opt_eg[-100:].mean()*100:.1f}%")
print(f" UCB: {opt_ucb[-100:].mean()*100:.1f}%")
print(f" Thompson Sampling: {opt_ts[-100:].mean()*100:.1f}%")
print(f"\n结论:UCB和Thompson Sampling明显优于ε-greedy")
print(f" 因为它们进行的是"智能探索"而非"盲目探索"")什么用(应用):理解不同探索策略的优劣,能帮助你在实际RL项目中做出正确的选择。对于简单任务,ε-greedy足够好;对于需要高效探索的任务(如稀疏奖励环境),UCB或好奇心驱动的方法更合适;对于不确定性量化的需求,Thompson Sampling或其深度版本是最佳选择。
哪些坑(缺点):探索策略的选择高度依赖任务特性;没有一种策略在所有场景下都最优;深度RL中的探索策略需要与函数近似配合,可能不稳定;探索过多可能导致训练时间过长,探索过少可能导致策略次优。
概念关系图谱
| 概念 | 上位概念 | 核心思想 | 关键公式/方法 | 应用场景 |
|---|---|---|---|---|
| 多臂老虎机 | 序列决策 | K个动作,未知奖励分布,最大化累积奖励 | Regret = T·μ* - Σr_t | 探索-利用基础模型 |
| ε-greedy | 探索策略 | 以概率ε随机探索 | 随机动作 vs argmax Q(a) | 简单RL任务 |
| UCB | 探索策略 | 乐观面对不确定性,加探索奖励 | Q(a) + c·√(ln t / N(a)) | 高效探索 |
| Thompson Sampling | 探索策略 | 贝叶斯后验采样 | μ̃_a ~ Beta(α_a, β_a) | 不确定性量化 |
| 遗憾(Regret) | 评估指标 | 与最优策略的累积奖励差距 | Regret = O(log T) / O(T) | 评估探索策略 |
| 衰减ε | 探索调度 | ε从大到小逐步衰减 | ε_t = max(ε_min, ε_0·d^t) | 平衡探索与利用 |
| 好奇心驱动 | 深度探索 | 用预测误差作为内在奖励 | ICM, RND | 稀疏奖励探索 |
| 熵正则化 | 探索正则 | 最大化策略熵鼓励探索 | SAC, H(π(· | s)) |
重点答疑
Q1: 为什么ε-greedy的遗憾是O(T)而UCB是O(log T)?
ε-greedy即使已经确定了最优动作,仍然以概率ε随机探索(包括已知很差的动作),导致累积遗憾随T线性增长。而UCB的探索奖励c·√(ln t/N(a))随着动作被选次数增多而快速衰减,最终几乎只选最优动作,所以遗憾只随log T增长。
解答:ε-greedy是"永远在探索"(线性遗憾),UCB是"探索够了就停止"(对数遗憾)。这就是"盲目探索"和"智能探索"的本质区别。
Q2: Thompson Sampling和UCB哪个更好?
两者在理论上都是接近最优的(遗憾O(log T)),但各有优势:
- Thompson Sampling在实际中通常表现更好,因为它自然地利用完整的后验分布,而不是仅用置信区间。
- UCB计算更简单,不需要维护后验分布。
- Thompson Sampling更容易扩展到复杂模型(如贝叶斯神经网络)。
- 在深度RL中,Thompson Sampling的近似版本(如Bootstrapped DQN)表现优异。
解答:两者都很好,Thompson Sampling通常略优但计算成本更高。实际中选择取决于任务的计算约束和建模复杂度。
Q3: 在深度RL中,ε-greedy为什么还是最常用的探索策略?
尽管ε-greedy在理论上不如UCB和Thompson Sampling,但在深度RL中它仍然是最常用的,因为:
- 极其简单:只需一行代码,不需要修改网络结构。
- 与经验回放兼容:DQN的经验回放机制已经在一定程度上缓解了探索不足的问题。
- 深度RL中的主要挑战是函数近似和稳定性,探索策略的选择相对次要。
- 在密集奖励环境中,ε-greedy已经足够好。
解答:简单就是美。在深度RL中,稳定性比探索效率更重要。但随着RL应用越来越复杂(稀疏奖励),更智能的探索策略正在变得更重要。
Q4: 探索和利用的权衡是否可以完全自动化?
有一些方法尝试自动化这个权衡:
- 贝叶斯方法(如Thompson Sampling)自然地从数据中学习探索程度。
- 元学习(Meta-RL)可以学习"如何探索"的策略。
- 内在动机(Intrinsic Motivation)让智能体自己决定何时探索。
但完全自动化仍然是一个开放问题。在大多数实际应用中,仍然需要人工设置探索参数(如ε的衰减速度、UCB的c值)。
解答:目前还没有完全自动化的解决方案,但贝叶斯方法和元学习正在朝这个方向努力。实践中,调参仍然不可避免。
Q5: Contextual Bandit和MDP中的探索有什么区别?
Contextual Bandit(上下文老虎机)介于Bandit和MDP之间:
- Bandit:没有状态,只有动作选择。
- Contextual Bandit:每次决策前观察到一个"上下文"(状态),但动作不影响下一个状态。
- MDP:动作影响状态转移,探索影响未来能访问的状态。
Contextual Bandit中,探索只需要考虑"这个上下文下哪个动作好"。MDP中,探索还需要考虑"这个动作会把我带到哪里"——即探索的"策略性"(strategic exploration)。
解答:MDP中的探索比Bandit复杂得多,因为探索不仅影响即时奖励,还影响未来能访问的状态。这是深度RL中探索研究的核心挑战。
Q6: 在RL中,有什么方法可以替代ε-greedy进行更高效的探索?
除了ε-greedy,还有多种探索策略:
- 参数噪声:在策略网络的参数上加噪声,而非在输出上加噪声。比ε-greedy更结构化。
- 熵正则化:在损失函数中加入策略熵项,鼓励策略保持随机性(SAC)。
- 好奇心驱动:用状态预测误差作为内在奖励(ICM),鼓励探索"意外"的状态。
- 计数探索:给访问次数少的状态额外奖励(#Exploration)。
- Bootstrapped DQN:用多个Q网络头实现Thompson Sampling的近似。
解答:参数噪声对于连续控制任务效果好,好奇心驱动对于稀疏奖励环境好,熵正则化是SAC的标准做法。选择哪种取决于任务特性。
章节单词汇总
| 英文 | 音标 | 中文 |
|---|---|---|
| exploration | /ˌekspləˈreɪʃn/ | 探索 |
| exploitation | /ˌeksplɔɪˈteɪʃn/ | 利用 |
| multi-armed bandit | /ˈmʌlti ɑːrmd ˈbændɪt/ | 多臂老虎机 |
| epsilon-greedy | /ˈepsɪlɒn ˈɡriːdi/ | ε-贪婪 |
| upper confidence bound | /ˈʌpər ˈkɑːnfɪdəns baʊnd/ | 置信上界 |
| Thompson Sampling | /ˈtɑːmpsən ˈsæmplɪŋ/ | 汤普森采样 |
| regret | /rɪˈɡret/ | 遗憾 |
| Hoeffding inequality | /ˈhoʊfdɪŋ ˌɪnɪˈkwɑːləti/ | 霍夫丁不等式 |
| beta distribution | /ˈbeɪtə ˌdɪstrɪˈbjuːʃn/ | Beta分布 |
| posterior | /pɑːˈstɪriər/ | 后验 |
| prior | /ˈpraɪər/ | 先验 |
| Bayesian | /ˈbeɪziən/ | 贝叶斯的 |
| curiosity-driven | /ˌkjʊriˈɑːsəti ˈdrɪvn/ | 好奇心驱动的 |
| entropy regularization | /ˈentrəpi ˌreɡjələrəˈzeɪʃn/ | 熵正则化 |
| parameter noise | /pəˈræmɪtər nɔɪz/ | 参数噪声 |
| contextual bandit | /kənˈtekstʃuəl ˈbændɪt/ | 上下文老虎机 |
| intrinsic motivation | /ɪnˈtrɪnsɪk ˌmoʊtɪˈveɪʃn/ | 内在动机 |
面试练习
Q1 [单选] ε-greedy策略中,ε=0.2的含义是什么?
- A. 80%概率随机探索
- B. 20%概率随机探索,80%概率选择最优动作
- C. 每个动作有20%概率被选中
- D. 学习率为0.2
解答:ε=0.2表示探索概率20%,利用概率80%。即20%的时间随机选择动作,80%的时间选择当前最优动作。
Q2 [单选] UCB策略中,探索奖励c·√(ln t/N(a))的作用是什么?
- A. 惩罚被选次数多的动作
- B. 给被选次数少的动作一个"加分",鼓励探索
- C. 减小所有动作的估计值
- D. 增加学习率
解答:探索奖励给被选次数少的动作一个加分,使得它们有机会被选中。当N(a)很小时,探索奖励大;当N(a)很大时,探索奖励接近0,策略退化为贪心。
Q3 [多选] 以下关于Thompson Sampling的说法,哪些是正确的?
- A. 它从后验分布中采样,自然平衡探索与利用
- B. 对于Bernoulli奖励,使用Beta分布作为共轭先验
- C. 它总是选择估计值最大的动作
- D. 不确定性大的动作有更大的概率被选中
解答:A正确,采样机制自然实现了探索。B正确,Beta-Bernoulli共轭对是Thompson Sampling最常见的实现。C错误,它选采样值最大的动作,而非估计值最大的。D正确,后验分布宽的动作,采样值范围大,有时会采到高值。
Q4 [单选] 多臂老虎机问题的"遗憾"(Regret)衡量的是什么?
- A. 智能体的"后悔"情绪
- B. 与已知最优策略相比,累积奖励的损失
- C. 探索次数与利用次数的比例
- D. 每个动作的方差
解答:遗憾 = T·μ* - Σ_{t=1}^T r_t,其中μ*是最优手臂的期望奖励。它衡量的是"因为不知道哪个手臂最好,而损失了多少奖励"。遗憾越小,探索策略越高效。
Q5 [多选] 以下哪些是MDP中探索比Bandit中探索更复杂的原因?
- A. MDP中动作影响未来状态,Bandit中不影响
- B. MDP需要探索状态空间,而不仅是动作空间
- C. MDP中不需要探索
- D. MDP中探索可能导致终止状态或危险状态
解答:A正确,MDP中动作影响状态转移,这是核心区别。B正确,MDP中需要探索"哪些状态值得访问"。C错误。D正确,MDP中探索可能带来代价(如掉入陷阱)。
Q6 [单选] UCB策略的遗憾上界是什么?
- A. O(T)
- B. O(log T)
- C. O(1)
- D. O(T²)
解答:UCB的遗憾上界是O(log T),即对数级别。这意味着随着T增大,平均遗憾趋于0。ε-greedy的遗憾是O(T),即线性级别。
Q7 [单选] 在UCB的计算中,如果某个动作的N(a)=0(从未被选过),通常如何处理?
- A. 优先选择该动作
- B. 跳过该动作
- C. 给该动作赋予0值
- D. 给该动作赋予无限大的值
解答:通常先确保每个动作至少被选一次(初始化阶段),或者在UCB计算中给未选过的动作赋予一个很大的值。这确保了探索的完整性。
Q8 [多选] 以下哪些是深度RL中常用的探索策略?
- A. ε-greedy
- B. 熵正则化(如SAC)
- C. 参数噪声
- D. 确定性策略
解答:A、B、C都是深度RL中常用的探索策略。D(确定性策略)本身不提供探索,需要配合其他探索机制(如Ornstein-Uhlenbeck噪声)。
Q9 [单选] Thompson Sampling中,如果某个动作被选了100次,成功80次,它的Beta后验分布是什么?
- A. Beta(80, 20)
- B. Beta(81, 21)
- C. Beta(80, 100)
- D. Beta(100, 80)
解答:Beta(α+success, β+failure) = Beta(1+80, 1+20) = Beta(81, 21)。Beta分布的先验参数(1,1)对应均匀分布,加上成功次数和失败次数得到后验参数。
Q10 [多选] 以下关于探索-利用权衡的说法,哪些是正确的?
- A. 过度利用可能导致收敛到次优策略
- B. 过度探索会降低短期绩效
- C. 探索和利用是两个完全独立的问题
- D. 好的探索策略应该在探索和利用之间找到平衡
解答:A正确,如果不探索,可能永远找不到更好的动作。B正确,探索期间可能选择次优动作,降低短期奖励。C错误,探索和利用是同一个问题的两面。D正确,平衡是关键。