Actor-Critic 网络
实战深度强化学习DQN:理论与实践
基于价值的强化学习算法的核心理念是:在当前状态下评估每个可能动作的价值,并依据价值大小进行选择。如果我们跳过中间环节,则可以直接根据当前状态来决定采取行动。
除了在强化学习领域之外,在另一个重要的算法方面也有显著进展——那就是基于策略梯度的方法(Policy Gradient)。我们之前已经介绍了该算法的基本原理及其实现细节,请建议大家根据自身需求选择性地回顾相关内容:
深度强化学习-Policy Gradient基本实现:https://www.jianshu.com/p/2ccbab48414b
本文介绍了一种称为Actor-Critic算法的方法呢,它融合了前面提到两种算法的核心理念而产生,那么什么是Actor?又是什么呢Critic?它们之间又是如何相互作用并实现协同作用的呢,通过本文内容的学习与分析,请您深入理解这一机制.
本文的主要内容主要学习自莫烦老师的强化学习课程,在哔哩哔哩平台可以看到相关的教学视频:https://www.bilibili.com/video/av16921335/#page=22
1、Actor-Critic算法原理
我们为什么要有Actor-Critic呢,下面的话摘自莫烦老师的文章:
我们已经有了如Q-learning这样卓著的算法, 那么为什么要费心费力地设计出Actor-Critic体系呢? 其根源可追溯至Policy Gradient方法论. 其擅长于在连续动作空间中自然地选择合适的行为方案. 然而Q-learning在这种场景下却显得力不从心. 那么为什么不直接采用Policy Gradient方法呢? 其根源在于Actor-Critic体系中的Critic部分起源于Q-learning或其他基于值的方法. 它能够实现分批更新机制从而显著提升了学习效率. 相比之下传统的Policy Gradient方法采用的是分批更新策略这反而降低了其学习效率
上面的文字不仅阐述了为何发展出Actor-Critic这一类算法的原因,并且进一步说明了该算法的具体运作机制。若读者已经对这一领域有了一定了解,并且打算立即查看代码实现,则无需深入探讨此处内容。由于Actor本质上是一个Policy Network结构,在其运作过程中需要借助奖励惩罚机制来评估不同状态下的动作概率分布。而传统的Policy Gradient方法则要求完整地经历一整个回合(episode)才能计算出这些奖励惩罚值。由此带来的一个问题便是学习效率较低,在许多实际应用中可能需要较长时间才能获得有效的策略。与之相对应的是Critic网络采用基于值的方法进行更新,在每一步操作后即可即时计算当前步骤的奖励惩罚值。在此过程中,Actor持续迭代优化其在各状态下的动作概率分布模型,并根据经验不断改进Critic所依据的价值评估模型。
下图就简单的介绍了Actor-Critic算法的流程:
但Actor-Critic并不是一个完善的算法, 后面还会提到进一步的改进:
该方法包含了两个神经网络模型,在连续的状态空间中进行参数更新。值得注意的是,不同参数更新之间具有相互关联性。这种特性使得该方法难以全面分析问题,并可能导致学习效果不佳。
2、代码解析
本文的GitHub存储位置位于:https://github.com/princewen/tensorflow_practice/tree/master/Basic-Actor-Critic
2.1 Actor
明确Actor的输入
在本研究中,在我们的Actor能够实现单次训练的前提下,在这种情况下,在我们的模型设计中仅需涵盖一个状态、一个动作以及一个奖励:
self.s = tf.placeholder(tf.float32,[1,n_features],name=‘state’)
self.a = tf.placeholder(tf.int32,None,name=‘act’)
self.td_error = tf.placeholder(tf.float32,None,“td_error”)
Actor的网络定义
Actor的神经网络结构和我们的Policy Gradient定义的是一样的,是一个双层的全链接神经网络:
with tf.variable_scope("Actor"):
l1 = tf.layers.dense(
inputs=self.s,
units=20,
activation=tf.nn.relu,
kernel_initializer=tf.random_normal_initializer(mean=0, stddev=0.1),
bias_initializer=tf.constant_initializer(0.1),
name="l1"
)
self.acts_prob = tf.layers.dense(
inputs = l1,
units = n_actions,
activation = tf.nn.softmax,
kernel_initializer = tf.random_normal_initializer(mean=0,stddev=0.1),
bias_initializer = tf.constant_initializer(0.1),
name = 'acts_prob'
)
代码解读
该损失函数源自于Policy Gradient方法论中所提及的经典形式...具体而言,在这一改进版本中将原本基于价值函数(vt)的时间差分估计替换为由Critic网络计算得出的时间差分误差(td_error)作为损失函数的核心计算单元。
Using the tf.variable_scope named ‘exp_v’, we perform the following computations: first, we calculate the log probability of the action taken, which is stored in self.acts_prob at index [0, a]. Then, we update the experience value by computing the mean of the product between log probability and the temporal difference error.
with tf.变量命名空间('train'):
self.train_op = tf.Adam优化器(lr).最小化(-self.exp_v)
Actor优化过程
通过输入状态、动作及时间差分值到网络中进行优化。
def learn(self,s,a,td):
s = s[np.newaxis,:]
feed_dict = {self.s:s,self.a:a,self.td_error:td}
_,exp_v = self.sess.run([self.train_op,self.exp_v],feed_dict=feed_dict)
return exp_v
选择动作
选择动作和Policy Gradient一样,根据计算出的softmax值来选择动作
def choose_action(self, s):
将输入向量s扩展为二维数组以便后续计算。
使用图灵机模型计算在当前状态s下的所有可能动作的概率分布probs。
通过调用self.sess.run方法获取具体的动作概率值。
最后从这个概率分布中生成一个随机动作索引并返回。
2.2 Critic
定义Critic输入
Critic需要将时间差分值传递给Actor作为评估和指导其选择动作的关键指标。具体而言,在这一过程中,如果计算出的时间差分值较大,则预示该动作在当前状态下具有较高的吸引力或兴奋度。为了优化这个过程,Critic应通过增加更多的训练样本来降低这种高差异带来的不确定性,从而逐步缩小与理想目标之间的差距。详细阐述时间差分(TD)的具体计算过程,包括其在强化学习框架中的理论基础和实际应用方法,有助于更好地理解整个机制的工作原理。其中,TD算法的核心在于通过递归更新机制不断逼近真实的价值函数,从而实现对复杂环境下的智能体行为进行有效的预测和控制。Critic网络的主要任务就是从经验中学习状态价值函数的变化规律,并通过这一过程帮助Actor做出更加明智的选择。值得注意的是,Critic的输入并不包含明确的动作信息(如动作A),因为这些信息是由Actor自主选择并执行的行为表现出来的自然结果。此外,为什么不能直接使用下一个时刻的状态来进行Q值计算呢?这是因为我们在计算TD误差时已经将下一个状态的信息融入到了神经网络模型中以获得相应的Q估计值,这使得我们无需单独处理下一状态的信息即可完成价值评估的过程。通过这种方式,Critic能够高效地学习并适应复杂多变的环境特性
自定义说明部分请勿输出
自定义说明部分请勿输出
同Actor一样,我们的Critic也是一个双层的神经网络结构。
within the critic module:
assigning a dense layer named l1 to the network
from the state vector s
with 20 hidden units
using ReLU activation function
kernel weights are initialized with a normal distribution (mean=0, std=0.1)
biases are initialized to a constant value of 0.1
as layer l1
self.v = tf.layers.dense(
inputs = l1,
units = 1,
activation = None,
kernel_initializer=tf.random_normal_initializer(0,0.1),
bias_initializer = tf.constant_initializer(0.1),
name = 'V'
)
代码解读
定义损失
Critic的损失定义为时间差分值的平方值
定义一个名为squared_TD_error的作用域:
计算td_error等于r加上gamma乘以v_再减去v:
损失函数被定义为td_error的平方:
通过定义一个变量_scope来进行训练:
通过Adam优化器对损失函数进行最小化操作。
**监督评估者(Critic)的主要职责是评估并反馈Actor所采取的行为质量。具体操作时,我们只需获取相关的TD值,并将它们传递给Actor进行行为更新。
def learn(self,s,r,s_):
s,s_ = s[np.newaxis,:],s_[np.newaxis,:]
v_ = self.sess.run(self.v,feed_dict = {self.s:s_})
td_error,_ = self.sess.run([self.td_error,self.train_op],
feed_dict={self.s:s,self.v_:v_,self.r:r})
return td_error
代码解读
2.3 整体模型训练
基于Critic的存在,Actor能够完成相应的训练与更新过程。由此可见,在整个训练流程的关键代码如下。
循环开始:
actor选择动作:
环境根据动作返回新状态、奖励、是否结束以及额外信息。
计算值函数梯度:
更新策略参数:
更新当前状态为新状态。
3.参考资料
https://morvanzhou.github.io/tutorials/machine-learning/reinforcement-learning/6-1-actor-critic/
