探索与利用权衡

1. 概述

探索(Exploration)与利用(Exploitation)的权衡是强化学习的核心挑战之一。1 智能体需要在利用已知知识以获取即时奖励,和探索未知状态以获取潜在更高未来奖励之间做出权衡。

1.1 核心矛盾

方面利用 (Exploitation)探索 (Exploration)
目标最大化当前期望奖励发现更好的策略
风险
短期收益
长期收益可能低可能高

1.2 探索困境

多臂老虎机问题是最好的例子:

假设有 个老虎机臂,每个臂 的奖励分布为 ,但 未知。

探索-利用权衡

  • 选择已知高奖励的臂:可能错过真正的最佳臂
  • 探索未知臂:可能获得更高奖励但也可能是低奖励

2. 探索策略分类

2.1 策略总览

探索策略
├── 随机探索
│   ├── ε-Greedy
│   ├── Boltzmann Exploration
│   └── 噪声注入
├── 确定性探索
│   ├── UCB (Upper Confidence Bound)
│   └── Thompson Sampling
├── 基于不确定性的探索
│   ├── 内在奖励 (Intrinsic Motivation)
│   ├── 不确定性估计
│   └── 信息增益
└── 基于计数的探索
    ├── 哈希方法
    └── 伪计数

2.2 随机探索策略

2.2.1 ε-Greedy

最简单直接的探索策略

def epsilon_greedy(Q, epsilon, n_arms):
    if random.random() < epsilon:
        return random.randint(0, n_arms - 1)  # 探索
    else:
        return argmax(Q)  # 利用

变体

  • 线性衰减
  • 指数衰减
  • 分段常数2

2.2.2 Boltzmann Exploration

基于softmax的概率探索

def boltzmann_exploration(Q, tau):
    probs = softmax(Q / tau)
    return np.random.choice(len(Q), p=probs)

温度参数 的影响

  • :趋向贪婪
  • :趋向均匀

2.2.3 噪声注入

在动作或策略上添加噪声:

# 动作噪声
action = policy(state) + noise
 
# 参数空间噪声
policy_params = policy_params + noise

3. 确定性探索策略

3.1 UCB (Upper Confidence Bound)

核心思想:不仅考虑平均奖励,还考虑不确定性。

其中:

  • :臂 的平均奖励估计
  • :臂 被选择的次数
  • :探索常数

置信度上界

3.2 UCB1算法

class UCB1:
    def __init__(self, n_arms, c=2.0):
        self.n_arms = n_arms
        self.c = c
        self.counts = [0] * n_arms
        self.values = [0.0] * n_arms
    
    def select_arm(self, t):
        for arm in range(self.n_arms):
            if self.counts[arm] == 0:
                return arm  # 探索未访问臂
        
        ucb_values = [
            self.values[arm] + 
            self.c * np.sqrt(np.log(t) / self.counts[arm])
            for arm in range(self.n_arms)
        ]
        return argmax(ucb_values)
    
    def update(self, arm, reward):
        self.counts[arm] += 1
        n = self.counts[arm]
        value = self.values[arm]
        self.values[arm] = ((n - 1) / n) * value + (1 / n) * reward

3.3 Thompson Sampling

贝叶斯方法:维护奖励的后验分布。

class ThompsonSampling:
    def __init__(self, n_arms, prior_alpha=1, prior_beta=1):
        self.n_arms = n_arms
        # Beta分布参数 (用于伯努利奖励)
        self.alpha = [prior_alpha] * n_arms
        self.beta = [prior_beta] * n_arms
    
    def sample(self):
        # 从后验分布采样
        samples = [np.random.beta(self.alpha[i], self.beta[i]) 
                   for i in range(self.n_arms)]
        return argmax(samples)
    
    def update(self, arm, reward):
        # 更新后验
        self.alpha[arm] += reward
        self.beta[arm] += (1 - reward)

4. 基于不确定性的探索

4.1 内在奖励框架

总奖励分解

其中 是内在奖励, 是权重。

4.2 好奇驱动学习 (ICM)

ICM模型3 提出预测状态变化作为内在奖励:

class ICM:
    def __init__(self, state_dim, action_dim, feature_dim=64):
        # 特征编码器
        self.encoder = nn.Sequential(
            nn.Linear(state_dim, 256),
            nn.ReLU(),
            nn.Linear(256, feature_dim)
        )
        
        # 逆向模型:预测动作
        self.inverse_model = nn.Sequential(
            nn.Linear(feature_dim * 2, 256),
            nn.ReLU(),
            nn.Linear(256, action_dim)
        )
        
        # 正向模型:预测下一状态特征
        self.forward_model = nn.Sequential(
            nn.Linear(feature_dim + action_dim, 256),
            nn.ReLU(),
            nn.Linear(256, feature_dim)
        )
    
    def intrinsic_reward(self, state, next_state, action):
        with torch.no_grad():
            f_s = self.encoder(state)
            f_s_next = self.encoder(next_state)
        
        # 预测的动作
        pred_action = self.inverse_model(torch.cat([f_s, f_s_next], dim=1))
        
        # 预测的下一状态特征
        pred_f_next = self.forward_model(torch.cat([f_s, action], dim=1))
        
        # 预测误差作为内在奖励
        reward = 0.5 * F.mse_loss(pred_f_next, f_s_next)
        
        return reward

4.3 随机网络蒸馏 (RND)

核心思想:使用随机初始化网络作为预测目标。

