【深度强化学习】3. 表格型方法

news/2024/5/18 22:17:08 标签: 强化学习, 人工智能, 算法

【DataWhale打卡】百度的强化学习课程,通俗易懂,主要讲了Q-Learning,例子很多,生动形象。

1. Q-table概念

Q-table类似生活手册,在遇到一种特定的状态,会提供不同的动作,并且可以知道对应的价值。
Q ( S , A ) Q(S,A) Q(S,A)
我们可以为每一个状态(state)上进行的每一个动作(action)计算出最大的未来奖励(reward)的期望。

2. SARSA


这个公式就是说可以拿下一步的 Q 值 Q ( S t + 1 , A t + 1 ) Q(S_{t+_1},A_{t+1}) Q(St+1,At+1) 来更新我这一步的 Q 值 Q ( S t , A t ) Q(S_t,A_t) Q(St,At)

为了理解这个公式,如上图所示,我们先把 R t + 1 + γ Q ( S t + 1 , A t + 1 ) R_{t+1}+\gamma Q\left(S_{t+1}, A_{t+1}\right.) Rt+1+γQ(St+1,At+1) 当作是一个目标值,就是 Q ( S t , A t ) Q(S_t,A_t) Q(St,At)想要去逼近的一个目标值。我们想要计算的就是 Q ( S t , A t ) Q(S_t,A_t) Q(St,At)因为最开始 Q 值都是随机初始化或者是初始化为零,它需要不断地去逼近它理想中真实的 Q 值,我们就叫 target 。Target 就是带衰减的未来收益的总和。

我们用 G t G_t Gt 来表示未来收益总和(return),并且对它做一下数学变化:
G t = R t + 1 + γ R t + 2 + γ 2 R t + 3 + γ 3 R t + 4 + ⋯ = R t + 1 + γ ( R t + 2 + γ R t + 3 + γ 2 R t + 4 + ⋯   ) = R t + 1 + γ G t + 1 \begin{aligned} G_{t} &=R_{t+1}+\gamma R_{t+2}+\gamma^{2} R_{t+3}+\gamma^{3} R_{t+4}+\cdots \\ &=R_{t+1}+\gamma\left(R_{t+2}+\gamma R_{t+3}+\gamma^{2} R_{t+4}+\cdots\right) \\ &=R_{t+1}+\gamma G_{t+1} \end{aligned} Gt=Rt+1+γRt+2+γ2Rt+3+γ3Rt+4+=Rt+1+γ(Rt+2+γRt+3+γ2Rt+4+)=Rt+1+γGt+1
就可以知道 G t = R t + 1 + γ G t + 1 G_t = R_{t+1}+ \gamma G_{t+1} Gt=Rt+1+γGt+1

Q ( S t , A t ) Q(S_t,A_t) Q(St,At) 来逼近 G t G_t Gt,那 Q ( S t + 1 , A t + 1 ) Q(S_{t+1},A_{t+1}) Q(St+1,At+1) 其实就是近似 G t + 1 G_{t+1} Gt+1。我就可以用 Q ( S t + 1 , A t + 1 ) Q(S_{t+1},A_{t+1}) Q(St+1,At+1) 近似 G t + 1 G_{t+1} Gt+1,然后把 R t + 1 + Q ( S t + 1 , A t + 1 ) R_{t+1}+Q(S_{t+1},A_{t+1}) Rt+1+Q(St+1,At+1)当成目标值。

算法由于每次更新值函数需要知道当前的状态(state)、当前的动作(action)、奖励(reward)、下一步的状态(state)、下一步的动作(action),由此得名 Sarsa 算法。它走了一步之后,拿到了 ( S t , A t , R t + 1 , S t + 1 , A t + 1 ) (S_{t}, A_{t}, R_{t+1}, S_{t+1}, A_{t+1}) (St,At,Rt+1,St+1,At+1)之后,就可以做一次更新。

Sarsa 是一种 on-policy 策略。Sarsa 优化的是它实际执行的策略,它直接拿下一步会执行的 action 来去优化 Q 表格,所以 on-policy 在学习的过程中,只存在一种策略,它用一种策略去做 action 的选取,也用一种策略去做优化。所以 Sarsa 知道它下一步的动作有可能会跑到悬崖那边去,所以它就会在优化它自己的策略的时候,会尽可能的离悬崖远一点。这样子就会保证说,它下一步哪怕是有随机动作,它也还是在安全区域内。

