Actor-Critic(A2C)算法 原理讲解+pytorch程序实现
文章目录
- 1 前言
- 2 算法简介
- 3 原理推导
- 4 程序实现
- 5 优缺点分析
- 6 使用经验
- 7 总结
1 前言
强化学习在人工智能领域中具有广泛的应用,它可以通过与环境互动来学习如何做出最佳决策。本文将介绍一种常用的强化学习算法:Actor-Critic并且附上基于pytorch实现的代码。
2 算法简介
Actor-Critic算法是一种基于策略梯度(Policy Gradient)和价值函数(Value Function)的强化学习方法,通常被用于解决连续动作空间和高维状态空间下的强化学习问题。该算法将一个Actor网络和一个Critic网络组合在一起,通过Actor网络产生动作,并通过Critic网络估计状态值函数或状态-动作值函数,最终通过策略梯度算法训练Actor网络和Critic网络。Actor-Critic算法的优点是在处理大型状态空间时具有较高的效率和可扩展性。
3 原理推导
对于连续动作和高维状态空间下的强化学习问题,直接使用策略梯度算法的效率可能会比较低,因为其需要对所有的动作做出预测,并找到最大化奖励的动作。为了提高训练效率,我们可以将动作值函数或状态-动作值函数引入到策略梯度算法中,这就是Actor-Critic算法的核心思想。
Actor-Critic算法中的Actor网络用于学习策略,用于生成动作。Critic网络则用于学习值函数,用于评估状态或状态动作对的价值。Actor和Critic网络之间的交互便是Actor-Critic算法的核心机制。
Actor-Critic算法中,我们有两个更新任务:Actor网络的策略梯度更新和Critic网络的值函数更新。对于Actor网络的策略梯度更新,我们需要使用Glearning策略梯度定理根据当前的策略 计算更新梯度,以更新Actor网络的参数;而对于Critic网络的值函数更新,则需要先计算出每一次的Reward,然后使用TD误差计算当前状态值和下一时刻状态值之间的误差,进而更新Critic网络的参数。
在Actor-Critic算法中使用的策略梯度方法是REINFORCE算法,该算法的公式如下:
∇ θ J ( θ ) = E t [ ∇ θ l o g π ( a t ∣ s t ) ( Q π ( s t , a t ) − b t ) ] \nabla_\theta J(\theta) = E_t[\nabla_\theta log\pi(a_t|s_t)(Q^\pi(s_t,a_t) - b_t)] ∇θJ(θ)=Et[∇θlogπ(at∣st)(Qπ(st,at)−bt)]
其中, J ( θ ) J(\theta) J(θ)表示目标策略的性能, ∇ θ J ( θ ) \nabla_\theta J(\theta) ∇θJ(θ)表示策略梯度, π ( a t ∣ s t ) \pi(a_t|s_t) π(at∣st)表示在状态 s t s_t st下选择动作 a t a_t at的概率。
虽然REINFORCE算法在Actor-Critic算法中被广泛使用,但它存在两个问题:高方差和计算效率低。为了解决这两个问题,我们可以引入一个基准函数 B ( s t ) B(s_t) B(st),并将奖励 Q π ( s t , a t ) − B ( s t ) Q^\pi(s_t,a_t) - B(s_t) Qπ(st,at)−B(st)作为更新中的优势函数 A π ( s t , a t ) A^\pi(s_t,a_t) Aπ(st,at),公式变为:
∇ θ J ( θ ) = E t [ ∇ θ l o g π ( a t ∣ s t ) A π ( s t , a t ) ] \nabla_\theta J(\theta) = E_t[\nabla_\theta log\pi(a_t|s_t)A^\pi(s_t,a_t)] ∇θJ(θ)=Et[∇θlogπ(at∣st)Aπ(st,at)]
其中, A π ( s t , a t ) = Q π ( s t , a t ) − B ( s t ) A^\pi(s_t,a_t)=Q^\pi(s_t,a_t)-B(s_t) Aπ(st,at)=Qπ(st,at)−B(st)表示相对于基准函数的优势函数。
参数化的值函数可以通过状态价值函数V(s)或动作价值函数Q(s,a)来表示,取决于我们需要估计的是状态价值函数还是状态-动作价值函数。对于Critic网络的值函数更新,我们可以使用TD误差来计算当前状态值和下一时刻状态值之间的误差:
δ = r + γ V ( s ′ ) − V ( s ) \delta = r + \gamma V(s') - V(s) δ=r+γV(s′)−V(s)
其中 r r r是当前时刻的奖励, γ \gamma γ是折扣因子, V ( s ′ ) V(s') V(s′)是下一时刻的状态值, V ( s ) V(s) V(s)是当前时刻的状态值。我们可以使用每个状态 s s s的TD(Temporal Difference)误差 δ \delta δ的平方来衡量当前值函数 V ( s ) V(s) V(s)的误差,并用该误差更新Critic网络的参数。
Actor-Critic算法中,Actor网络和Critic网络可以使用不同的神经网络架构(如前馈神经网络或卷积神经网络)来表示。Actor网络的输出通常是代表各个动作的概率分布,而Critic网络的输出则是代表状态值或状态-动作值的估计值。Actor网络和Critic网络的优化可以使用不同的优化器(如Adam优化器)和损失函数(如均方误差损失函数)来进行。
以下是Actor-Critic算法的主要步骤:
- 初始化Actor网络和Critic网络的参数
- 接受初始状态 s 0 s_0 s0作为输入,使用Actor网络生成初始动作 a 0 a_0 a0
- 获取下一时刻的状态 s 1 s_1 s1和对应的Reward r 1 r_1 r1
- 使用Critic网络估计当前状态值或状态-动作值,并计算TD误差 δ \delta δ
- 更新Critic网络的参数以减小TD误差
- 使用TD误差 δ \delta δ计算优势函数 A π ( s t , a t ) A^\pi(s_t,a_t) Aπ(st,at)
- 使用REINFORCE算法的策略梯度公式,计算Actor网络的梯度,以提高策略性能
- 使用更新的梯度来更新Actor网络的参数
- 将状态更新为下一状态 s 1 s_1 s1,并返回步骤2。
经过多轮的迭代,Actor和Critic网络的参数将会逐渐趋于最优状态,从而实现高效的连续动作和高维状态空间下的强化学习任务。
4 程序实现
我们将以OpenAI Gym中的CartPole(倒立摆)游戏为应用场景,基于pytorch实现一个基础的Actor-Critic算法,让算法去玩这个游戏。
程序共分为两个文件:
- main.py文件:主要负责调用算法实现整体功能
- model.py文件:主要实现一个完整的Actor-Critic算法
下面是main.py中的程序:
import gym
from model import Actor_Critic
import matplotlib.pyplot as pltif __name__ == "__main__":env = gym.make('CartPole-v0')model = Actor_Critic(env) #实例化Actor_Critic算法类reward = []for episode in range(200):s = env.reset() #获取环境状态env.render() #界面可视化done = False #记录当前回合游戏是否结束ep_r = 0while not done:# 通过Actor_Critic算法对当前环境做出行动a,log_prob = model.get_action(s)# 获得在做出a行动后的最新环境s_,rew,done,_ = env.step(a)#计算当前rewardep_r += rew#训练模型model.learn(log_prob,s,s_,rew)#更新环境s = s_reward.append(ep_r)print(f"episode:{episode} ep_r:{ep_r}")plt.plot(reward)plt.show()
model.py中的程序:
import torch
import torch.nn as nn
import torch.nn.functional as F
import numpy as np
from torch.distributions import Categoricalclass Actor(nn.Module):'''演员Actor网络'''def __init__(self, action_dim, state_dim):super(Actor, self).__init__()self.fc1 = nn.Linear(state_dim, 300)self.fc2 = nn.Linear(300, action_dim)self.ln = nn.LayerNorm(300)def forward(self, s):if isinstance(s, np.ndarray):s = torch.FloatTensor(s)x = self.ln(F.relu(self.fc1(s)))out = F.softmax(self.fc2(x), dim=-1)return outclass Critic(nn.Module):'''评论家Critic网络'''def __init__(self, state_dim):super(Critic, self).__init__()self.fc1 = nn.Linear(state_dim, 300)self.fc2 = nn.Linear(300, 1)self.ln = nn.LayerNorm(300)def forward(self, s):if isinstance(s, np.ndarray):s = torch.FloatTensor(s)x = self.ln(F.relu(self.fc1(s)))out = self.fc2(x)return outclass Actor_Critic:def __init__(self, env):self.gamma = 0.99self.lr_a = 3e-4self.lr_c = 5e-4self.env = envself.action_dim = self.env.action_space.n #获取描述行动的数据维度self.state_dim = self.env.observation_space.shape[0] #获取描述环境的数据维度self.actor = Actor(self.action_dim, self.state_dim) #创建演员网络self.critic = Critic(self.state_dim) #创建评论家网络self.actor_optim = torch.optim.Adam(self.actor.parameters(), lr=self.lr_a)self.critic_optim = torch.optim.Adam(self.critic.parameters(), lr=self.lr_c)self.loss = nn.MSELoss()def get_action(self, s):a = self.actor(s)dist = Categorical(a)action = dist.sample() #可采取的actionlog_prob = dist.log_prob(action) #每种action的概率return action.detach().numpy(), log_probdef learn(self, log_prob, s, s_, rew):#使用Critic网络估计状态值v = self.critic(s)v_ = self.critic(s_)critic_loss = self.loss(self.gamma * v_ + rew, v)self.critic_optim.zero_grad()critic_loss.backward()self.critic_optim.step()td = self.gamma * v_ + rew - v #计算TD误差loss_actor = -log_prob * td.detach()self.actor_optim.zero_grad()loss_actor.backward()self.actor_optim.step()
程序运行结果可视化(游戏效果):
5 优缺点分析
Actor-Critic算法是一种基于策略梯度和值函数的强化学习算法,针对连续动作和高维状态空间等实际应用中较为复杂的强化学习问题,具有以下优缺点:
优点:
- 可大大提升强化学习的效率和稳定性。Actor-Critic算法引入的值函数可以减少强化学习中探索过程中的高方差问题,同时也可以减少算法中的可变性,使得算法更加稳定。
- 支持连续动作和高维状态空间。与传统强化学习算法不同,Actor-Critic算法可以处理连续动作和高维状态空间,因为其基于策略梯度方法。
- 可以适应多个环境。Actor-Critic算法适应多个环境,具有较好的泛化性能。
- 可以灵活选择网络架构和损失函数进行优化。Actor-Critic算法可根据任务需求变换网络架构和损失函数。
缺点:
- 容易陷入局部最优解。由于Actor-Critic算法中存在两个更新任务,因此有可能会陷入局部最优解。
- 训练过程不稳定。在实践中,由于策略梯度算法的高方差问题,Actor-Critic算法可能出现训练过程不稳定的情况。
- 不适合处理超大规模状态空间问题。当状态空间非常大时,Actor-Critic算法的性能可能会受到限制。
- 需要大量的数据训练。由于Actor-Critic算法需要大量的数据进行训练,因此可能需要使用大量的计算资源和时间。
6 使用经验
以下是我对于Actor-Critic算法的使用心得:
- 确定合适的环境复杂度:Actor-Critic算法强调的是在输入态和输出态均较复杂的RL问题中的应用,这里所说的“复杂”是指状态空间和动作空间较大、过程不可预测,需要模型才能完成观测、计算和决策的问题。如果环境越复杂,应用Actor-Critic算法就更有优势,能够有效应对高维空间、连续动作这些常见问题。
- 确定好价值函数和策略函数的网络架构和超参数:Actor-Critic算法中,价值函数和策略函数均需要进行神经网络模型的设计,这里的模型设计和选择会直接对最终的结果产生影响。实际应用过程中,不同的问题、不同的数据性质以及不同的处理方法都可能会导致最终模型的性能表现有所不同。因此,在使用Actor-Critic算法前,一定要先确定好神经网络模型的架构和超参数,以确定最优方案。
- 策略目标的定义:Actor-Critic算法中的 Actor 需要优化经验奖励和当前的信用估计,因此选择合适的策略目标非常重要。常见的策略目标包括任务相关奖励、状态价值、Q 值或漏斗形策略(Policy)。尤其是在多目标优化时,需要明确各个目标之间的优先级和权重。
- 增加探索机制:Actor-Critic算法在处理好网络和输入输出方案后,并不保证结果一定会很好,因此在实践中,还需要增加探索机制以保证算法在前期足够地探索状态空间,避免落入局部最优解。常用的探索机制有ε-贪心和玻尔兹曼探索。
- 监控和调试:Actor-Critic算法存在的问题不一定都很明显(那种直接不收敛),因此需要实时监控算法的性能,确定算法参数和网络架构的调整和优化策略。
总之,应用Actor-Critic算法需要考虑到具体的问题场景和实际需求,确定好应用场景、网络架构、策略目标和探索机制,并且对算法的表现进行监控和调试,才能更好地应用该算法。
7 总结
总体来说,Actor-Critic算法是一种具有广泛适用性的强化学习算法,可以针对多种实际应用场景进行调整和改进。其中,Actor Critic 升级版: Deep Deterministic Policy Gradient、Asynchronous Advantage Actor-Critic (A3C)等都是比较优秀的Actor-Critic改进算法。在工程应用时可以有限考虑这些算法。
Actor-Critic(A2C)算法 原理讲解+pytorch程序实现相关推荐
- AMCL算法原理讲解
ROS进阶教程(二)AMCL算法原理讲解 AMCL算法理解 蒙特卡洛定位算法 蒙特卡洛定位算法自适应变种 里程计运动模型 测距仪模型 波束模型 似然域模型 AMCL算法理解 AMCL(adaptive ...
- 朴素贝叶斯算法原理讲解
朴素贝叶斯算法原理讲解 1 算法抽象性解释 NaïveBayes算法,又叫朴素贝叶斯算法,是基于贝叶斯定理与特征条件独立假设的分类方法. 名称由来:朴素,即特征条ming件独立:贝叶斯:基于贝叶斯定理 ...
- 一文掌握图像超分辨率重建(算法原理、Pytorch实现)——含完整代码和数据
目录 一. 图像超分辨率重建概述 1. 概念 2. 应用领域 3. 研究进展 3.1 传统超分辨率重建算法 3.2 基于深度学习的超分辨率重建算法 二. SRResNet算法原理和Pytorch实 ...
- 一文掌握语义分割PSPNet——证件照制作、抠图(算法原理、Pytorch实现)
目录 一. 语义分割概述 二. PSPNet语义分割原理和Pytorch实现 1. PSPNet算法原理 2. 环境配置 3. 训练数据集处理 4.数据预处理和加载 5. 模型构建 5. 训练 三 ...
- 情感分析学习笔记(5)——PolarityRank算法原理讲解
本文参考的是两篇论文(Fernández-Gavilanes et al., 2016; Cruz et al., 2011)以及PageRank算法(Page et al., 1998) 由于本文内 ...
- SSD系列算法原理讲解----(1)SSD系列算法介绍(主干网络、多尺度Feature Map预测)(笔记)
SSD系列算法原理介绍 SSD算法介绍: Single Shot MultiBox Detector(One-stage方法) - Wei Liu在ECCV 2016提出 - 直接回归目标类别和位置 ...
- (转)KMP算法原理讲解及模板C实现
原作者:v_JULY_v 1. 引言 本KMP原文最初写于2年多前的2011年12月,因当时初次接触KMP,思路混乱导致写也写得混乱.所以一直想找机会重新写下KMP,但苦于一直以来对KMP的理解始终不 ...
- 浅谈KNN算法原理及python程序简单实现、KD树、球树
最近比较空闲,打算利用这一段时间理一下机器学习的一些常见的算法.第一个是KNN算法: KNN 1.原理: KNN,K-NearestNeighbor---K最近邻 K最近邻,就是K个最近的邻居的意思, ...
- SVM算法—原理讲解
原文作者:奔跑的前浪 原文地址:svm算法 最通俗易懂讲解 最近在学习svm算法,借此文章记录自己的学习过程,在学习时很多处借鉴了z老师的讲义和李航的统计,若有不足的地方,请海涵:svm算法通俗的理解 ...
最新文章
- Mac环境下配置Java开发环境(jdk+maven+tomcat+idea)
- emacs 跳转到指定行
- VTK:图表之ColorVerticesLookupTable
- 浅析C语言中assert的用法(转)
- php 7 class 初始化 销毁_在 PHP 中使用和管理 Session
- 95-138-010-源码-Function-KeyedProcessFunction
- java listener 实现机制_Java监听器机制ServletContextListener实现执行某方法函数
- 【VMC实验室】在QCloud上创建您的SQL Cluster(5)
- Cornerstone详细操作
- 关于 Pycharm专业版 安装教程,简单好用
- 推荐几款好用的编程字体
- 计算机网络怎么算默认网关,ip地址子网掩码计算器_默认网关怎么计算_ip 掩码 网关的关系...
- 深入浅出vuejspdf下载_vue下载pdf
- python卡方检验kf_Python 卡方检验
- 我的编程之路点滴记录(四)
- 数控编程也是c语言吗,学数控编程需要使用个人电脑吗
- 自定义ListVIew添加上下更多项
- 三分钟了解企业产品发布会直播全流程
- ORA-3136 WARNING: inbound connection timed out (ORA-3136)
- n8_Visualizing Multivariate_sns_3D plot_matplotlib.dates_mpl_finance_aapl stock_EMA_RSI_Bollinger
热门文章
- 【Linux kernel/CPU idle】CPU Idle ----framework
- Unity 之 UGUI Layout自动布局组件详解
- GNU sed 4.5 版参考文档全文翻译 各命令和随带20个示例详细解析(四)
- $CONDITIONS的作用
- Bootstrap笔记(十一) 表格篇
- 不可多得的干货!mysqlerror2003
- 【Python杂项】with open() as f的用法
- Android 删除aar包中的jar包解决Duplicate class包冲突问题
- 基于Oracl安装用友NC63
- 线称池饱和策略:DiscardOldestPolicy解释