微信登录

策略梯度算法 - Actor - Critic - 结合价值与策略

策略梯度算法 - Actor - Critic:结合价值与策略

一、引言

在强化学习领域,策略梯度算法和基于价值的方法是两种重要的学习范式。策略梯度算法直接对策略进行优化,通过调整策略参数来最大化累积奖励;而基于价值的方法则通过学习价值函数来间接指导策略的选择。Actor - Critic算法巧妙地将这两种方法结合起来,充分发挥了它们的优势,在许多复杂的强化学习任务中取得了出色的表现。本文将详细介绍策略梯度算法以及Actor - Critic算法的原理、特点和实现。

二、策略梯度算法基础

2.1 策略表示

在策略梯度算法中,策略通常用一个参数化的函数 $\pi{\theta}(a|s)$ 来表示,其中 $\theta$ 是策略的参数,$s$ 是状态,$a$ 是动作。这个函数表示在状态 $s$ 下选择动作 $a$ 的概率。例如,在一个简单的机器人导航任务中,状态 $s$ 可以是机器人当前的位置和朝向,动作 $a$ 可以是机器人的前进、左转、右转等操作,$\pi{\theta}(a|s)$ 则给出了在当前状态下选择每个动作的概率。

2.2 目标函数

策略梯度算法的目标是最大化期望累积奖励 $J(\theta)$,即:
[J(\theta) = \mathbb{E}{\tau \sim \pi{\theta}} \left[ \sum_{t=0}^{T} r(s_t, a_t) \right]]
其中,$\tau = (s_0, a_0, r_0, s_1, a_1, r_1, \cdots)$ 是一个轨迹,$r(s_t, a_t)$ 是在状态 $s_t$ 下执行动作 $a_t$ 获得的即时奖励。

2.3 策略梯度定理

为了优化目标函数 $J(\theta)$,我们需要计算其关于参数 $\theta$ 的梯度 $\nabla{\theta} J(\theta)$。根据策略梯度定理,有:
[\nabla
{\theta} J(\theta) = \mathbb{E}{\tau \sim \pi{\theta}} \left[ \sum{t=0}^{T} \nabla{\theta} \log \pi{\theta}(a_t|s_t) Q^{\pi{\theta}}(st, a_t) \right]]
其中,$Q^{\pi
{\theta}}(st, a_t)$ 是动作价值函数,表示在策略 $\pi{\theta}$ 下,从状态 $s_t$ 执行动作 $a_t$ 后获得的期望累积奖励。

通过计算梯度,我们可以使用梯度上升法来更新策略参数:
[\theta \leftarrow \theta + \alpha \nabla_{\theta} J(\theta)]
其中,$\alpha$ 是学习率。

三、基于价值的方法回顾

基于价值的方法主要通过学习价值函数来指导策略的选择。最常见的价值函数是状态价值函数 $V^{\pi}(s)$ 和动作价值函数 $Q^{\pi}(s, a)$。

3.1 状态价值函数

状态价值函数 $V^{\pi}(s)$ 表示在策略 $\pi$ 下,从状态 $s$ 开始获得的期望累积奖励:
[V^{\pi}(s) = \mathbb{E}{\tau \sim \pi} \left[ \sum{t=0}^{T} r(s_t, a_t) | s_0 = s \right]]

3.2 动作价值函数

动作价值函数 $Q^{\pi}(s, a)$ 表示在策略 $\pi$ 下,从状态 $s$ 执行动作 $a$ 后获得的期望累积奖励:
[Q^{\pi}(s, a) = \mathbb{E}{\tau \sim \pi} \left[ \sum{t=0}^{T} r(s_t, a_t) | s_0 = s, a_0 = a \right]]

基于价值的方法通常使用动态规划、蒙特卡罗方法或时间差分学习来学习价值函数,然后根据价值函数选择最优动作。

四、Actor - Critic算法原理

Actor - Critic算法结合了策略梯度算法和基于价值的方法。它由两个部分组成:Actor(策略网络)和Critic(价值网络)。

4.1 Actor

Actor负责学习策略 $\pi_{\theta}(a|s)$,通过策略梯度算法来更新策略参数 $\theta$。Actor根据当前状态 $s$ 选择动作 $a$,并与环境进行交互,获得奖励 $r$ 和下一个状态 $s’$。

4.2 Critic

Critic负责学习价值函数 $V{\phi}(s)$ 或 $Q{\phi}(s, a)$,其中 $\phi$ 是价值网络的参数。Critic根据Actor与环境交互得到的数据来更新价值网络的参数,以估计状态或动作的价值。

4.3 算法流程

Actor - Critic算法的基本流程如下:

  1. 初始化Actor的参数 $\theta$ 和Critic的参数 $\phi$。
  2. 对于每个回合:
    • 初始化状态 $s$。
    • 对于每个时间步 $t$:
      • 根据当前策略 $\pi_{\theta}(a|s)$ 选择动作 $a$。
      • 执行动作 $a$,与环境交互,获得奖励 $r$ 和下一个状态 $s’$。
      • 使用Critic估计当前状态的价值 $V{\phi}(s)$ 和下一个状态的价值 $V{\phi}(s’)$。
      • 计算时间差分误差 $\delta = r + \gamma V{\phi}(s’) - V{\phi}(s)$,其中 $\gamma$ 是折扣因子。
      • 更新Critic的参数 $\phi$,以最小化时间差分误差,例如使用均方误差损失函数:
        [L(\phi) = \frac{1}{2} \delta^2]
      • 更新Actor的参数 $\theta$,使用策略梯度:
        [\nabla{\theta} J(\theta) \approx \nabla{\theta} \log \pi{\theta}(a|s) \delta]
        [\theta \leftarrow \theta + \alpha \nabla
        {\theta} J(\theta)]
    • 更新状态 $s = s’$。

