RL论文阅读1- 从PG到AC、A3C和A2C的理论推导+tensorflow2.0代码实现

A3C.2016 and A2C

Tittle

在这里插入图片描述

source

标签

  • Model-free
  • Policy-based/Value-based
  • On-policy/Off-policy
  • Continuous State Space
  • Discrete Action Space
  • Support High-dim Input

总结

针对的问题

简单的online RL算法和深度神经网络结合是不稳定的。
解决这种不稳定的方法有很多例如比较有效的就是经验回放。然而经验回放只能使用off-policy算法,需要大量内存和计算资源,而且可能使用一些old policy产生的数据去replay。

解决方法

提出新的解决方法。多个agent并行与环境交互产生数据。
关键思想

  • 对固定长度(例如20步)的经验片段进行操作,通过计算经验片段的return和Advantage function来更新。
  • 在policy和value function 之间共享参数的结构
  • 异步更新

这篇论文提出的是一种异步学习的框架,可以适用于one-step Q-learning/n-step Q-learning、one-step Sarsa/n-step Sarsa、和actor-critic类算法。

其中,应用到actor-critic类算法中,叫做A3C。

A3C: Asynchronous Advantage Actor Critic

A2C: Advantage Actor Critic

在A3C基础上,又衍生出A2C。 A2C是同步算法,在每次更新时,等待每个actor都完产出他的经验片段。这个的有点是能够更有效的使用GPUs。使用大的batch size。一般来说,效果好于A3C

优点

  • On-policy和Off-policy都适用
  • 更快,相比experience replay
  • 连续和离散动作空间懂能用。
    在这里插入图片描述

原理

PG(Policy Gradient):

agent和Env的某个交互序列

Env: s1 -> agent: a1 -> Env: s2 -> agent-> a2 …

得到交互序列:Trajectory τ = { s 1 , a 1 , s 2 , a 2 , . . . , s T , a T } \tau = \{s_1,a_1,s_2,a_2,...,s_T,a_T\} τ={s1,a1,s2,a2,...,sT,aT}

那么我们得到完全一样的交互序列的 概率 p θ ( τ ) p_\theta(\tau) pθ(τ) 是多少?
p θ ( τ ) = p ( s 1 ) p θ ( a 1 ∣ s 1 ) p ( s 2 ∣ s 1 , a 1 ) p θ ( s 3 ∣ s 2 , a 2 ) . . . = p ( s 1 ) ∏ t = 1 T p θ ( a t ∣ s t ) p ( s t + 1 ∣ s t , a t ) p_\theta(\tau) = p(s_1)p_{\theta}(a_1|s_1)p(s_2|s_1,a_1)p_{\theta}(s_3|s_2,a_2)... \\ = p(s_1) \prod_{t=1}^{T}p_\theta(a_t|s_t)p(s_{t+1}|s_t,a_t) pθ(τ)=p(s1)pθ(a1s1)p(s2s1,a1)pθ(s3s2,a2)...=p(s1)t=1Tpθ(atst)p(st+1st,at)

p θ p_\theta pθ: 在某个状态下,产生某个动作的概率

p p p Env 的转换概率, 具有马尔科夫性。状态转换只和上次状态相关。

R ( τ ) R(\tau) R(τ)为整个序列的奖励的和。(无衰减)

agent在该策略( π θ \pi_\theta πθ)下的奖励综合的数学期望为:
R θ ‾ = ∑ τ R ( τ ) p θ ( τ ) = E τ ∼ p θ ( τ ) [ R ( τ ) ] \overline{R_\theta} = \sum_\tau R(\tau)p_\theta(\tau) = E_{\tau \sim p_\theta(\tau)}[R(\tau)] Rθ=τR(τ)pθ(τ)=Eτpθ(τ)[R(τ)]

注意: 这里是指所有轨迹所获的奖励的数学期期望。 τ \tau τ 只代表某一个具体序列。