3. Q-learning

off-policy 在学习的过程中,有两种不同的策略:

  • 第一个策略是我们需要去学习的策略,即target policy(目标策略),一般用 π 来表示,Target policy 就像是在后方指挥战术的一个军师,它可以根据自己的经验来学习最优的策略,不需要去和环境交互。
  • 另外一个策略是探索环境的策略,即behavior policy(行为策略),一般用 μ 来表示。μ 可以大胆地去探索到所有可能的轨迹,采集轨迹,采集数据,然后把采集到的数据喂给 target policy 去学习。而且喂给目标策略的数据中并不需要 A t + 1 A_{t+1} At+1 ,而 Sarsa 是要有 A t + 1 A_{t+1} At+1 的。Behavior policy 像是一个战士,可以在环境里面探索所有的动作、轨迹和经验,然后把这些经验交给目标策略去学习。比如目标策略优化的时候,Q-learning 才不管你下一步去往哪里探索,会不会掉进悬崖,我就只选我收益最大一个最优的策略。

Off-policy learning 有很多优点:

  • 我们可以利用 exploratory policy 来学到一个最佳的策略,学习效率高;
  • 可以让我们学习其他 agent 的行为,模仿学习,学习人或者其他 agent 产生的轨迹;
  • 重用老的策略产生的轨迹。探索过程需要很多计算资源,这样的话,可以节省资源。

Q-learning 的算法有两种 policy:behavior policy 和 target policy

  • Target policy π 直接在 Q-table 上取 greedy,就取它下一步能得到的所有状态,(确定性策略)如下式所示:

π ( S t + 1 ) = arg ⁡ max ⁡ a ′   Q ( S t + 1 , a ′ ) \pi\left(S_{t+1}\right)=\underset{a^{\prime}}{\arg \max}~ Q\left(S_{t+1}, a^{\prime}\right) π(St+1)=aargmax Q(St+1,a)

  • Behavior policy μ 可以是一个随机的 policy,但我们采取 ε -greedy \varepsilon\text{-greedy} ε-greedy,让 behavior policy 不至于是完全随机的,它是基于 Q-table 逐渐改进的(探索性策略)。

Target Policy更新公式:
Q ( S t , A t ) ← Q ( S t , A t ) + α [ R t + 1 + γ m a x a Q ( S t + 1 , a ) − Q ( S t , A t ) ] Q(S_t,A_t)←Q(S_t,A_t)+α[R_{t+1}+γmax_a Q(S_{t+1},a)−Q(S_t,A_t)] Q(St,At)Q(St,At)+α[Rt+1+γmaxaQ(St+1,a)Q(St,At)]
Sarsa 和 Q-learning 的更新公式都是一样的,区别只在 target 计算的这一部分,

  • Sarsa 是 R t + 1 + γ Q ( S t + 1 , A t + 1 ) R_{t+1}+\gamma Q(S_{t+1}, A_{t+1}) Rt+1+γQ(St+1,At+1)
  • Q-learning 是 R t + 1 + γ max ⁡ a Q ( S t + 1 , a ) R_{t+1}+\gamma \underset{a}{\max} Q\left(S_{t+1}, a\right) Rt+1+γamaxQ(St+1,a)

Sarsa 是用自己的策略产生了 S,A,R,S’,A’ 这一条轨迹。然后拿着 Q ( S t + 1 , A t + 1 ) Q(S_{t+1},A_{t+1}) Q(St+1,At+1)去更新原本的 Q 值 Q ( S t , A t ) Q(S_t,A_t) Q(St,At)

Q-learning 并不需要知道我实际上选择哪一个 action ,它默认下一个动作就是 Q 最大的那个动作。Q-learning 知道实际上 behavior policy 可能会有 10% 的概率去选择别的动作,但 Q-learning 并不担心受到探索的影响,它默认了就按照最优的策略来去优化目标策略,所以它可以更大胆地去寻找最优的路径,它会表现得比 Sarsa 大胆非常多。

