在强化学习领域,策略梯度算法和基于价值的方法是两种重要的学习范式。策略梯度算法直接对策略进行优化,通过调整策略参数来最大化累积奖励;而基于价值的方法则通过学习价值函数来间接指导策略的选择。Actor - Critic算法巧妙地将这两种方法结合起来,充分发挥了它们的优势,在许多复杂的强化学习任务中取得了出色的表现。本文将详细介绍策略梯度算法以及Actor - Critic算法的原理、特点和实现。
在策略梯度算法中,策略通常用一个参数化的函数 $\pi{\theta}(a|s)$ 来表示,其中 $\theta$ 是策略的参数,$s$ 是状态,$a$ 是动作。这个函数表示在状态 $s$ 下选择动作 $a$ 的概率。例如,在一个简单的机器人导航任务中,状态 $s$ 可以是机器人当前的位置和朝向,动作 $a$ 可以是机器人的前进、左转、右转等操作,$\pi{\theta}(a|s)$ 则给出了在当前状态下选择每个动作的概率。
策略梯度算法的目标是最大化期望累积奖励 $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$ 获得的即时奖励。
为了优化目标函数 $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)$。
状态价值函数 $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]]
动作价值函数 $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负责学习策略 $\pi_{\theta}(a|s)$,通过策略梯度算法来更新策略参数 $\theta$。Actor根据当前状态 $s$ 选择动作 $a$,并与环境进行交互,获得奖励 $r$ 和下一个状态 $s’$。
Critic负责学习价值函数 $V{\phi}(s)$ 或 $Q{\phi}(s, a)$,其中 $\phi$ 是价值网络的参数。Critic根据Actor与环境交互得到的数据来更新价值网络的参数,以估计状态或动作的价值。
Actor - Critic算法的基本流程如下:
与传统的策略梯度算法相比,Actor - Critic算法使用Critic来估计价值函数,从而减少了策略梯度估计的方差。因为Critic可以提供更准确的价值估计,使得策略更新更加稳定。
由于结合了价值函数的学习,Actor - Critic算法可以更快地收敛到最优策略。Critic可以帮助Actor更快地找到有价值的动作,从而加速学习过程。
Actor - Critic算法可以很方便地处理连续动作空间。因为Actor直接输出动作的概率分布,对于连续动作空间,可以使用高斯分布等连续概率分布来表示策略。
以下是一个简单的基于TensorFlow的Actor - Critic算法实现示例,用于解决OpenAI Gym的CartPole-v1环境:
import tensorflow as tf
import numpy as np
import gym
# 定义Actor网络
class Actor(tf.keras.Model):
def __init__(self, num_actions):
super(Actor, self).__init__()
self.dense1 = tf.keras.layers.Dense(64, activation='relu')
self.dense2 = tf.keras.layers.Dense(num_actions, activation='softmax')
def call(self, inputs):
x = self.dense1(inputs)
return self.dense2(x)
# 定义Critic网络
class Critic(tf.keras.Model):
def __init__(self):
super(Critic, self).__init__()
self.dense1 = tf.keras.layers.Dense(64, activation='relu')
self.dense2 = tf.keras.layers.Dense(1)
def call(self, inputs):
x = self.dense1(inputs)
return self.dense2(x)
# 定义Actor - Critic代理
class ActorCriticAgent:
def __init__(self, num_actions, learning_rate_actor=0.001, learning_rate_critic=0.005, gamma=0.99):
self.actor = Actor(num_actions)
self.critic = Critic()
self.optimizer_actor = tf.keras.optimizers.Adam(learning_rate=learning_rate_actor)
self.optimizer_critic = tf.keras.optimizers.Adam(learning_rate=learning_rate_critic)
self.gamma = gamma
def select_action(self, state):
state = np.expand_dims(state, axis=0)
action_probs = self.actor(state)
action = np.random.choice(len(action_probs[0]), p=action_probs[0].numpy())
return action
def train_step(self, state, action, reward, next_state, done):
state = np.expand_dims(state, axis=0)
next_state = np.expand_dims(next_state, axis=0)
with tf.GradientTape() as tape_actor, tf.GradientTape() as tape_critic:
# 计算Critic的价值估计
value = self.critic(state)
next_value = self.critic(next_state)
# 计算时间差分误差
if done:
target = reward
else:
target = reward + self.gamma * next_value
delta = target - value
# 计算Actor的损失
action_probs = self.actor(state)
action_mask = tf.one_hot(action, len(action_probs[0]))
log_prob = tf.math.log(tf.reduce_sum(action_mask * action_probs, axis=1))
actor_loss = -log_prob * delta
# 计算Critic的损失
critic_loss = 0.5 * tf.square(delta)
# 更新Actor的参数
gradients_actor = tape_actor.gradient(actor_loss, self.actor.trainable_variables)
self.optimizer_actor.apply_gradients(zip(gradients_actor, self.actor.trainable_variables))
# 更新Critic的参数
gradients_critic = tape_critic.gradient(critic_loss, self.critic.trainable_variables)
self.optimizer_critic.apply_gradients(zip(gradients_critic, self.critic.trainable_variables))
# 训练代理
env = gym.make('CartPole-v1')
num_actions = env.action_space.n
agent = ActorCriticAgent(num_actions)
num_episodes = 500
for episode in range(num_episodes):
state = env.reset()
total_reward = 0
done = False
while not done:
action = agent.select_action(state)
next_state, reward, done, _ = env.step(action)
agent.train_step(state, action, reward, next_state, done)
state = next_state
total_reward += reward
print(f"Episode {episode + 1}: Total Reward = {total_reward}")
env.close()
Actor - Critic算法通过结合策略梯度算法和基于价值的方法,充分发挥了两者的优势。它减少了策略梯度估计的方差,提高了学习效率,并且可以处理连续动作空间。在实际应用中,Actor - Critic算法已经在许多领域取得了成功,如机器人控制、自动驾驶、游戏等。通过不断的研究和改进,Actor - Critic算法有望在更多复杂的强化学习任务中发挥更大的作用。