可见,总奖励的数学期望 R θ ‾ \overline{R_\theta} Rθ越大,说明我们的策略越好。目标就是最大化 R θ ‾ \overline{R_\theta} Rθ,使用梯度下降
∇ R θ ‾ = ∑ τ R ( τ ) ∇ p θ ( τ ) = ∑ τ R ( τ ) p θ ( τ ) ∇ p θ ( τ ) p θ ( τ ) = ∑ τ R ( τ ) p θ ( τ ) ∇ log ⁡ p θ ( τ ) \nabla \overline{R_\theta} = \sum_\tau R(\tau) \nabla p_\theta(\tau) \\ =\sum_\tau R(\tau) p_\theta(\tau) \frac{\nabla p_\theta(\tau)}{p_\theta(\tau)} \\ =\sum_\tau R(\tau) p_\theta(\tau) \nabla \log p_\theta(\tau) Rθ=τR(τ)pθ(τ)=τR(τ)pθ(τ)pθ(τ)pθ(τ)=τR(τ)pθ(τ)logpθ(τ)

  1. ∇ f ( x ) = f ( x ) ∇ log ⁡ f ( x ) \nabla f(x) = f(x) \nabla \log f(x) f(x)=f(x)logf(x) 就是那个导数公式, log底数为e

  2. 求和符号和概率 p θ ( τ ) p_\theta(\tau) pθ(τ)拿出来,就是数学期望

= E τ ∼ p θ ( τ ) [ R ( τ ) ∇ log ⁡ p θ ( τ ) ] = E_{\tau \sim p_\theta(\tau)}[R(\tau) \nabla \log p_\theta(\tau)] \\ =Eτpθ(τ)[R(τ)logpθ(τ)]

假设有N组序列, τ ( 1 ) . . . τ ( n ) \tau^{(1)}...\tau^{(n)} τ(1)...τ(n),且认为每个序列产生的次数相等

≈ 1 N ∑ n = 1 N R ( τ ( n ) ) ∇ log ⁡ p θ ( τ ( n ) ) \approx \frac{1}{N} \sum_{n=1}^N R(\tau^{(n)}) \nabla \log p_\theta(\tau^{(n)}) \\ N1n=1NR(τ(n))logpθ(τ(n))

把上面计算单饿 p θ ( τ ) = p ( s 1 ) ∏ t = 1 T p θ ( a t ∣ s t ) p ( s t + 1 ∣ s t , a t ) p_\theta(\tau)= p(s_1) \prod_{t=1}^{T}p_\theta(a_t|s_t)p(s_{t+1}|s_t,a_t) pθ(τ)=p(s1)t=1Tpθ(atst)p(st+1st,at) 带入上式,整理:

= 1 N ∑ n = 1 N ∑ t = 1 T n R ( τ ( n ) ) ∇ log ⁡ p θ ( a t n ∣ s t n ) = \frac{1}{N} \sum_{n=1}^N \sum_{t=1}^{T_n}R(\tau^{(n)}) \nabla \log p_\theta(a_t^n|s_t^n) =N1n=1Nt=1TnR(τ(n))logpθ(atnstn)

上式就是策略参数的梯度。

PG算法的缺点:

  • 需要一个完整的序列
  • 在一个总奖励的期望较高的序列中,可能存在个别的很差的动作a。由于我们优化目标是总奖励尽可能高,优化时会忽视这个问题。 造成的结果就是,为了得到最优策略,我们很多次采样来消除个别差的动作干扰。

AC:

AC aka Actor和Critic。

PG算法必须要一个完整的序列,才能够计算出来 R t R_t Rt, 是基于Monte Carlo算法的。

为了解决PG的两个缺点,把算法转移到TD-learning上。

解决的办法就是使用 Q ( s n , a n ) Q(s^{n},a^{n}) Q(sn,an)值来代替 R ( τ ( n ) ) R(\tau^{(n)}) R(τ(n))。这个Q值是由神经网络产生的。我们不在需要等完整的序列,只需要把响应的动作状态传到Q网络(critic)中,询问Q值,就可以大致判断出动作好坏。