五、Actor - Critic算法的优点

5.1 减少方差

与传统的策略梯度算法相比,Actor - Critic算法使用Critic来估计价值函数,从而减少了策略梯度估计的方差。因为Critic可以提供更准确的价值估计,使得策略更新更加稳定。

5.2 更快的收敛速度

由于结合了价值函数的学习,Actor - Critic算法可以更快地收敛到最优策略。Critic可以帮助Actor更快地找到有价值的动作,从而加速学习过程。

5.3 处理连续动作空间

Actor - Critic算法可以很方便地处理连续动作空间。因为Actor直接输出动作的概率分布,对于连续动作空间,可以使用高斯分布等连续概率分布来表示策略。

六、基于TensorFlow的Actor - Critic算法实现示例

以下是一个简单的基于TensorFlow的Actor - Critic算法实现示例,用于解决OpenAI Gym的CartPole-v1环境:

  1. import tensorflow as tf
  2. import numpy as np
  3. import gym
  4. # 定义Actor网络
  5. class Actor(tf.keras.Model):
  6. def __init__(self, num_actions):
  7. super(Actor, self).__init__()
  8. self.dense1 = tf.keras.layers.Dense(64, activation='relu')
  9. self.dense2 = tf.keras.layers.Dense(num_actions, activation='softmax')
  10. def call(self, inputs):
  11. x = self.dense1(inputs)
  12. return self.dense2(x)
  13. # 定义Critic网络
  14. class Critic(tf.keras.Model):
  15. def __init__(self):
  16. super(Critic, self).__init__()
  17. self.dense1 = tf.keras.layers.Dense(64, activation='relu')
  18. self.dense2 = tf.keras.layers.Dense(1)
  19. def call(self, inputs):
  20. x = self.dense1(inputs)
  21. return self.dense2(x)
  22. # 定义Actor - Critic代理
  23. class ActorCriticAgent:
  24. def __init__(self, num_actions, learning_rate_actor=0.001, learning_rate_critic=0.005, gamma=0.99):
  25. self.actor = Actor(num_actions)
  26. self.critic = Critic()
  27. self.optimizer_actor = tf.keras.optimizers.Adam(learning_rate=learning_rate_actor)
  28. self.optimizer_critic = tf.keras.optimizers.Adam(learning_rate=learning_rate_critic)
  29. self.gamma = gamma
  30. def select_action(self, state):
  31. state = np.expand_dims(state, axis=0)
  32. action_probs = self.actor(state)
  33. action = np.random.choice(len(action_probs[0]), p=action_probs[0].numpy())
  34. return action
  35. def train_step(self, state, action, reward, next_state, done):
  36. state = np.expand_dims(state, axis=0)
  37. next_state = np.expand_dims(next_state, axis=0)
  38. with tf.GradientTape() as tape_actor, tf.GradientTape() as tape_critic:
  39. # 计算Critic的价值估计
  40. value = self.critic(state)
  41. next_value = self.critic(next_state)
  42. # 计算时间差分误差
  43. if done:
  44. target = reward
  45. else:
  46. target = reward + self.gamma * next_value
  47. delta = target - value
  48. # 计算Actor的损失
  49. action_probs = self.actor(state)
  50. action_mask = tf.one_hot(action, len(action_probs[0]))
  51. log_prob = tf.math.log(tf.reduce_sum(action_mask * action_probs, axis=1))
  52. actor_loss = -log_prob * delta
  53. # 计算Critic的损失
  54. critic_loss = 0.5 * tf.square(delta)
  55. # 更新Actor的参数
  56. gradients_actor = tape_actor.gradient(actor_loss, self.actor.trainable_variables)
  57. self.optimizer_actor.apply_gradients(zip(gradients_actor, self.actor.trainable_variables))
  58. # 更新Critic的参数
  59. gradients_critic = tape_critic.gradient(critic_loss, self.critic.trainable_variables)
  60. self.optimizer_critic.apply_gradients(zip(gradients_critic, self.critic.trainable_variables))
  61. # 训练代理
  62. env = gym.make('CartPole-v1')
  63. num_actions = env.action_space.n
  64. agent = ActorCriticAgent(num_actions)
  65. num_episodes = 500
  66. for episode in range(num_episodes):
  67. state = env.reset()
  68. total_reward = 0
  69. done = False
  70. while not done:
  71. action = agent.select_action(state)
  72. next_state, reward, done, _ = env.step(action)
  73. agent.train_step(state, action, reward, next_state, done)
  74. state = next_state
  75. total_reward += reward
  76. print(f"Episode {episode + 1}: Total Reward = {total_reward}")
  77. env.close()

七、总结

Actor - Critic算法通过结合策略梯度算法和基于价值的方法,充分发挥了两者的优势。它减少了策略梯度估计的方差,提高了学习效率,并且可以处理连续动作空间。在实际应用中,Actor - Critic算法已经在许多领域取得了成功,如机器人控制、自动驾驶、游戏等。通过不断的研究和改进,Actor - Critic算法有望在更多复杂的强化学习任务中发挥更大的作用。

策略梯度算法 - Actor - Critic - 结合价值与策略