4. On-policy vs Off-policy

  • Sarsa 是一个典型的 on-policy 策略,它只用了一个 policy π 。如果 policy 采用 ε-greedy 算法的话,它需要兼顾探索,为了兼顾探索和利用,它训练的时候会显得有点胆小怕事。它在解决悬崖问题的时候,会尽可能地离悬崖边上远远的,确保说哪怕自己不小心探索了一点,也还是在安全区域内。此外,因为采用的是 ε-greedy 算法,策略会不断改变(ε 会不断变小),所以策略不稳定。
  • Q-learning 是一个典型的 off-policy 的策略,它有两种策略:target policy 和 behavior policy。它分离了目标策略跟行为策略。Q-learning 就可以大胆地用 behavior policy 去探索得到的经验轨迹来去优化目标策略,从而更有可能去探索到最优的策略。Behavior policy 可以采用 ε-greedy 算法,但 target policy 采用的是 greedy 算法,直接根据 behavior policy 采集到的数据来采用最优策略,所以 Q-learning 不需要兼顾探索。
  • 比较 Q-learning 和 Sarsa 的更新公式可以发现,Sarsa 并没有选取最大值的 max 操作。
    • 因此,Q-learning 是一个非常激进的算法,希望每一步都获得最大的利益;
    • 而 Sarsa 则相对非常保守,会选择一条相对安全的迭代路线。

参考文献

https://datawhalechina.github.io/leedeeprl-notes/#/chapter3/chapter3?id=temporal-difference

https://mp.weixin.qq.com/s/34E1tEQMZuaxvZA66_HRwA

https://www.bilibili.com/video/BV1yv411i7xd?p=6


http://www.niftyadmin.cn/n/1003480.html

相关文章

数据库与hibernate锁机制

数据库中的锁机制锁是网络数据库中的一个非常重要的概念,它主要用于多用户环境下保证数据库完整性和一致性。各种大型数据库所采用的锁的基本理论是一致的,但在具体实现上各有差别。目前,大多数数据库管理系统都或多或少具有自我调节、自我管…

线程信号量操作

为兼容jdk1.5之前版本的信号量操作:1.Semahpore2package com.jzy.thread; import java.util.Random; import java.util.Vector; //信号量 public class Semahpore {private Vector locksnew Vector(); //保存线程private int permitNum1; //允许的的信号量数pri…

【深度强化学习】4. Policy Gradient

【Datawhale打卡】十一的时候自己看过一遍,李宏毅老师讲的很好,对数学小白也很友好,但是由于没有做笔记(敲代码),看完以后脑袋里空落落的。趁着这次打卡活动,重新看一遍,果然好多细节…

Kinect for windows语音识别(Speech)

Kinect for windows提供了语音识别的能力,它靠Kinect的语音采集流进行识别的,这是建立在微软的语音识虽库的基础上的,关于微软语音识别可以参考http://msdn.microsoft.com/en-us/library/hh361572(voffice.14).aspx。对别Kinect识别的语音&am…

Android入门第九篇之AlertDialog

时隔一年,又要准备做Android的开发了,最近复习和整理一下Android的知识。 这次要说的是AlertDialog,这种对话框会经常遇到。AlertDialog跟WIN32开发中的Dialog不一样,AlertDialog是非阻塞的,而阻塞的对话框用的是Popu…

.NET 性能优化方法总结==转

.NET 性能优化方法总结 目录 目录 1. C#语言方面... 4 1.1 垃圾回收... 4 1.1.1 避免不必要的对象创建... 4 1.1.2 不要使用空析构函数 ★... 4 1.1.3 实现 IDisposable 接口... 4 1.2 String 操作... 5 1.2.1 使用 StringBuilder 做字符串连接... 5 1.2.2 避免不必要的调用 To…

Android入门第十篇之PopupWindow

介绍过AlertDialog之后,接下来就介绍一下PopupWindow这种对话框。PopupWindow是阻塞对话框,只有在外部线程 或者 PopupWindow本身做退出操作才行。PopupWindow完全依赖Layout做外观,在常见的开发中,PopupWindow应该会与 AlertDial…

摘:C语言数字转换为字符串

数字转换为字符串 C语言提供了几个标准库函数&#xff0c;可以将任意类型(整型、长整型、浮点型等)的数字转换为字符串。以下是用itoa()函数将整数转换为字符串的一个例子&#xff1a; # include <stdio. h># include <stdlib. h> void main (void);void main (vo…