存在两个网络,一个是Actor, 产生动作。

  • Actor: π ( s ; θ ) \pi(s;\theta) π(s;θ)

    • 参数: θ \theta θ

    • Input: States

    • Output: action(可以是连续的,如ddpg算法)

    • 优化梯度:
      1 N ∑ n = 1 N ∑ t = 1 T n Q ( s ( n ) , a ( n ) ) ∇ log ⁡ p θ ( a t ( n ) ∣ s t ( n ) ) \frac{1}{N} \sum_{n=1}^N \sum_{t=1}^{T_n}Q(s^{(n)},a^{(n)}) \nabla \log p_\theta(a_t^{(n)}|s_t^{(n)}) N1n=1Nt=1TnQ(s(n),a(n))logpθ(at(n)st(n))

      p θ ( a t n ∣ s t n ) p_\theta(a_t^n|s_t^n) pθ(atnstn) 就是 π ( a t n ∣ s t n ; θ ) \pi(a_t^n | s_t^n ; \theta) π(atnstn;θ)

  • Critic: Q ( s , a ; w ) Q(s,a; w) Q(s,a;w)

    • 参数: w w w

    • Input: Status 和 Action

    • Output:Q-value

    • 优化参数:

      就是希望Critic给出的结果和实际的结果之间误差最小。

      这里面target Q使用 r t n + max ⁡ a t + 1 n Q π θ ( s t + 1 n , a t + 1 n ) r_t^n + \max_{a^n_{t+1}}Q^{\pi_\theta}(s^n_{t+1},a^n_{t+1}) rtn+maxat+1nQπθ(st+1n,at+1n)估计。这里和DQN的target一样,只是没有乘以 γ \gamma γ。乘以也可以。

      J ( w ) = 1 N ∑ n = 1 N ∑ t = 1 T n ( r t n + max ⁡ a t + 1 n Q π θ ( s t + 1 n , a t + 1 n ) − Q π θ ( s t n , a t n ) ) 2 J(w) = \frac{1}{N} \sum_{n=1}^N \sum_{t=1}^{T_n} (r_t^n + \max_{a^n_{t+1}}Q^{\pi_\theta}(s^n_{t+1},a^n_{t+1})- Q^{\pi_\theta}(s_t^n,a_t^n))^2 J(w)=N1n=1Nt=1Tn(rtn+at+1nmaxQπθ(st+1n,at+1n)Qπθ(stn,atn))2

N : N组采样的序列,batch size

T n T_n Tn:每一组序列有多少步,可以是1步,也可以是n步。

优化方法:

Actor网络负责产生动作a,Critic网络负责使用Q-Value来评价这个动作好坏。

A2C和A3C的原理支撑:

AC算法虽然解决了单步学习的问题

A2C和AC相比,引入了Advantage function.

什么是Advantage function??

对于AC算法,收敛不稳定。

Q ( s , a ; w ) Q(s,a;w) Q(s,a;w)加入一个baseline,一般这个baseline是 V ( s ; θ ) V(s;\theta) V(s;θ)

那么Actor的优化梯度为:
1 N ∑ n = 1 N ∑ t = 1 T n ( Q ( s ( n ) , a ( n ) ) − V ( s ; θ ) ) ∇ log ⁡ p θ ( a t ( n ) ∣ s t ( n ) ) \frac{1}{N} \sum_{n=1}^N \sum_{t=1}^{T_n}(Q(s^{(n)},a^{(n)})-V(s;\theta)) \nabla \log p_\theta(a_t^{(n)}|s_t^{(n)}) N1n=1Nt=1Tn(Q(s(n),a(n))V(s;θ))logpθ(at(n)st(n))

N组

T n T_n Tn

Q ( s ( n ) , a ( n ) ) − V ( s n ; θ ) Q(s^{(n)},a^{(n)})-V(s^n;\theta) Q(s(n),a(n))V(sn;θ)就是优势函数A。

难道,,,,我们同时需要Q和V两个网络来做critic么??不用,使用TD-error来估计

