优势演员-评论家(Advantage Actor-Critic,A2C)算法详解与实现
- 
- [0. 前言](#0. 前言)
 - [1. Advantage Actor-Critic (A2C) 算法原理](#1. Advantage Actor-Critic (A2C) 算法原理)
 - [2. A2C 算法流程](#2. A2C 算法流程)
 - [3. 实现 A2C](#3. 实现 A2C)
 
 
0. 前言
在强化学习领域,演员-评论家 (Actor-Critic)方法融合策略优化与价值评估,是解决复杂决策问题的重要框架。基于这一基础,优势演员-评论家 (Advantage Actor-Critic, A2C) 算法通过三个关键创新实现了性能提升:采用回合制更新替代在线学习,引入优势函数精准评估行动价值,并使用均方误差优化价值网络。此外,算法通过策略熵正则项促进探索,有效防止策略过早收敛。本节将深入解析 A2C 的理论基础,详述其与演员-评论家和 REINFORCE算法的核心差异,并使用 Keras 实现 A2C。
1. Advantage Actor-Critic (A2C) 算法原理
在演员-评论家 (Actor-Critic)方法中,其目标在于让价值函数能够准确评估状态价值。训练价值网络还存在其他技术,一种简单的方法是在价值函数优化中采用均方误差 (mean square error, MSE),这与Q学习中的算法类似。新的价值梯度等于回报 ( R t R_t Rt) 与状态价值之间均方误差的偏导数:
∇ V ( θ v ) = ∂ ( R t − 𝑉 ( s , θ v ) ) 2 ∂ θ v \nabla V(\theta_v) = \frac {\partial(R_t- 𝑉(s,\theta_v))^2}{\partial\theta_v} ∇V(θv)=∂θv∂(Rt−V(s,θv))2
当 ( R t − 𝑉 ( s , θ v ) ) → 0 (R_t- 𝑉(s,\theta_v)) \rightarrow 0 (Rt−V(s,θv))→0 时,价值网络对给定状态回报的预测会越来越精确。我们将演员-评论员算法的这种变体称为优势演员-评论家 (Advantage Actor-Critic, A2C)。A2C 是异步优势演员-评论家 (Asynchronous Advantage Actor-Critic, A3C) 的单线程或同步版本。量值 ( R t − 𝑉 ( s , θ v ) ) (R_t- 𝑉(s,\theta_v)) (Rt−V(s,θv)) 称为优势量。
2. A2C 算法流程
以下算法流程总结了 A2C 方法。A2C 与演员-评论家 (Actor-Critic)存在几点差异:演员-评论家采用在线学习方式,即基于每个经验样本进行训练;而 A2C 则与蒙特卡洛算法、REINFORCE 算法及带基线的 REINFORCE 算法类似,是在完成整个回合后才进行训练。演员-评论家从初始状态训练至终止状态,A2C 则从终止状态开始训练至初始状态。此外,A2C 的策略梯度和价值梯度不再使用 γ t \gamma^t γt 进行折现计算。
为增强智能体在训练过程中的探索能力,A3C 算法提出在梯度函数中引入策略函数加权熵值的梯度项 β ∇ θ H ( π ( a t ∣ s t , θ ) ) \beta\nabla_\theta H(\pi(a_t|s_t,\theta)) β∇θH(π(at∣st,θ))。需要说明的是,熵是衡量事件信息量或不确定性的指标。
定义可微参数化目标策略网络 π ( a t ∣ s t , θ ) \pi(a_t|s_t,\theta) π(at∣st,θ) 与可微参数化价值网络 V ( s t , θ v ) V(s_t,\theta_v) V(st,θv);设定折扣因子 γ ∈ [ 0 , 1 ] \gamma∈[0,1] γ∈[0,1],性能梯度学习率 α \alpha α,价值梯度学习率 α v \alpha_v αv,以及熵权重 β \beta β;初始化策略网络参数 θ 0 \theta_0 θ0 与价值网络参数 θ v 0 \theta_{v_0} θv0
重复执行
依据策略 π ( a t ∣ s t , θ ) \pi(a_t|s_t,\theta) π(at∣st,θ) 生成完整轨迹 ( s 0 a 0 r 1 s 1 , s 1 a 1 r 2 s 2 , . . . , s t − 1 a t − 1 r t s t ) (s_0a_0r_1s_1, s_1a_1r_2s_2, ..., s_{t-1}a_{t-1}r_ts_t) (s0a0r1s1,s1a1r2s2,...,st−1at−1rtst)
计算终止状态回报: R t = { 0 s T 为终止状态 V ( s T , θ v ) 对于非终止状态 s T , 从最终状态开始进行自举法估计 R_t=\begin{cases}0 & s_T为终止状态\\ V(s_T,θ_v) & 对于非终止状态 s_T, 从最终状态开始进行自举法估计 \end{cases} Rt={0V(sT,θv)sT为终止状态对于非终止状态sT,从最终状态开始进行自举法估计
从最后一步 t = T − 1 t=T-1 t=T−1 反向遍历至初始状态 t = 0 t=0 t=0:
计算累计回报: R t = r t + γ R t R_t = r_t + \gamma R_t Rt=rt+γRt
计算价值梯度: ∇ V ( θ v ) = ∂ ( R t − V ( s , θ v ) ) 2 ∂ θ v \nabla V(\theta _v) = \frac {\partial (R_t - V(s,\theta _v))²}{\partial \theta _v} ∇V(θv)=∂θv∂(Rt−V(s,θv))2
累积价值梯度更新: θ v = θ v + α v ∇ V ( θ v ) \theta _v = \theta _v + \alpha _v\nabla V(\theta _v) θv=θv+αv∇V(θv)
计算策略梯度: ∇ J ( θ ) = ∇ θ l n π ( a t ∣ s t , θ ) ( R t − V ( s , θ v ) ) + β ∇ θ H ( π ( a t ∣ s t , θ ) ) \nabla J(\theta) = \nabla _\theta ln\pi(a_t|s_t,\theta)(R_t - V(s,\theta _v)) + \beta \nabla _\theta H(\pi(a_t|s_t,\theta)) ∇J(θ)=∇θlnπ(at∣st,θ)(Rt−V(s,θv))+β∇θH(π(at∣st,θ))
执行梯度上升: θ = θ + α ∇ J ( θ ) \theta = \theta + \alpha \nabla J(\theta) θ=θ+α∇J(θ)
3. 实现 A2C
接下来,使用 Keras 实现 A2CAgent 类。与两种 REINFORCE 方法不同,本算法从最终经验单元反向计算至初始状态。在每个经验单元处,目标函数网络 logp_model 和价值函数网络 value_model 分别通过调用 fit() 方法进行优化。需要注意的是,在对象实例化时,熵损失权重 beta 设置为 0.9 以启用熵损失函数,且 value_model 采用均方误差损失函数进行训练。
            
            
              python
              
              
            
          
          class A2CAgent(PolicyAgent):
    def __init__(self,env):
        super().__init__(env)
        #beta of entropy used in A2C
        self.beta = 0.9
        #loss function of A2C value_model is mse
        self.loss = 'mse'
    
    def train_by_episode(self,last_value=0):
        #implements A2C training from the last state
        #to the first state
        #discount factor
        gamma = 0.95
        r = last_value
        #the memory is visited in reverse
        for item in self.memory[::-1]:
            [step,state,next_state,reward,done] = item
            #compute the return
            r = reward + gamma * r
            item = [step,state,next_state,r,done]
            #train pre step
            #a2c reward has been discounted
            self.train(item)
        
    def train(self,item,gamma=1.0):
        [step,state,next_state,reward,done] = item
        #must save state for entropy computation
        self.state = state
        discount_factor = gamma ** step
        #a2c: delta = discounted_reward - value
        delta = reward - self.value(state)[0]
        discounted_delta = delta * discount_factor
        discounted_delta = np.reshape(discounted_delta,[-1,1])
        verbose = 1 if done else 0
        #train the logp model (implies training of actor model 
        # as well) since they share exactly the same set of parameters
        self.logp_model.fit(np.array(state),
                discounted_delta,
                batch_size=1,
                epochs=1,
                verbose=verbose)
        
        #in A2C, the target value is the return (reward
        # replaced by return in train_by_episode function)
        discounted_delta = reward
        discounted_delta = np.reshape(discounted_delta,[-1,1])
        #train the value network (critic)
        self.value_model.fit(np.array(state),
                discounted_delta,
                batch_size=1,
                epochs=1,
                verbose=verbose)