自学内容网 自学内容网

5. ε-greedy 探索

在 DDPG(Deep Deterministic Policy Gradient)中加入 ε-greedy 探索 也是一种增加智能体探索性的策略,尽管 ε-greedy 策略通常更适用于离散动作空间。然而,在 DDPG 的连续动作空间中,也可以通过 ε-greedy 策略实现探索。以下是如何将 ε-greedy 应用于 DDPG 的方法及其原因。

ε-greedy

1. 什么是 ε-greedy 探索策略?

ε − g r e e d y ε-greedy εgreedy 策略是一种简单而有效的探索方法,定义如下:

  • 在每个时间步中,以 ε 的概率进行随机探索,即选择一个随机动作;
  • 以 (1 - ε) 的概率选择当前策略网络输出的最优动作,即 Actor 网络的确定性输出。

在离散动作空间中,ε-greedy 的随机探索通常是从离散动作集中随机选择一个动作。而在连续动作空间中,我们可以稍作修改,使 ε-greedy 策略与 DDPG 的确定性策略结合。

2. 在 DDPG 中实现 ε-greedy 探索

在 DDPG 中,可以通过以下方式引入 ε-greedy 策略:

1 ) 随机选择一个动作

  • 以 ε 的概率选择一个完全随机的动作,从动作空间中均匀采样。

2 ) 选择当前策略输出的最优动作

  • 以 (1 - ε) 的概率选择 Actor 网络输出的确定性动作(最优动作)。

在连续动作空间中,具体实现如下:

import numpy as np

def select_action(state, actor, action_dim, epsilon):
    # 以 epsilon 的概率进行随机探索
    if np.random.rand() < epsilon:
        # 随机生成一个动作
        action = np.random.uniform(low=-1.0, high=1.0, size=action_dim)
    else:
        # 否则选择当前策略的最优动作
        action = actor(state).detach().cpu().numpy()
    return action

3. ε 的值及其调整

  • 初始值设置:在训练开始时,可以将 ε 设置得较高(如 0.1 至 0.3),这样可以让智能体在初期进行更多的探索。
  • 逐步减少 ε:随着训练的进行,逐渐减小 ε 的值,使得智能体逐渐从探索过渡到利用。
    epsilon = max(epsilon_min, epsilon * decay_rate)
    

4. 为什么在 DDPG 中加入 ε-greedy 探索?

在 DDPG 中使用 ε-greedy 探索有以下几点优势:

1 ) 探索与利用平衡

  • 通过 ε-greedy 策略,智能体在训练初期能够进行更多随机探索,逐渐减少探索以便更专注于最优策略。
  • 这种机制有助于在确定性策略中增加随机性,以避免过度依赖当前策略网络输出。

2 ) 简单且有效

  • 相比于加入连续噪声(如高斯噪声或 Ornstein-Uhlenbeck 噪声),ε-greedy 策略的实现更加直接且便于调节。
  • 这种方法尤其适合对噪声分布不敏感的任务,能够以更简单的方式实现探索。

3 ) 适合在特定场景下使用

  • 对于需要更强的探索性或环境具有较多随机性时,ε-greedy 可以确保一定的随机探索,有助于跳出局部最优解。

5. ε-greedy 与噪声探索的对比

在 DDPG 中,加入 ε-greedy 探索和噪声探索各有优势,具体区别如下:

特性ε-greedy 探索噪声探索(如 Ornstein-Uhlenbeck 噪声)
适用性更适合需要随机选择动作的任务更适合需要连续平滑动作的任务
探索方式ε 概率选择随机动作,(1 - ε) 概率选择最优动作每个时间步中均在确定性动作上加入噪声
复杂性实现简单、调节直观实现稍复杂,可能需调整噪声参数
效果增强探索性,适合具有较多随机性环境的任务平滑且时间相关的探索,适合物理系统或需要平滑动作的任务

6.实践中的应用

在 DDPG 中,通常会优先使用噪声(如高斯噪声或 Ornstein-Uhlenbeck 噪声)进行探索。然而,在某些任务中,ε-greedy 探索也可以提供有效的探索方式,尤其是在探索多样性、随机性方面有较高要求的任务中。

    def allocate(self, prev_action, users, curren_episode, current_step):

        self.prev_qualities = prev_action
        self.users = users
        self.curren_episode = curren_episode
        self.curren_step = current_step
        # input state
        state_vector = self.get_state_vector(self.prev_qualities, self.users)

        # 增加noise探索
        epsilon = np.interp(x=self.curren_episode * self.num_step + self.curren_step,
                            xp=[0, self.epsilon_decay],
                            fp=[self.epsilon_start, self.epsilon_end])
        random_sample = random.random()
        if random_sample <= epsilon:
            # 探索:选择一个随机离散动作
            actions = np.random.choice(range(1, self.max_quality_level + 1), size=self.action_dim)
        else:
            # 利用:使用 Actor 网络选择动作
            actions = self.ddpg_agent.select_action(state_vector)

        return actions