TD error δ t = R t + γ Q ( S t + 1 , A t + 1 ) − Q ( S t , A t ) \delta_t = R_{t} + \gamma Q(S_{t+1}, A_{t+1}) - Q(S_t, A_t) δt=Rt+γQ(St+1,At+1)Q(St,At)

R t n + γ V π ( s t + 1 n ) − V π ( s t n ) 代 替 Q π ( s t n , a t n ) − V ( s n ) R_t^n + \gamma V^\pi(s_{t+1} ^n)-V^\pi(s_t^n) 代替Q^\pi(s^n_t,a^n_t)-V(s^n) Rtn+γVπ(st+1n)Vπ(stn)Qπ(stn,atn)V(sn)

会增加一定的方差,可以忽略不计。

Actor:
  • 策略 π ( a t ∣ s t ; θ ) \pi(a_t|s_t;\theta) π(atst;θ)actor

    • 本身参数 θ \theta θ

    • 函数 π \pi π的Input是状态 s t s_t st

    • output: 在状态 s t s_t st下,动作 a t a_t at的概率

  • 策略函数的(actor)更新梯度

    • ∇ θ ′ log ⁡ π ( a t ∣ s t ; θ ′ ) A ( s t , a t ; θ , θ v ) \nabla_{\theta'}\log \pi(a_t|s_t;\theta')A(s_t, a_t; \theta,\theta_v) θlogπ(atst;θ)A(st,at;θ,θv)

    • (可选)通过阻止过早的收敛到次优策略,可以目标函数中加入策略的熵,从而提升探索能力(Williams & Peng,1991)。 所以:
      ∇ θ ′ log ⁡ π ( a t ∣ s t ; θ ′ ) A ( s t , a t ; θ , θ v ) + β ∇ θ ′ H ( π ( s t ; θ ′ ) ) \nabla_{\theta'}\log \pi(a_t|s_t;\theta')A(s_t, a_t; \theta,\theta_v) + \beta \nabla_{\theta'}H(\pi(s_t; \theta')) θlogπ(atst;θ)A(st,at;θ,θv)+βθH(π(st;θ))

      H是熵。

      β \beta β控制熵的正则化强度。

  • 优势函数(advantage function) A ( s t , a t ; θ , θ v ) A(s_t, a_t; \theta, \theta_v) A(st,at;θ,θv)

    • 在这里插入图片描述

    • 从状态 s 1 s_1 s1开始,采样了 k k k 步。下标如上图:

      • A ( s k − 1 , a k − 1 ) = r k − 1 + γ V ( S k ; θ v ) − V ( s k − 1 ; θ v ) A(s_{k-1}, a_{k-1}) = r_{k-1} + \gamma V(S_{k};\theta_v) - V(s_{k-1};\theta_v) A(sk1,ak1)=rk1+γV(Sk;θv)V(sk1;θv)

      • A t ( s k − 2 , a k − 2 ) = r k − 2 + γ r k − 1 + γ 2 V ( S k ; θ v ) − V ( S k − 2 ; θ v ) A_t(s_{k-2}, a_{k-2}) = r_{k-2} + \gamma r_{k-1}+ \gamma^2 V(S_{k};\theta_v) - V(S_{k-2};\theta_v) At(sk2,ak2)=rk2+γrk1+γ2V(Sk;θv)V(Sk2;θv)

      • A ( s 0 , a 0 ) = r 0 + γ r 2 + γ 2 r 3 . . . + γ k − 2 r k − 1 + γ k − 1 V ( s k ; θ v ) − V ( S 0 ; θ v ) A({s_0,a_0}) = r_0 + \gamma r_2 + \gamma^2 r_3 ... + \gamma^{k-2}r_{k-1} + \gamma^{k-1}V(s_{k};\theta_v) - V(S_{0};\theta_v) A(s0,a0)=r0+γr2+γ2r3...+γk2rk1+γk1V(sk;θv)V(S0;θv)

      注: 这里的k和上文的 T n T_n Tn代表的同一个东西。

    注:可以认为奖励是离开 S t S_t St后,获得奖励 r t r_t rt

    注: 论文中的原版中符号和此处略有差异。但是表达的意思相同。

    A ( s t , a t ) = R t − V ( S t ; θ ) A(s_t,a_t) = R_t -V(S_t;\theta) A(st,at)=RtV(St;θ)

    R t R_t Rt 为状态t的return。

  • 在更新时,使用累计梯度更新。(应该是为了提高data efficiency)

    对于某个采样序列 τ = { s 1 , a 1 , s 2 , a 2 , . . . , s k , a k } \tau = \{s_1,a_1,s_2,a_2,...,s_k,a_k\} τ={s1,a1,s2,a2,...,sk,ak}
    d θ τ = ∑ t = 0 k − 1 ∇ θ ′ log ⁡ π ( a t ∣ s t ; θ ′ ) A ( s t , a t ; θ , θ v ) d\theta^\tau = \sum_{t=0} ^{k-1}\nabla_{\theta'}\log \pi(a_t|s_t;\theta')A(s_t, a_t; \theta,\theta_v) dθτ=t=0k1θlogπ(atst;θ)A(st,at;θ,θv)

    A为优势函数

