在强化学习的广阔领域中,策略梯度算法和基于价值的算法是两大重要分支。策略梯度算法直接对策略进行优化,而基于价值的算法则通过估计状态价值函数来间接优化策略。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 算法由两个网络组成:
CartPole 是 OpenAI Gym 中的一个经典控制问题,智能体需要控制一个小车在水平轨道上左右移动,以保持连接在小车上的杆子的平衡。环境的状态包括小车的位置、速度,杆子的角度和角速度,动作空间为离散的两个动作:向左或向右移动小车。
import torch
import torch.nn as nn
import torch.optim as optim
import gym
# 定义 Actor 网络
class Actor(nn.Module):
def __init__(self, state_dim, action_dim):
super(Actor, self).__init__()
self.fc1 = nn.Linear(state_dim, 128)
self.fc2 = nn.Linear(128, action_dim)
self.softmax = nn.Softmax(dim = 1)
def forward(self, x):
x = torch.relu(self.fc1(x))
x = self.fc2(x)
probs = self.softmax(x)
return probs
# 定义 Critic 网络
class Critic(nn.Module):
def __init__(self, state_dim):
super(Critic, self).__init__()
self.fc1 = nn.Linear(state_dim, 128)
self.fc2 = nn.Linear(128, 1)
def forward(self, x):
x = torch.relu(self.fc1(x))
value = self.fc2(x)
return value
# 初始化环境
env = gym.make('CartPole-v1')
state_dim = env.observation_space.shape[0]
action_dim = env.action_space.n
# 初始化 Actor 和 Critic 网络
actor = Actor(state_dim, action_dim)
critic = Critic(state_dim)
# 定义优化器
actor_optimizer = optim.Adam(actor.parameters(), lr = 0.001)
critic_optimizer = optim.Adam(critic.parameters(), lr = 0.001)
# 训练参数
gamma = 0.99
num_episodes = 1000
for episode in range(num_episodes):
state = env.reset()
state = torch.FloatTensor(state).unsqueeze(0)
done = False
total_reward = 0
while not done:
# Actor 选择动作
probs = actor(state)
action_dist = torch.distributions.Categorical(probs)
action = action_dist.sample()
# 与环境交互
next_state, reward, done, _ = env.step(action.item())
next_state = torch.FloatTensor(next_state).unsqueeze(0)
total_reward += reward
# 计算 TD 误差
value = critic(state)
next_value = critic(next_state)
td_error = reward + gamma * next_value * (1 - done) - value
# 更新 Critic 网络
critic_loss = td_error.pow(2).mean()
critic_optimizer.zero_grad()
critic_loss.backward()
critic_optimizer.step()
# 更新 Actor 网络
actor_loss = -action_dist.log_prob(action) * td_error.detach()
actor_optimizer.zero_grad()
actor_loss.backward()
actor_optimizer.step()
state = next_state
print(f'Episode {episode + 1}: Total Reward = {total_reward}')
env.close()
算法类型 | 优势 | 不足 | 适用场景 |
---|---|---|---|
策略梯度算法 | 可处理连续动作空间,能学习随机策略 | 样本效率低,训练不稳定 | 复杂环境,连续动作任务 |
基于价值的算法 | 样本效率高,训练稳定 | 难以处理连续动作空间,只能学习确定性策略 | 离散动作任务 |
Actor - Critic 算法 | 结合两者优势,提高样本效率,增强训练稳定性 | 实现复杂度较高 | 多种强化学习任务 |
Actor - Critic 算法通过巧妙地结合策略梯度算法和基于价值的算法,在强化学习领域取得了显著的成果。它既能够处理连续动作空间,又具有较高的样本效率和训练稳定性。通过 CartPole 环境的例子,我们可以看到 Actor - Critic 算法的具体实现和应用。在实际应用中,我们可以根据具体的任务需求对算法进行调整和优化,以获得更好的性能。