本博客代码部分参考了《动手学强化学习》
基于值函数的方法(DQN)和基于策略的方法(REINFORCE),其中基于值函数的方法只学习一个价值函数,而基于策略的方法只学习一个策略函数。那么,一个很自然的问题是,有没有什么方法既学习价值函数,又学习策略函数呢?答案就是 Actor-Critic。Actor-Critic 是囊括一系列算法的整体架构,目前很多高效的前沿算法都属于 Actor-Critic 算法。需要明确的是,Actor-Critic 算法本质上是基于策略的算法,因为这一系列算法的目标都是优化一个带参数的策略,只是会额外学习价值函数,从而帮助策略函数更好地学习。
文章目录
- Actor-Critic 算法
- Actor 模型
- Critic 模型
- 状态动作预测
- 更新梯度
- 一些概念
- 模型的比较
- TD算法,贝尔曼方程
- policy-base 与 value-base
- on-policy 与 off-policy
- on-line 与 off-line
- model-base 与 model-free
- Q-learning 与 Sarsa
- 区别
Actor-Critic 算法
class ActorCritic:
def __init__(self, state_dim, hidden_dim, action_dim, actor_lr, critic_lr,
gamma, device):
# 策略网络
self.actor = PolicyNet(state_dim, hidden_dim, action_dim).to(device)
self.critic = ValueNet(state_dim, hidden_dim).to(device) # 价值网络
# 策略网络优化器
self.actor_optimizer = torch.optim.Adam(self.actor.parameters(),
lr=actor_lr)
self.critic_optimizer = torch.optim.Adam(self.critic.parameters(),
lr=critic_lr) # 价值网络优化器
self.gamma = gamma
self.device = device
def take_action(self, state):
state = torch.tensor([state], dtype=torch.float).to(self.device)
probs = self.actor(state)
action_dist = torch.distributions.Categorical(probs)
action = action_dist.sample()
return action.item()
def update(self, transition_dict):
states = torch.tensor(transition_dict['states'],
dtype=torch.float).to(self.device)
actions = torch.tensor(transition_dict['actions']).view(-1, 1).to(
self.device)
rewards = torch.tensor(transition_dict['rewards'],
dtype=torch.float).view(-1, 1).to(self.device)
next_states = torch.tensor(transition_dict['next_states'],
dtype=torch.float).to(self.device)
dones = torch.tensor(transition_dict['dones'],
dtype=torch.float).view(-1, 1).to(self.device)
# 时序差分目标
td_target = rewards + self.gamma * self.critic(next_states) * (1 -
dones)
td_delta = td_target - self.critic(states) # 时序差分误差
log_probs = torch.log(self.actor(states).gather(1, actions))
actor_loss = torch.mean(-log_probs * td_delta.detach())
# 均方误差损失函数
critic_loss = torch.mean(
F.mse_loss(self.critic(states), td_target.detach()))
self.actor_optimizer.zero_grad()
self.critic_optimizer.zero_grad()
actor_loss.backward() # 计算策略网络的梯度
critic_loss.backward() # 计算价值网络的梯度
self.actor_optimizer.step() # 更新策略网络的参数
self.critic_optimizer.step() # 更新价值网络的参数
Actor 模型
class PolicyNet(torch.nn.Module):
def __init__(self, state_dim, hidden_dim, action_dim):
super(PolicyNet, self).__init__()
self.fc1 = torch.nn.Linear(state_dim, hidden_dim)
self.fc2 = torch.nn.Linear(hidden_dim, action_dim)
def forward(self, x):
x = F.relu(self.fc1(x))
return F.softmax(self.fc2(x), dim=1)
Actor
模型最后输出的是根据State
返回的动作概率,从F.softmax(self.fc2(x), dim=1)
可以看出
Critic 模型
class Valuenet(nn.Module):
def __init__(self, state_dim, hidden_dim, action_dim):
super(Valuenet, self).__init__()
self.fc1 = torch.nn.Linear(state_dim, hidden_dim)
self.fc2 = torch.nn.Linear(hidden_dim, 1)
def forward(self, x):
x = F.relu(self.fc1(x))
return self.fc2(x)
Critic
模型最后输出的是对当前状态预测的最大值,与之前的DQN
有些许不同的是,Critic
模型输出的维度为1维度,也就是说Critic
只要关注当前得分预测,不用参与实际的动作选择。
状态动作预测
def take_action(self, state):
state = torch.tensor([state], dtype=torch.float).to(self.device)
probs = self.actor(state)
action_dist = torch.distributions.Categorical(probs)
action = action_dist.sample()
return action.item()
可以看到与环境交互的时候,只有Actor
参与了预测,Critic
则是在计算误差的时候,才有调用。
更新梯度
Reinforce 模型的损失计算推导可以参考该篇博客
Acotr模型的损失计算推导可以参考该博客
REINFORCE 通过蒙特卡洛采样的方法(也就是从最后一步反向累加奖励)对策略梯度的估计是无偏的,但是方差非常大。通过引入基线函数(baseline function)来减小方差,也就是Actor-Critic 中的self.critic(states)
。
REINFORCE 算法基于蒙特卡洛采样,只能在序列结束后进行更新,这同时也要求任务具有有限的步数,而 Actor-Critic 算法则可以在每一步之后都进行更新,并且不对任务的步数做限制。
# 时序差分目标
td_target = rewards + self.gamma * self.critic(next_states) * (1 -
dones)
td_delta = td_target - self.critic(states) # 时序差分误差
log_probs = torch.log(self.actor(states).gather(1, actions))
actor_loss = torch.mean(-log_probs * td_delta.detach())
# 均方误差损失函数
critic_loss = torch.mean(
F.mse_loss(self.critic(states), td_target.detach()))
self.actor_optimizer.zero_grad()
self.critic_optimizer.zero_grad()
actor_loss.backward() # 计算策略网络的梯度
critic_loss.backward() # 计算价值网络的梯度
self.actor_optimizer.step() # 更新策略网络的参数
self.critic_optimizer.step() # 更新价值网络的参数
Acto
算法通过计算
td_target = rewards + self.gamma * self.critic(next_states) * (1 - dones)
作为 TD目标
td_delta = td_target - self.critic(states)
计算时序差分误差
actor_loss = torch.mean(-log_probs * td_delta.detach())
计算Actor
误差,其中的-
是因为根据公式推导,我们需要让目标函数趋向于期望价值,所以需要梯度上升来寻找最大值,在公式推导中没有-
,但是优化器是用梯度下降进行参数更新,所以使用-
做方向的调整。
Critic
算法通过计算
critic_loss = torch.mean(F.mse_loss(self.critic(states), td_target.detach()))
作为Critic
的误差
一些概念
模型的比较
-
Q-learning、DQN 及 DQN 改进算法都是基于价值(value-based), 他们通过选择最大价值动作来与环境交互
-
Actor-Critic 结合了两者的特点,Reinforce 作为 Actor 部分, DQN 作为 Critic 部分,从而结合了两者的有点
-
Reinforce、Actor-Critic 通过 SARSA 样本数据进行训练,所以他们是 on-policy基于策略,也就是学习一个策略,从策略中进行动作概率分布抽样
-
REINFORCE 算法基于蒙特卡洛采样,只能在序列结束后进行更新, Actor-Critic 算法则可以在每一步之后都进行更新,并且不对任务的步数做限制。
-
TRPO 是在 Actor-Critic 的基础上加入了更新幅度限,也就是制信任区域(trust region),从而避免模型效果的震荡。
-
PPO 是 TRPO 的改良版, 基于 TRPO 的思想,但是 PPO算法实现更加简单,没有TRPO 的计算那么复杂和远算量那么大。
-
PPO 有两种形式,一是 PPO-惩罚,二是 PPO-截断,
-
PPO-截断总是比 PPO-惩罚表现得更好, 大量实验表明。
-
REINFORCE、Actor-Critic 以及两个改进算法——TRPO 和 PPO, 这类算法有一个共同的特点:它们都是在线策略算法,这意味着它们的样本效率(sample efficiency)比较低。
-
TRPO(trust region policy optimization,TRPO)。当策略网络是深度模型时,沿着策略梯度更新参数,很有可能由于步长太长,策略突然显著变差,进而影响训练效果。针对这个问题,考虑在更新时找到一块信任区域(trust region),在这个区域上更新策略时能够得到某种策略性能的安全性保证,这就是信任区域策略优化(trust region policy optimization,TRPO)算法的主要思想。TRPO 算法在 2015 年被提出,它在理论上能够保证策略学习的性能单调性,并在实际应用中取得了比策略梯度算法更好的效果。
TD算法,贝尔曼方程
policy-base 与 value-base
- Policy-Based RL(基于概率)
通过感官分析所处的环境,直接输出下一步要采取的各种动作的概率,然后根据概率采取行动,所以每种动作都有可能被选中,只是可能性不同。如,Policy Gradients等。
- Value-Based RL(基于价值)
输出所有动作的价值,根据最高价值来选择动作。如,Q learning、Sarsa等。(对于不连续的动作,这两种方法都可行,但如果是连续的动作基于价值的方法是不能用的,我们只能用一个概率分布在连续动作中选择特定的动作)。
- Actor-Critic
结合这两种方法建立一种Actor-Critic的方法,基于概率会给出做出的动作,基于价值会对做出的动作的价值二者的综合。
on-policy 与 off-policy
- 无论是在线策略(on-policy)算法还是离线策略(off-policy)算法,都有一个共同点:智能体在训练过程中可以不断和环境交互,得到新的反馈数据。
- 二者的区别主要在于在线策略算法会直接使用这些反馈数据,而离线策略算法会先将数据存入经验回放池中,需要时再采样
On-Policy Learning:
在On-Policy学习中,代理学习并改进当前正在执行的策略。它会根据当前策略收集的数据进行学习,因此策略的改进可能会受到当前策略的限制。On-Policy方法通常用于需要连续决策和探索的情境。
Off-Policy Learning:
在Off-Policy学习中,代理学习一个策略,但同时也可以使用来自不同策略的经验数据。这使得代理可以更灵活地学习,并且可以更有效地重用以前的经验。Off-Policy方法通常更具有样本效率,因为它们可以更好地利用之前的经验。
on-line 与 off-line
-
online RL(在线强化学习) 学习过程中,智能体需要和真实环境进行交互(边玩边学习)。并且在线强化学习可分为on-policy RL和off-policy RL。on-policy(在线策略学习)采用的是当前策略搜集的数据训练模型,每条数据仅使用一次,如,Actor-Critic、Sarsa等。off-policy(离线策略学习)训练采用的数据不需要是当前策略搜集的,如Q learning。
-
offline RL(离线强化学习) 学习过程中,不与真实环境进行交互,只从过往经验(dataset)中直接学习,而dataset是采用别的策略收集的数据,并且采集数据的策略并不是近似最优策略。。
Online Learning:在线学习是指代理在与环境互动的同时学习。它不断地采集经验,并根据当前的经验进行学习和决策。Online学习适用于需要实时决策的情境,但它也可能导致学习过程中的探索成本。
Offline Learning:离线学习是指代理在与环境互动之前收集一些经验数据,然后在离线状态下进行学习。这样可以避免在线学习的探索成本,但需要足够多的先前数据来训练模型。Offline学习在某些情况下更稳定,但可能无法应对快速变化的环境。
model-base 与 model-free
Model-Based Learning: 在Model-Based学习中,代理(学习者)试图建立一个关于环境的模型,该模型可以预测状态转移和奖励。代理使用这个模型来规划和执行动作,以最大化预期奖励。Model-Based方法通常需要较多的计算资源来构建和维护环境模型。
Model-Free Learning: 在Model-Free学习中,代理不试图建立环境模型,而是直接学习策略或价值函数,以根据观察到的经验来进行动作选择。Model-Free方法通常更适用于复杂或不确定的环境,因为它们不需要对环境进行精确的建模。基于值函数的方法 DQN、基于策略的方法 REINFORCE 以及两者结合的方法 Actor-Critic。
Q-learning 与 Sarsa
Q learning 与 Sarsa 由于TD算法实际内容上存在的差异,导致了其对样本数据利用的不同。Q learning 能够使用Exprience replay 而 Sarsa 不能使用Exprience replay
参考
Q-learning的目标是求解“真正”的 Q ∗ ( s , a ) Q^{*}(s,a) Q∗(s,a) ,而Sarsa的目标则是求解 Q π ( s , a ) Q_\pi(s,a) Qπ(s,a) 。
在Q-learning中,我们一般会采用experience replay技术,即准备一个数据库并不断把Agent新产生的 ( s , a , r , s ′ ) (s,a,r,s^{\prime}) (s,a,r,s′) 数据集存入数据库中。我们每次会从数据库中随机抽取一个batch的数据集用以训练,这意味着每次训练时我们用到的数据集可能是Agent在很久以前产生的。但是,无论我们用到的数据是Agent在训练中的哪一个阶段产生的,数据都是服从环境分布的,所以它们当然都可以被用以训练。在Sarsa中,情况则与Q-learning很不一样。对于 ( s , a , r , s ′ , a ′ ) (s,a,r,s',a') (s,a,r,s′,a′) 的训练数据集,我们不但要求 ( r , s ′ ) (r,s^{\prime}) (r,s′) 应该服从环境分布,也要求 a ′ a^{\prime} a′ 必须服从 π \pi π 关于 s ′ s^{\prime} s′ 的条件分布。在训练中,Q表的内容会不断被改变,所以Agent产生数据的策略 也会不断被改变。这意味在Agent过去产生的 ( s , a , r , s ′ , a ′ ) (s,a,r,s',a') (s,a,r,s′,a′) 中, ( s ′ , a ′ ) (s^{\prime},a^{\prime}) (s′,a′) 可能不服从现在策略 π \pi π 对应的条件分布,因此Agent在过去产生的数据就不能用以现在的训练。
由于上述的原因,我们不能在Sarsa中采用experience replay。在训练中,设当前Agent产生数据的策略为 π \pi π
。我们可以一次性用Agent产生大量服从环境及 π \pi π 分布的数据,并用这些数据来进行训练。而训练过后,Q表的内容发生了变化,这意味着Agent产生数据的策略变成了与 π \pi π 不同的 π ′ \pi^{\prime} π′ 。这时,刚才那些服从环境与 π \pi π 分布的 ( s , a , r , s ′ , a ′ ) (s,a,r,s',a') (s,a,r,s′,a′) 数据就变得不再有价值,我们只能将其丢弃。接下来,我们就要让Agent用当前产生数据的策略 继续产生大量的数据,并进行下一步的训练。
我们将Q-learning中那种experience replay的训练方式称作off-policy的,而将Sarsa中这种“边学边玩”的训练方式称作on-policy的。不难看出,二者的核心差别就在于off-policy方法中我们只是要求数据服从于环境分布,而on-policy方法中我们却要求数据要服从环境与当前策略的分布。如果只要求数据服从环境分布,由于过去产生的数据都是服从环境分布的,所以我们当前可以将其储存下来多次利用;如果要求数据服从环境与当前策略分布,由于训练中我们的策略可能会一直发生改变,用过去策略产生的数据很可能无法用于当前的训练,所以我们的数据就不能被多次利用。
区别
-
off-line 在现实生活中的许多场景下,让尚未学习好的智能体和环境交互可能会导致危险发生,或是造成巨大损失。例如,在训练自动驾驶的规控智能体时,如果让智能体从零开始和真实环境进行交互,那么在训练的最初阶段,它操控的汽车无疑会横冲直撞,造成各种事故。再例如,在推荐系统中,用户的反馈往往比较滞后,统计智能体策略的回报需要很长时间。而如果策略存在问题,早期的用户体验不佳,就会导致用户流失等后果。因此,离线强化学习(offline reinforcement learning)的目标是,在智能体不和环境交互的情况下,仅从已经收集好的确定的数据集中,通过强化学习算法得到比较好的策略。
-
On-Policy和Off-Policy 是关于策略评估和改进的方式。二者的区别主要在于在线策略算法会直接使用这些反馈数据,而离线策略算法会先将数据存入经验回放池中,需要时再采样。
-
Model-Based和Model-Free 是关于如何对环境建模和学习的方法。Model-Based建立模型,Model-Free直接学习策略或价值函数。
https://blog.csdn.net/niulinbiao/article/details/134081800
https://blog.csdn.net/qq_43585760/article/details/133557729
https://wjrsbu.smartapps.cn/pages/article/index?id=602217717
https://zhuanlan.zhihu.com/p/166412379
https://hrl.boyuai.com/chapter/2/actor-critic%E7%AE%97%E6%B3%95