Actor在Continues Action 连续动作空间处理

我们的梯度更新函数所使用的 π ( a t ∣ s t ; θ ) \pi(a_t|s_t;\theta) π(atst;θ)代表的是状态s下选择a动作的概率。

对于离散的动作空间,actor网络直接输出的是各个动作的概率,所以直接就可以用。

但是对于连续的动作空间,actor网络需要输出的是两个参数 μ \mu μ σ \sigma σ

# example
in = keras.layers.Input(shape=input_state_shape)
layer = keras.layers.Dense(units=64,activation=tf.nn.relu)(input)
layer = keras.layers.Dense(units=64, activation=tf.nn.relu)(layer)

# 使用tanh,保证在0-1之间
mu = keras.layers.Dense(units=action_dim, activation=tf.nn.tanh, name='mu')(layer)
sigma = keras.layers.Dense(units=action_dim, activation=tf.nn.softplus, name='sigma')(layer) 
model = keras.models.Model(inputs=in, outputs=[mu, sigma], name=name)

然后使用生成的 μ , σ \mu, \sigma μ,σ来构造正态分布norm_dist

动过a的获得:

  • 所得到的 μ \mu μ 范围在0-1之间,再乘以动作的范围,就可以得到Actor的预测动作。

  • 在探索时,只需要服从这个正态分布对横坐标进行一个采样。(在 μ \mu μ附近概率较大,越远概率越小。),通过增大 σ \sigma σ可以增加探索率。

  • 如果有多个连续的动作空间,那么就需要多组正态分布

