微信登录

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

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

一、引言

在强化学习的广阔领域中,策略梯度算法和基于价值的算法是两大重要分支。策略梯度算法直接对策略进行优化,而基于价值的算法则通过估计状态价值函数来间接优化策略。Actor - Critic 算法巧妙地将这两者结合起来,既利用策略网络(Actor)直接学习最优策略,又借助价值网络(Critic)来评估策略的好坏,从而在很多复杂的强化学习任务中展现出卓越的性能。

二、策略梯度算法回顾

(一)基本原理

策略梯度算法的核心思想是通过优化策略网络的参数,使得在每个状态下采取的动作能够最大化累积奖励。策略网络通常用 $\pi{\theta}(a|s)$ 表示,其中 $\theta$ 是网络的参数,$s$ 是状态,$a$ 是动作。算法通过计算策略梯度 $\nabla{\theta} J(\theta)$,并沿着梯度方向更新参数 $\theta$,从而逐步改进策略。

(二)优势与不足

  • 优势:可以直接处理连续动作空间,能够学习到随机策略,适用于复杂的环境。
  • 不足:样本效率较低,训练过程不稳定,收敛速度较慢。

三、基于价值的算法回顾

(一)基本原理

基于价值的算法通过估计状态价值函数 $V(s)$ 或动作价值函数 $Q(s,a)$ 来指导策略的选择。常见的算法如 Q - learning,通过不断更新 $Q$ 值,使得智能体在每个状态下选择具有最大 $Q$ 值的动作。

(二)优势与不足

  • 优势:样本效率相对较高,训练过程相对稳定。
  • 不足:难以处理连续动作空间,只能学习到确定性策略。

四、Actor - Critic 算法原理

(一)基本架构

Actor - Critic 算法由两个网络组成:

  • Actor(策略网络):负责生成动作,即根据当前状态 $s$ 输出动作的概率分布 $\pi_{\theta}(a|s)$。
  • Critic(价值网络):负责评估状态或动作的价值,通常估计状态价值函数 $V{\omega}(s)$ 或动作价值函数 $Q{\omega}(s,a)$,其中 $\omega$ 是价值网络的参数。

(二)算法流程

  1. 初始化:初始化 Actor 网络的参数 $\theta$ 和 Critic 网络的参数 $\omega$。
  2. 采样:智能体根据当前策略 $\pi_{\theta}(a|s)$ 在环境中采样一系列的状态 - 动作对 $(s_t, a_t)$ 和奖励 $r_t$。
  3. 更新 Critic 网络:根据采样得到的数据,更新 Critic 网络的参数 $\omega$,使得价值估计更加准确。例如,使用时间差分(TD)误差来更新状态价值函数:
    • TD 误差:$\deltat = r_t + \gamma V{\omega}(s{t + 1}) - V{\omega}(s_t)$
    • 更新公式:$\omega \leftarrow \omega + \alpha{\omega} \delta_t \nabla{\omega} V{\omega}(s_t)$
      其中,$\gamma$ 是折扣因子,$\alpha
      {\omega}$ 是 Critic 网络的学习率。
  4. 更新 Actor 网络:根据 Critic 网络给出的价值评估,更新 Actor 网络的参数 $\theta$,使得策略朝着获得更高价值的方向改进。策略梯度更新公式为:
    • $\nabla{\theta} J(\theta) \approx \sum{t = 0}^{T} \nabla{\theta} \log \pi{\theta}(a_t|s_t) \delta_t$
    • 更新公式:$\theta \leftarrow \theta + \alpha{\theta} \nabla{\theta} J(\theta)$
      其中,$\alpha_{\theta}$ 是 Actor 网络的学习率。
  5. 重复步骤 2 - 4:直到策略收敛或达到最大训练步数。

(三)结合价值与策略的优势

  • 提高样本效率:Critic 网络可以对每个状态 - 动作对的价值进行评估,使得 Actor 网络能够更有针对性地更新策略,减少不必要的探索,从而提高样本效率。
  • 增强训练稳定性:Critic 网络提供的价值估计可以作为一个反馈信号,帮助 Actor 网络更稳定地更新参数,避免策略梯度算法中常见的训练不稳定问题。

五、实用例子:CartPole 环境

(一)环境介绍