这段代码实现了基于 ε-greedy 策略的探索与利用机制。它通过插值计算逐步减少的 ε 值来控制探索的概率,使得在训练早期更偏向探索,后期则逐渐更偏向利用 Actor 网络输出的最优动作。以下是每一行的解释:

6.1 代码详细解释

for step_i in range(NUM_STEP):
  • 这段代码运行一个循环 NUM_STEP 次(假设是一个训练过程中需要执行的步数),每次循环都代表一个时间步。
  • step_i 表示当前时间步的索引。
epsilon = np.interp(x=episode_i * NUM_STEP + step_i, xp=[0, epsilon_decay], fp=[epsilon_start, epsilon_end])
  • 这一行使用 np.interp 函数对 epsilon 进行线性插值,使 epsilonepsilon_start(初始探索概率)逐步减小到 epsilon_end(最终探索概率)。
  • np.interp 的参数含义:
    • x=episode_i * NUM_STEP + step_i:表示当前训练的步数。episode_i 是当前的回合数,乘以 NUM_STEP 后表示所有时间步的数量,再加上当前步 step_i
    • xp=[0, epsilon_decay]:定义了插值的两个参考点,即从步数 0epsilon_decay 之间,epsilon 会逐渐变化。
    • fp=[epsilon_start, epsilon_end]:指定插值的起始值和结束值,即 epsilonepsilon_start 逐渐减小到 epsilon_end
  • 这种插值方法让 epsilon 随着步数逐渐减小,初期探索概率较高,训练后期则逐渐减少探索概率。
random_sample = random.random()
  • 生成一个 0 到 1 之间的随机浮点数 random_sample,用于决定当前时间步是执行探索还是利用。
  • random.random() 返回一个均匀分布的随机数,介于 [0, 1) 之间。
if random_sample <= epsilon:
    # 探索:选择一个随机动作
    action = np.random.uniform(-2, 2, size=ACTION_DIM)
  • 如果 random_sample 小于等于当前的 epsilon 值,表示以 epsilon 概率进行探索,即选择一个随机动作。
  • np.random.uniform(-2, 2, size=ACTION_DIM):在动作空间中随机生成一个动作,范围为 [-2, 2],动作的维度是 ACTION_DIM
  • 这种探索方式允许智能体尝试不同的动作,从而在训练初期积累更多多样性的经验。
else:
    # 利用:使用 Actor 网络选择动作
    action = agent.select_action(state)
  • 如果 random_sample 大于 epsilon 值,表示以 1 − ϵ 1 - \epsilon 1ϵ 的概率执行利用,即使用 Actor 网络来选择动作。
  • agent.select_action(state):调用 agentselect_action 方法,用 Actor 网络基于当前状态 state 输出确定性动作。

6.2 代码总结

  • 这段代码实现了 ε-greedy 探索策略,在每个时间步中以 ϵ \epsilon ϵ 的概率执行探索(选择随机动作),以 1 − ϵ 1 - \epsilon 1ϵ 的概率执行利用(选择最优动作)。
  • epsilon 通过插值逐渐减小,使得智能体在训练早期更偏向探索,后期则逐渐更偏向利用 Actor 网络的输出,从而逐步收敛到更稳定的策略。

6.3 参数解释

参数 xp=[0, epsilon_decay] 是用来定义 epsilon 的衰减过程的步数范围。它指定了 epsilon 从初始值逐渐衰减到终止值的步数区间。

np.interp 函数中:

  • xp 表示插值过程的参考点的步数范围。在 [0, epsilon_decay] 之间,epsilon 从初始值 epsilon_start 逐渐减小到终值 epsilon_end
  • epsilon_decay 通常是一个整数,表示经过多少步后,epsilon 应该从 epsilon_start 减小到 epsilon_end

6.4 如何设定 epsilon_decay

1 ) 任务复杂度

  • 对于较复杂的任务,可能需要更长时间的探索。因此,epsilon_decay 可以设定得较大,让智能体更长时间保持较高的探索概率,从而积累足够的经验。
  • 对于简单的任务,epsilon_decay 可以设定得小一些,让智能体快速过渡到利用阶段。

2 ) 环境动态性

  • 如果环境较为动态,可能需要较长时间的探索。此时,可以增加 epsilon_decay 值。
  • 如果环境稳定,可以更快地衰减 epsilon,因此可以设置较小的 epsilon_decay 值。

3 ) 训练时长

  • 假设训练的总步数为 total_steps,可以设置 epsilon_decay 使探索持续到总步数的 10%-20%,即 epsilon_decay ≈ total_steps * 0.10.2
  • 例如,若总步数为 100000,可以将 epsilon_decay 设为 1000020000,这样前 10000-20000 步中 epsilon 会逐渐减小。

6.5 示例

假设我们有如下参数:

  • total_steps = 100000(总训练步数)
  • 希望在前 10% 的步数中衰减 epsilon,那么:
    epsilon_decay = int(total_steps * 0.1)  # 10% 的步数
    xp = [0, epsilon_decay]  # 衰减范围
    

这样,epsilon 会在前 10000 步内从 epsilon_start 逐渐衰减到 epsilon_end


原文地址:https://blog.csdn.net/u014217137/article/details/143793398

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!