动作a在策略 π \pi π下概率的计算( π ( a t ∣ s t ; θ ) \pi(a_t |s_t;\theta) π(atst;θ))

  • 动作 a t a_t at是已知的(采样序列中的)

  • 通过Actor对状态s生成响应的正态分布norm_dist

  • 求动作 a t a_t at在这个正态分布中的概率(其实就是算一个积分。从负无穷到 a t a_t at

注:在tensorflow_probability包中有直接生成正态分布、采样、某一点的概率、某一点概率的对数(这个求梯度用的到)的响应函数。

import tensorflow_probability as tp
tfd = tp.distributions
a = tfd.Normal(0.2,2) # 生成正态分布
a.log_prob(x) # 计算x在正态分布a下的概率的log值
Critic
  • 状态价值函数 V ( s t ; θ v ) V(s_t; \theta_v) V(st;θv) critic

    • 自身参数 θ \theta θ

    • input: s t s_t st

    • output: V,代表某个状态的价值。

  • 状态价值函数的优化(critic)

    • cost function:(实际状态价值和估计状态价值的均方误差)
      J ( θ ) = 1 N ∑ 1 N ( ∑ i = 0 k − 1 γ i r t + i + γ T n V ( s t + k ; θ v ) − V ( s i ; θ ) ) 2 = 1 N ∑ 1 N ∑ 1 T n ( R t − V ( s i ; θ ) ) 2 J(\theta)=\frac{1}{N} \sum_1^N {(\sum^{k-1}_{i=0} \gamma^ir_{t+i} + \gamma^{Tn}V(s_{t+k};\theta_v)-V(s_i;\theta))^2} \\ =\frac{1}{N} \sum_1^N \sum_1^{T_{n}} {(R_t - V(s_i;\theta))^2} J(θ)=N11N(i=0k1γirt+i+γTnV(st+k;θv)V(si;θ))2=N11N1Tn(RtV(si;θ))2

      N个 batch size

      T_n步长

      V ( s i ; θ ) V(s_i;\theta) V(si;θ)实际状态价值

    R t R_t Rt是Return,不是Reward!!!

    • g r a d = ∂ ( R − V ( s i ; θ v ′ ) ) 2 ∂ θ v ′ grad = \frac{\partial(R-V(s_i; \theta_v'))^2}{\partial \theta_v'} grad=θv(RV(si;θv))2

A3C的架构:

在这里插入图片描述

  • 多个agent一起跑、
  • 所有agent共跑 T m a x T_{max} Tmax步后,统一更新所有agent的参数 θ ′ \theta' θ
  • 每个agent跑了 t m a x t_{max} tmax步或者停止后,对 d θ ′ d\theta' dθ d θ v ′ d\theta'_v dθv进行一次累加。并更新到全局target
  • 用累加的梯度来更新全局的目标 θ 、 θ v \theta、\theta_v θθv
    在这里插入图片描述

A2C架构

在这里插入图片描述

代码实现:

Github
Pendulum-v0测试环境Reward图

  • 蓝色为A2C
  • 橙色为A3C
    在这里插入图片描述

reference

  1. 原版论文
  2. Blog
  3. David Silver强化学习笔记
  4. 李宏毅强化学习课程
  5. Tensorlayer官方例程
  • 5
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
以下是基于RL78/F12的I2C从机实现代码示例,仅供参考: ```c #include "iodefine.h" // I2C从机地址 #define I2C_SLAVE_ADDRESS 0x50 // 数据缓冲区大小 #define BUFFER_SIZE 16 unsigned char tx_buffer[BUFFER_SIZE]; unsigned char rx_buffer[BUFFER_SIZE]; // I2C从机中断服务程序 #pragma vector = INTI2C0_vect __interrupt void i2c_slave_interrupt(void) { unsigned char data; unsigned char status; // 获取I2C中断状态 status = IICS0; // 接收到读取请求 if (status & 0x01) { // 从数据缓冲区中读取数据,发送给主机 data = tx_buffer[0]; tx_buffer++; IICD0 = data; } // 接收到写入请求 if (status & 0x02) { // 从主机接收数据,保存到数据缓冲区 data = IICD0; rx_buffer[0] = data; rx_buffer++; } // 清除中断标志位 IICS0 &= ~(0x07); } void init_i2c_slave(void) { // 配置I2C从机模块 IICAMK0 = 1; // 关闭I2C从机中断 IICAIF0 = 0; // 清除I2C从机中断标志位 IICAM0 = I2C_SLAVE_ADDRESS; // 设置I2C从机地址 IICMK0 = 0; // 开启I2C总线中断 IICIF0 = 0; // 清除I2C总线中断标志位 // 初始化数据缓冲区 for (int i = 0; i < BUFFER_SIZE; i++) { tx_buffer[i] = i; rx_buffer[i] = 0; } // 开启I2C从机模块 IICCTL01 |= 0x01; } int main(void) { // 初始化I2C从机 init_i2c_slave(); // 主循环 while (1) { // do something } return 0; } ``` 在这个示例代码中,I2C从机地址被设置为0x50,数据缓冲区大小为16字节。在初始化函数`init_i2c_slave()`中,先配置了相关寄存器,然后初始化了数据缓冲区并开启了I2C从机模块。在主循环中,可以添加其他的代码逻辑。需要注意的是,I2C从机中断服务程序`i2c_slave_interrupt()`中的代码需要根据具体的应用场景进行修改。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值