CartPole 是 OpenAI Gym 中的一个经典控制问题,智能体需要控制一个小车在水平轨道上左右移动,以保持连接在小车上的杆子的平衡。环境的状态包括小车的位置、速度,杆子的角度和角速度,动作空间为离散的两个动作:向左或向右移动小车。

(二)代码实现(简化版)

  1. import torch
  2. import torch.nn as nn
  3. import torch.optim as optim
  4. import gym
  5. # 定义 Actor 网络
  6. class Actor(nn.Module):
  7. def __init__(self, state_dim, action_dim):
  8. super(Actor, self).__init__()
  9. self.fc1 = nn.Linear(state_dim, 128)
  10. self.fc2 = nn.Linear(128, action_dim)
  11. self.softmax = nn.Softmax(dim = 1)
  12. def forward(self, x):
  13. x = torch.relu(self.fc1(x))
  14. x = self.fc2(x)
  15. probs = self.softmax(x)
  16. return probs
  17. # 定义 Critic 网络
  18. class Critic(nn.Module):
  19. def __init__(self, state_dim):
  20. super(Critic, self).__init__()
  21. self.fc1 = nn.Linear(state_dim, 128)
  22. self.fc2 = nn.Linear(128, 1)
  23. def forward(self, x):
  24. x = torch.relu(self.fc1(x))
  25. value = self.fc2(x)
  26. return value
  27. # 初始化环境
  28. env = gym.make('CartPole-v1')
  29. state_dim = env.observation_space.shape[0]
  30. action_dim = env.action_space.n
  31. # 初始化 Actor 和 Critic 网络
  32. actor = Actor(state_dim, action_dim)
  33. critic = Critic(state_dim)
  34. # 定义优化器
  35. actor_optimizer = optim.Adam(actor.parameters(), lr = 0.001)
  36. critic_optimizer = optim.Adam(critic.parameters(), lr = 0.001)
  37. # 训练参数
  38. gamma = 0.99
  39. num_episodes = 1000
  40. for episode in range(num_episodes):
  41. state = env.reset()
  42. state = torch.FloatTensor(state).unsqueeze(0)
  43. done = False
  44. total_reward = 0
  45. while not done:
  46. # Actor 选择动作
  47. probs = actor(state)
  48. action_dist = torch.distributions.Categorical(probs)
  49. action = action_dist.sample()
  50. # 与环境交互
  51. next_state, reward, done, _ = env.step(action.item())
  52. next_state = torch.FloatTensor(next_state).unsqueeze(0)
  53. total_reward += reward
  54. # 计算 TD 误差
  55. value = critic(state)
  56. next_value = critic(next_state)
  57. td_error = reward + gamma * next_value * (1 - done) - value
  58. # 更新 Critic 网络
  59. critic_loss = td_error.pow(2).mean()
  60. critic_optimizer.zero_grad()
  61. critic_loss.backward()
  62. critic_optimizer.step()
  63. # 更新 Actor 网络
  64. actor_loss = -action_dist.log_prob(action) * td_error.detach()
  65. actor_optimizer.zero_grad()
  66. actor_loss.backward()
  67. actor_optimizer.step()
  68. state = next_state
  69. print(f'Episode {episode + 1}: Total Reward = {total_reward}')
  70. env.close()

(三)代码解释

  1. 网络定义:定义了 Actor 网络和 Critic 网络,分别用于生成动作概率分布和估计状态价值。
  2. 训练过程:在每个回合中,智能体根据 Actor 网络的输出选择动作,与环境交互得到奖励和下一个状态。然后计算 TD 误差,更新 Critic 网络和 Actor 网络的参数。

六、总结

算法类型 优势 不足 适用场景
策略梯度算法 可处理连续动作空间,能学习随机策略 样本效率低,训练不稳定 复杂环境,连续动作任务
基于价值的算法 样本效率高,训练稳定 难以处理连续动作空间,只能学习确定性策略 离散动作任务
Actor - Critic 算法 结合两者优势,提高样本效率,增强训练稳定性 实现复杂度较高 多种强化学习任务

Actor - Critic 算法通过巧妙地结合策略梯度算法和基于价值的算法,在强化学习领域取得了显著的成果。它既能够处理连续动作空间,又具有较高的样本效率和训练稳定性。通过 CartPole 环境的例子,我们可以看到 Actor - Critic 算法的具体实现和应用。在实际应用中,我们可以根据具体的任务需求对算法进行调整和优化,以获得更好的性能。

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