class RND:
    def __init__(self, state_dim, hidden_dim=256):
        # 固定随机网络 (目标)
        self.target_net = nn.Sequential(
            nn.Linear(state_dim, hidden_dim),
            nn.ReLU(),
            nn.Linear(hidden_dim, hidden_dim),
        )
        for p in self.target_net.parameters():
            p.requires_grad = False
        
        # 可学习网络 (预测器)
        self.predictor_net = nn.Sequential(
            nn.Linear(state_dim, hidden_dim),
            nn.ReLU(),
            nn.Linear(hidden_dim, hidden_dim),
        )
    
    def intrinsic_reward(self, state):
        with torch.no_grad():
            target = self.target_net(state)
        prediction = self.predictor_net(state)
        
        # 预测误差
        return F.mse_loss(prediction, target, reduction='none').mean(dim=1)

4.4 信息增益探索

状态-动作信息增益

实际计算中的近似:


5. 基于计数的探索

5.1 伪计数方法

在连续状态空间中,使用密度模型估计访问计数。

Hashing Trick

class HashingCounter:
    def __init__(self, state_dim, hash_dim=10):
        self.hash_dim = hash_dim
        self.projection = np.random.randn(state_dim, hash_dim)
    
    def get_count(self, state):
        hash_key = self.hash_state(state)
        return self.counts.get(hash_key, 0)
    
    def hash_state(self, state):
        return tuple(np.sign(state @ self.projection).astype(int))
    
    def update(self, state):
        hash_key = self.hash_state(state)
        self.counts[hash_key] = self.counts.get(hash_key, 0) + 1

5.2 Bitmap方法

使用像素级图像作为状态哈希键。


6. 内在奖励计算方法

6.1 主流内在奖励类型

方法内在奖励理论基础
ICMpred_error预测误差 = 好奇心
RNDMSE(pred, target)预测随机目标
DISagreementVar(Q values)模型不确定性
Count-based访问计数

6.2 内在奖励归一化

def normalize_intrinsic_reward(reward, eps=1e-8):
    """Running mean normalization"""
    if not hasattr(self, 'running_mean'):
        self.running_mean = 0
        self.running_var = 1
        self.count = 0
    
    self.count += 1
    delta = reward - self.running_mean
    self.running_mean += delta / self.count
    delta2 = reward - self.running_mean
    self.running_var += delta * delta2
    
    if self.count > 1:
        std = np.sqrt(self.running_var)
        return (reward - self.running_mean) / (std + eps)
    return reward

7. 探索策略在深度RL中的应用

7.1 DQN中的探索

def epsilon_decay_schedule(episode, eps_start=1.0, eps_end=0.01, eps_decay=1000):
    return max(eps_end, eps_start - episode / eps_decay)

7.2 DDPG/TD3中的探索

# 添加时间相关探索噪声
class OUNoise:
    def __init__(self, action_dim, mu=0, theta=0.15, sigma=0.2):
        self.mu = mu
        self.theta = theta
        self.sigma = sigma
        self.state = np.zeros(action_dim)
    
    def sample(self):
        self.state += self.theta * (self.mu - self.state) + \
                      self.sigma * np.random.randn(len(self.state))
        return self.state
 
# 在TD3中使用
noise = OUNoise(action_dim)
action = policy(state) + noise.sample()

7.3 PPO/SAC中的探索

PPO 和 SAC 使用随机策略进行隐式探索:

  • PPO:通过熵奖励项
  • SAC:通过最大熵框架

8. 探索策略选择指南

8.1 根据任务特性选择

任务特性推荐策略
稀疏奖励内在奖励、ICM、RND
连续状态RND、伪计数
多峰环境最大熵RL、Boltzmann
短horizonε-greedy、UCB
长horizon内在奖励、信息增益

8.2 探索强度调节

class AdaptiveExploration:
    def __init__(self, strategy='ucb', initial_eps=1.0, min_eps=0.01):
        self.strategy = strategy
        self.eps = initial_eps
        self.min_eps = min_eps
    
    def update(self, episode, performance_improving):
        if self.strategy == 'epsilon_decay':
            # 基于表现的衰减
            decay_rate = 0.995 if performance_improving else 0.999
            self.eps = max(self.min_eps, self.eps * decay_rate)
        elif self.strategy == 'annealing':
            # 固定衰减
            self.eps = max(self.min_eps, self.eps * 0.995)

9. 探索评估指标

9.1 覆盖率

9.2 熵

9.3 访问均匀性


10. 总结

探索-利用权衡是强化学习的核心问题:

10.1 策略对比

策略优点缺点适用场景
ε-Greedy简单可能次优基线、离散
UCB有理论保证需要离散Bandits
Thompson贝叶斯最优计算成本多臂老虎机
ICM处理高维需要额外网络稀疏奖励
RND简单有效可能退化视频游戏
最大熵理论基础温度敏感连续控制

10.2 最佳实践

  1. 任务初期:高探索率
  2. 任务中期:自适应调整
  3. 任务后期:低探索率
  4. 安全关键:保守探索

参考资料


相关主题

Footnotes

  1. Sutton, R. S., & Barto, A. G. (2018). Reinforcement Learning: An Introduction (2nd ed.). MIT Press.

  2. Tokic, M. (2010). Adaptive ε-greedy exploration in reinforcement learning based on value differences. KI 2010.

  3. Pathak, D., Agrawal, P., Efros, A. A., & Darrell, T. (2017). Curiosity-driven Exploration by Self-supervised Prediction. ICML.