1. 前言

虽然将深度学习和加强学习结合的想法在几年前就有人尝试,但真正成功的开端就是DeepMind在NIPS 2013上发表的 Playing Atari with Deep Reinforcement Learning 一文,在该文中第一次提出Deep Reinforcement Learning 这个名称,而且提出DQN(Deep Q-Network)算法,实现从纯图像输入彻底经过学习来玩Atari游戏的成果。以后DeepMind在Nature上发表了改进版的DQN文章Human-level Control through Deep Reinforcement Learning,引发了普遍的关注,Deep Reinfocement Learning 今后成为深度学习领域的前沿研究方向。github

智能体 Agent 来表示一个具有行为能力的物体,好比机器人,无人车,人等等。算法

那么加强学习考虑的问题就是智能体Agent和 环境 Environment 之间交互的任务。网络

好比一个机械臂要拿起一个手机,那么机械臂周围的物体包括手机就是环境,机械臂经过外部的好比摄像头来感知环境,而后机械臂须要输出动做来实现拿起手机这个任务。再举玩游戏的例子,好比咱们玩极品飞车游戏,咱们只看到屏幕,这就是环境,而后咱们输出动做(键盘操做)来控制车的运动。app

那么,无论是什么样的任务,
都包含了一系列的:dom

  • 动做 Action
  • 观察 Observation
  • 反馈值 Reward

所谓的Reward就是Agent执行了动做与环境进行交互后,环境会发生变化,变化的好与坏就用Reward来表示。函数

接下来这里用了Observation观察一词而不是环境那是由于Agent不必定能获得环境的全部信息,好比机械臂上的摄像头就只能获得某个特定角度的画面。所以,只能用Observation来表示Agent获取的感知信息。oop

只能用 Observation 来表示 Agent 获取的感知信息post

每一个时间片,Agent 都是根据当前的观察来肯定下一步的动做。观察 Observation 的集合就做为Agent的所处的 状态 State,所以,状态 State动做 Action 存在映射关系,也就是一个 state 能够对应一个 action,或者对应不一样动做的几率(经常用几率来表示,几率最高的就是最值得执行的动做)。状态与动做的关系其实就是输入与输出的关系,而状态 State 到动做 Action 的过程就称之为一个策略 Policy,通常用 \(\pi\) 表示,也就是须要找到如下关系: 学习

$$a=\pi(s)$$

或者

$$\pi(a|s)$$

其中 a 是 action,s 是 state
第一种是一一对应的表示,第二种是几率的表示。

加强学习的任务就是找到一个最优的策略Policy从而使Reward最多

咱们一开始并不知道最优的策略是什么,所以每每从随机的策略开始,使用随机的策略进行试验,就能够获得一系列的状态,动做和反馈:

$$\{s_1,a_1,r_1,s_2,a_2,r_2,…s_t,a_t,r_t\}$$

这就是一系列的 样本 Sample。加强学习的算法就是须要根据这些样原本改进 Policy,从而使得获得的样本中的 Reward 更好。因为这种让 Reward 愈来愈好的特性,因此这种算法就叫作加强学习Reinforcement Learning。

 

2. 马尔科夫决策过程

MDP只须要用一句话就能够说明白,就是 “将来只取决于当前”,专业点说就是下一步的状态只取决于当前的状态,与过去的状态没有关系。

一个状态 \(S_t\) 是Markov当且仅当:

$$P(s_{t+1}|s_t)=P(s_{t+1}|s_t,s_{t-1},…s_1,s_0)$$

P为几率。简单的说就是下一个状态仅取决于当前的状态和当前的动做。
加强学习的问题均可以模型化为MDP的问题

所以 MDP 能够表示为一个元组 \((S, A, P_{sa}, R)\) :

  • \(S\) :全部可能状态的集合, \(s \in S\),\(s\) 表示某个特定状态
  • \(A\) :针对每一个状态,咱们都要作出动做,这些动做的集合就是 \(A\); \(a \in A\),有限动做 action 集合, \(a\) 表示某个特定动做
  • \(P_{sa}\) :状态转换分布(statetransition distribution),若是咱们在状态 \(s\) 中采起了动做 \(a\) ,系统会转移到一个新的状态,状态转换分布描述了转移到哪一个状态的几率分布。
  • \(R\) :回馈函数(rewardfunction),加强学习的核心概念,描述了动做可以产生的回报。好比 \(R_π(s,a)\) 描述了在状态 \(s\) 下采用策略 \(\pi\) 所对应的动做 \(a\) 的回报,也叫作当即回报,回馈函数能够有不一样的表达形式。
  • \(\pi(s)\rightarrow a\): 策略 policy,根据当前 state 来产生 action,可表现为 \(a=\pi(s) \) 或 \( \pi(a|s) = P[a|s]\),后者表示某种状态下执行某个动做的几率

一个基本的 MDP 能够用 \((S,A,P)\) 来表示, \(S \) 表示状态, \(A\) 表示动做, \(P \) 表示状态转移几率,也就是根据当前的状态 \(s_t\) 和 \(a_t\) 转移到 \(s_{t+1}\) 的几率。

若是咱们知道了转移几率 P,也就是称为咱们得到了 模型 Model,有了模型,将来就能够求解,那么获取最优的动做也就有可能,这种经过模型来获取最优动做的方法也就称为 Model-based 的方法。可是现实状况下,不少问题是很可贵到准确的模型的,所以就有 Model-free 的方法来寻找最优的动做。

 

3. 价值函数

既然一个状态对应一个动做,或者动做的几率,而有了动做,下一个状态也就肯定了。这就意味着每一个状态能够用一个肯定的值来进行描述。能够由此判断一个状态是好的状态仍是很差的状态。

可是在选取最优策略的过程当中,咱们只看当即回报并不能断定哪一种策略更优,咱们但愿的是在采起了策略 \(\pi\) 之后,可使得整个状态序列的折扣回馈最大。

状态的好坏其实等价于对将来回报的指望,回报 Return 来表示某个时刻 t 的状态将具有的回报:

$$G_t = R_{t+1} + \lambda R_{t+2} + … = \sum_{k=0}^\infty\lambda^kR_{t+k+1}$$
  • R 是 Reward 反馈
  • \(λ\) 是 discount factor 折扣因子,通常小于 1,就是说通常当下的反馈是比较重要的,时间越久,影响越小。

其中 \(λ\) 被称为折扣因子,在经济学上的解释叫作无风险折现率(risk-freeinterest rate),意思是立刻获得的钱(回馈)比将来获得钱更有价值。

以上概念就组成了加强学习的完整描述:找到一种策略,使得咱们可以根据状态 \(s_0, s_1, s_2, …\) 采起策略中对应的动做 \(a_0, a1, a2…,\) 并使 \(G_t\) 的指望值最大化

引出价值函数,对于获取最优的策略Policy这个目标,咱们就会有两种方法:

  • 直接优化策略 \(\pi(a|s)\) 或者 \(a = \pi(s)\) 使得回报更高
  • 经过估计 value function 来间接得到优化的策略。道理很简单,既然我知道每一种状态的优劣,那么我就知道我应该怎么选择了,而这种选择就是咱们想要的策略。

可是如今为了理解DQN,咱们将只关注第二种作法,就是估计value function的作法,由于DQN就是基于value function的算法。

  1. 状态价值函数 \(V\) :从状态 \(x_0\) 开始, 全部的动做 \(a\) ,都是执行某个策略 \(π\) 的结果,最后求每一个动做带来累积奖赏
  2. 动做价值函数 \(Q\) :从状态 \(x_0\) 开始,先执行动做 \(a_0\) , 而后再执行某个策略 \(π\) ,再求相应的积累奖赏

 

3.1 State-Value function 状态价值函数

那么实际上除非整个过程结束,不然显然咱们没法获取全部的 reward 来计算出每一个状态的Return,所以,再引入一个 概念价值函数 Value Function,用 value function \(v(s)\) 来表示一个状态将来的潜在价值。

从定义上看,value function 就是回报的指望:

$$v(s) = \mathbb E[G_t|S_t = s]$$

$$V^{\pi}(s) =\mathbb E_{\pi}[ R(s_0, a_0) + γR(s_1, a_1)+ γ^2R(s_2, a_2) + … | s_0= s ]$$

这个函数也被称为状态价值函数(statevalue function),记为 \(V_{\pi}(s)\)。 由于初始状态 \(s\) 和策略 \(\pi\) 是咱们给定的,动做 \(a = \pi(s)\) 。

 

3.2 Action-Value function 动做价值函数

咱们更关心在某个状态下的不一样动做的价值。显然。若是知道了每一个动做的价值,那么就能够选择价值最大的一个动做去执行了。

这就是 Action-Value function \(Q^\pi(s,a)\) 。那么一样的道理,也是使用 reward 来表示,只是这里的 reward 和以前的 reward 不同:

这里是执行完动做 action 以后获得的 reward,以前 state 对应的 reward 则是多种动做对应的 reward 的指望值。显然,动做以后的 reward 更容易理解。

那么,有了上面的定义,动做价值函数就为以下表示:

$$ Q^{\pi}(s,a) = \mathbb E[R_{t+1}+\lambda R_{t+2} + \lambda ^2R_{t+3} + …|S_t = s,A_t=a]$$

$$
\begin{align}
Q^\pi(s,a) & = \mathbb E[r_{t+1} + \lambda r_{t+2} + \lambda^2r_{t+3} + … |s,a] \\
& = \mathbb E_{s^\prime}[r+\lambda Q^\pi(s^\prime,a^\prime)|s,a]
\end{align}
$$

这里要说明的是动做价值函数的定义,加了 \(\pi\) ,也就是说是在策略下的动做价值。由于对于每个动做而已,都须要由策略根据当前的状态生成,所以必须有策略的支撑。而前面的价值函数则不必定依赖于策略。固然,若是定义 \(v^\pi(s)\) 则表示在策略 \(\pi\) 下的价值。

那么事实上咱们会更多的使用动做价值函数而不是价值函数,由于动做价值函数更直观,更方便应用于算法当中。

 

4. Bellman 方程

在上文咱们介绍了 Value Function 价值函数,因此为了解决加强学习的问题,一个显而易见的作法就是咱们须要估算 Value Function。是的,只要咱们可以计算出价值函数,那么最优决策也就获得了。所以,问题就变成了如何计算 Value Function?

$$P^a_{ss\prime} = P(S_{t+1}=s\prime|S_t =s, A_t =a)$$

还记得回报 Result 的基本定义吗?就是全部 Reward 的累加(带衰减系数 discount factor)

$$G_t = R_{t+1} + \lambda R_{t+2} + … = \sum_{k=0}^\infty\lambda^kR_{t+k+1}$$

那么 Value Function 该如何定义?也很简单,就是指望的回报啊!指望的回报越高,价值显然也就越大,也就越值得去选择。用数学来定义就是以下:

$$v(s) = \mathbb E[G_t|S_t = s]$$

$$v_{\pi}=\sum_{a\in A}P(a|s)\left(R^a_s+\lambda\sum_{s\prime \in S}P^a_{ss\prime}v_{\pi}(s\prime)\right)$$

接下来,咱们把上式展开以下:

$$
\begin{align}
v(s) & = \mathbb E[G_t|S_t = s] \\
& = \mathbb E[R_{t+1}+\lambda R_{t+2} + \lambda ^2R_{t+3} + …|S_t = s] \\
& = \mathbb E[R_{t+1}+\lambda (R_{t+2} + \lambda R_{t+3} + …)|S_t = s] \\
& = \mathbb E[R_{t+1} + \lambda G_{t+1}|S_t = s] \\
& = \mathbb E[R_{t+1} + \lambda v(S_{t+1})|S_t = s]
\end{align}
$$

所以,

$$v(s) = \mathbb E[R_{t+1} + \lambda v(S_{t+1})|S_t = s]$$

上面这个公式就是Bellman方程的基本形态。从公式上看,当前状态的价值和 下一步的价值以及当前的反馈Reward有关。

它代表Value Function是能够经过迭代来进行计算的!!!

总结一下:

$$v_{\pi}(s) = \mathbb E[R_{t+1} + \lambda v_{\pi}(S_{t+1})|S_t = s]$$

$$ q_{\pi}(s,a) = \mathbb E_{\pi}[R_{t+1} +\lambda q_\pi(S_{t+1},A_{t+1})|S_t =s,A_t = a]$$

 

5. 最优化

动态规划

先简单介绍一下动态规划,由于严格来讲,值迭代与策略迭代是用来解决动态规划问题的两种规划方法。而强化学习又有另一个昵称——就是拟动态规划。说白了强化学习就是模拟动态规划算法。

用一句话来总结动态规划就是,对一个复杂问题给出一个通常性的解决办法。它主要由两个性质:

  • 最优子结构:最优解法能被分解到多个子问题中
  • 重叠子问题:子问题能重复屡次且解法能被重复利用、

马尔科夫决策过程(MDP)知足以上两个性质,因此任何 MDP 均可以用动态规划来解。动态规划与强化学习的区别就是动态规划假设 MDP 模型是全知的(即参数可知) 而 强化学习可使 MDP 未知

MDP须要解决的问题有两种:

  • 第一种是 prediction,它已知MDP的 \(S,A,P,R,γ\) 以及 policy,目标是算出在每一个状态下的 value function(值函数其实就是问题的目标,通常都是跟 reward 有关的函数,例如 Atari 小游戏,通常值函数就是累计的得分的指望。目标通常就是最大化这个值函数。
  • 而第二种是control,它已知 MDP 的 \(S,A,P,R,γ\) 可是 policy 未知(即动做 \(a_t\) 未知),所以它的目标不只是计算出最优的 value function 并且要给出最优的 Policy。

5.1 Optimal value function 最优价值函数

能计算动做价值函数是不够的,由于咱们须要的是最优策略,如今求解最优策略等价于求解最优的 value function,找到了最优的 value function,天然而然策略也就是找到。(固然,这只是求解最优策略的一种方法,也就是 value-based approach,因为 DQN 就是 value-based,所以这里只讲这部分,之后咱们会看到还有 policy-based 和 model-based 方法。一个就是直接计算策略函数,一个是估计模型,也就是计算出状态转移函数,从而整个MDP过程得解)

首先是最优动做价值函数和通常的动做价值函数的关系:

$$V^*(s,a) = \max_\pi V^\pi(s,a)$$

$$Q^*(s,a) = \max_\pi Q^\pi(s,a)$$

也就是最优的动做价值函数就是全部策略下的动做价值函数的最大值。经过这样的定义就可使最优的动做价值的惟一性,从而能够求解整个MDP。

那么套用上一节获得的 value function,能够获得

$$Q^*(s,a) = \mathbb E_{s^\prime}[r+\lambda \max _{a^\prime}Q^*(s^\prime,a^\prime)|s,a]$$

由于最优的Q值必然为最大值,因此,等式右侧的Q值必然为使 \(a′\) 取最大的Q值。

下面介绍基于Bellman方程的两个最基本的算法,策略迭代和值迭代。




5.2 Policy Iteration 策略迭代

策略迭代就是在policy未知的状况下,根据每次的reward学到最优policy。

对一个具体的 MDP 问题,每次先初始化一个策略,根据这个策略计算值函数 \(v(s)\) , 经过这个re值函数来根据贪心策略更新策略,不断迭代最终获得最优策略与最优值函数。总结下来就两个阶段。

  • Policy evaluation :根据每一次的给出策略估计 \(v_π\)
  • Policy improvement:根据 Greedy poilcy 和以前获得的 \(v_π\) 得到当前策略 \(π′\)

Policy Iteration的目的是经过迭代计算value function 价值函数的方式来使policy收敛到最优。














给一个例子:

下图是一个叫 Small Gridworld 的例子,左上角和右下角是终点, \(γ=1\) ,移动一步 reward 减小1,起始的 random policy 是朝每一个能走的方向几率相同,先单独看左边一列,它表示在第 \(k\) 次迭代每一个 state上value function 的值,这一列始终采用了 random policy,这里的 value function 就是经过 Bellman Expectation Equation 获得的,考虑 \(k=2\) 的状况, \(-1.7 = -1.0 + 2\times (1/3.0)(-1)\),\(-2.0 = -1.0 + 4(1/4.0)\times (-1)\) 。而右边一列就是在当前的 value function 状况下经过 greedy 算法找到当前朝哪一个方向走更好。








Policy Iteration 本质上就是直接使用 Bellman 方程而获得的:



5.3 Value Iteration 价值迭代

Value Iteration 则是使用 Bellman 最优方程获得:



而后改变成迭代形式:




值迭代就是在已知 policy 和 MDP 模型的状况下,根据策略得到最优值函数和最优策略。
只不过这是肯定策略,在值函数 \(v_π\) 取得最大值的 \(a_t\) (策略)
经过每次迭代bellman方程得到 \(v_i\) , 知道值函数收敛。图解以下:




 

6. Q-Value (Quality-Value)

Q Learning的思想彻底根据value iteration获得。但要明确一点是value iteration每次都对全部的Q值更新一遍,也就是全部的状态和动做。但事实上在实际状况下咱们没办法遍历全部的状态,还有全部的动做,咱们只能获得有限的系列样本。所以,只能使用有限的样本进行操做。那么,怎么处理?Q Learning提出了一种更新Q值的办法:

$$Q(S_{t},A_{t}) \leftarrow Q(S_{t},A_{t})+\alpha({R_{t+1}+\lambda \max _aQ(S_{t+1},a)} - Q(S_t,A_t))$$

虽然根据value iteration计算出target Q值,可是这里并无直接将这个Q值(是估计值)直接赋予新的Q,而是采用渐进的方式相似梯度降低,朝target迈近一小步,取决于α,这就可以减小估计偏差形成的影响。相似随机梯度降低,最后能够收敛到最优的Q值。

具体的算法以下:



大体代码流程以下:

def update():
    # 学习 100 回合
    for episode in range(100):
        # 初始化 state 的观测值
        observation = env.reset()

        while True:
            # 更新可视化环境
            env.render()

            # RL 大脑根据 state 的观测值挑选 action
            action = RL.choose_action(str(observation))

            # 探索者在环境中实施这个 action, 并获得环境返回的下一个 state 观测值, reward 和 done (是不是掉下地狱或者升上天堂)
            observation_, reward, done = env.step(action)

            # RL 从这个序列 (state, action, reward, state_) 中学习
            RL.learn(str(observation), action, reward, str(observation_))

            # 将下一个 state 的值传到下一次循环
            observation = observation_

            # 若是掉下地狱或者升上天堂, 这回合就结束了
            if done:
                break

    # 结束游戏并关闭窗口
    print('game over')
    env.destroy()

if __name__ == "__main__":
    # 定义环境 env 和 RL 方式
    env = Maze()
    RL = QLearningTable(actions=list(range(env.n_actions)))

    # 开始可视化环境 env
    env.after(100, update)
    env.mainloop()
注意:

每一组 (state, action, reward, state_) 为一次序列



以咱们回到以前的流程, 根据 Q 表的估计, 由于在 s1 中, a2 的值比较大, 经过以前的决策方法, 咱们在 s1 采起了 a2, 并到达 s2, 这时咱们开始更新用于决策的 Q 表, 接着咱们并无在实际中采起任何行为, 而是再想象本身在 s2 上采起了每种行为, 分别看看两种行为哪个的 Q 值大, 好比说 Q(s2, a2) 的值比 Q(s2, a1) 的大, 因此咱们把大的 Q(s2, a2) 乘上一个衰减值 gamma (好比是0.9) 并加上到达s2时所获取的奖励 R (这里尚未获取到咱们的棒棒糖, 因此奖励为 0), 由于会获取实实在在的奖励 R , 咱们将这个做为我现实中 Q(s1, a2) 的值, 可是咱们以前是根据 Q 表估计 Q(s1, a2) 的值. 因此有了现实和估计值, 咱们就能更新Q(s1, a2) , 根据 估计与现实的差距, 将这个差距乘以一个学习效率 alpha 累加上老的 Q(s1, a2) 的值 变成新的值.

但时刻记住, 咱们虽然用 maxQ(s2) 估算了一下 s2 状态, 但尚未在 s2 作出任何的行为, s2 的行为决策要等到更新完了之后再从新另外作. 这就是 off-policy 的 Q learning 是如何决策和学习优化决策的过程.



$$\text{update = learing_rate * (q_target - q_predict)}$$

$$\text{学习率 * (真实值 - 预测值)}$$

咱们想象 Qlearning 的机器人天生近视眼, \(\gamma= 1\) 时, 机器人有了一副合适的眼镜, 在 s1 看到的 Q 是将来没有任何衰变的奖励, 也就是机器人能清清楚楚地看到以后全部步的所有价值, 可是当 \(\gamma= 0\) , 近视机器人没了眼镜, 只能摸到眼前的 reward, 一样也就只在意最近的大奖励, 若是 \(\gamma\) 从 0 变到 1, 眼镜的度数由浅变深, 对远处的价值看得越清楚, 因此机器人渐渐变得有远见, 不只仅只看眼前的利益, 也为本身的将来着想.

 

7. Exploration and Exploitation 探索与利用

在上面的算法中,咱们能够看到须要使用某一个policy来生成动做,也就是说这个policy不是优化的那个policy,因此Q-Learning算法叫作Off-policy的算法。另外一方面,由于Q-Learning彻底不考虑model模型也就是环境的具体状况,只考虑看到的环境及reward,所以是model-free的方法。

回到policy的问题,那么要选择怎样的 policy 来生成 action 呢?有两种作法:

  • 随机的生成一个动做
  • 根据当前的Q值计算出一个最优的动做,这个 policy \(\pi\) 称之为 greedy policy 贪婪策略。也就是 \(\pi(S_{t+1}) = arg\max _aQ(S_{t+1},a)\)

使用随机的动做就是 exploration,也就是探索未知的动做会产生的效果,有利于更新Q值,得到更好的policy。

而使用 greedy policy 也就是 target policy 则是 exploitation,利用policy,这个相对来讲就很差更新出更好的Q值,但能够获得更好的测试效果用于判断算法是否有效。

将二者结合起来就是所谓的 \(\epsilon\ greedy\) 策略, \(\epsilon\) 通常是一个很小的值,做为选取随机动做的几率值。能够更改 \(\epsilon\) 的值从而获得不一样的 exploration 和 exploitation 的比例。例如 \(\epsilon = 0.1\) 表示 90% 的时间是选择最优策略, 10% 的时间来探索.

要注意一点就是 egreedy 的 \(\epsilon\) 是不断变小的,也就是随机性不断变小。怎么理解呢?就是一开始须要更多的探索,因此动做偏随机,慢慢的咱们须要动做可以有效,所以减小随机。也就是愈来愈贪婪。
例如:
INITIAL_EPSILON = 0.5 # starting value of epsilon
FINAL_EPSILON = 0.01 # final value of epsilon

这里须要说明的一点是使用 \(\epsilon-greedy\) 策略是一种极其简单粗暴的方法,对于一些复杂的任务采用这种方法来探索未知空间是不可取的。所以,最近有愈来愈多的方法来改进这种探索机制。

 

8. 详解Q-Learning

8.1 Value Function Approximation 价值函数近似

在简单分析中,咱们使用表格来表示Q(s,a),可是这个在现实的不少问题上是几乎不可行的,由于状态实在是太多。使用表格的方式根本存不下。

咱们有必要对状态的维度进行压缩,解决办法就是 价值函数近似 Value Function Approximation

就是用一个函数来表示Q(s,a),即:

$$Q(s,a) = f(s,a)$$

f能够是任意类型的函数,好比线性函数:

$$Q(s,a) = w_1s + w_2a + b$$
其中 \(w_1,w_2,b\) 是函数 \(f\) 的参数。

经过函数表示,咱们就能够无所谓 \(s\) 究竟是多大的维度,反正最后都经过矩阵运算降维输出为单值的 \(Q\) 。这就是价值函数近似的基本思路。

若是咱们就用 \(w\) 来统一表示函数f的参数,那么就有

$$Q(s,a) = f(s,a,w)$$

为何叫近似,由于咱们并不知道 \(Q\) 值的实际分布状况,本质上就是用一个函数来近似 \(Q\) 值的分布,因此,也能够说是

$$Q(s,a)\approx f(s,a,w)$$

 

8.2 Q值神经网络化!

用一个深度神经网络来表示这个函数 \(f\),即咱们能够将状态和动做当成神经网络的输入, 而后通过神经网络分析后获得动做的 Q 值, 这样咱们就不必在表格中记录 Q 值, 而是直接使用神经网络生成 Q 值.还有一种形式的是这样, 咱们也能只输入状态值, 输出全部的动做值, 而后按照 Q learning 的原则, 直接选择拥有最大值的动做当作下一步要作的动做。通常使用第二种形式。

以DQN为例,输入是通过处理的4个连续的84x84图像,而后通过两个卷积层,两个全链接层,最后输出包含每个动做Q值的向量。

用神经网络来表示Q值很是简单,Q值也就是变成用Q网络(Q-Network)来表示。接下来就到了不少人都会困惑的问题,那就是怎么训练Q网络???

咱们知道,神经网络的训练是一个最优化问题,最优化一个损失函数loss function,也就是标签和网络输出的误差,目标是让损失函数最小化。为此,咱们须要有样本,巨量的有标签数据,而后经过反向传播使用梯度降低的方法来更新神经网络的参数。

因此,要训练Q网络,咱们要可以为Q网络提供有标签的样本。

因此,问题变成:

如何为 Q 网络提供有标签的样本?
答案就是利用 Q-Learning 算法。

回想一下 Q-Learning 算法,
$$Q(S_{t},A_{t}) \leftarrow Q(S_{t},A_{t})+\alpha({R_{t+1}+\lambda \max _aQ(S_{t+1},a)} - Q(S_t,A_t))$$

Q值的更新依靠什么?依靠的是利用 Reward 和 Q 计算出来的目标Q值:

$$\text{Target-Q : }\ \ R_{t+1}+\lambda \max _aQ(S_{t+1},a)$$

所以,咱们把目标Q值做为标签不就完了?咱们的目标不就是让Q值趋近于目标Q值吗?
所以,Q网络训练的损失函数就是:



\(s^`,a^`\) 即下一个状态和动做

既然肯定了损失函数,也就是cost,肯定了获取样本的方式。那么DQN的整个算法也就成型了!接下来就是具体如何训练的问题了!



前边提到,每一组 (state, action, reward, state_) 为一次序列:

  • state (observation) 为目前状态,传递给 q-eval net 获得预计值 (即输入状态值, 输出全部的动做值);
  • state_ 为下一步状态,传递给 q-target net 获得目标值,以后能够获得 \(\max _aQ(S_{t+1},a)\) ,在以后获得 \(R_{t+1}+\lambda \max _aQ(S_{t+1},a)\)

最终的 \(loss\) 为:

self.loss = tf.reduce_mean(tf.squared_difference(self.q_target, self.q_eval))

再次注意,q-eval net 和 q-target net 网络结构彻底同样,只不过参数更新不一样!(即 Fixed Q-targets 方法)








最基本的DQN,也就是NIPS 13版本的DQN:



那么上面的算法看起来那么长,其实就是反复试验,而后存储数据。接下来数据存到必定程度,就每次随机采用数据,进行梯度降低!

也就是在DQN中加强学习 Q-Learning 算法和深度学习的 SGD 训练是同步进行的!
经过 Q-Learning 获取无限量的训练样本,而后对神经网络进行训练。

总体代码结构大体以下:

def run_maze():
    step = 0    # 用来控制何时学习
    for episode in range(300):
        # 初始化环境
        observation = env.reset()

        while True:
            # 刷新环境
            env.render()

            # DQN 根据观测值选择行为
            action = RL.choose_action(observation)

            # 环境根据行为给出下一个 state, reward, 是否终止
            observation_, reward, done = env.step(action)

            # DQN 存储记忆
            RL.store_transition(observation, action, reward, observation_)

            # 控制学习起始时间和频率 (先累积一些记忆再开始学习)
            if (step > 200) and (step % 5 == 0):
                RL.learn()

            # 将下一个 state_ 变为 下次循环的 state
            observation = observation_

            # 若是终止, 就跳出循环
            if done:
                break
            step += 1   # 总步数

    # end of game
    print('game over')
    env.destroy()


if __name__ == "__main__":
    env = Maze()
    RL = DeepQNetwork(env.n_actions, env.n_features,
                      learning_rate=0.01,
                      reward_decay=0.9,
                      e_greedy=0.9,
                      replace_target_iter=200,  # 每 200 步替换一次 target_net 的参数
                      memory_size=2000, # 记忆上限
                      # output_graph=True   # 是否输出 tensorboard 文件
                      )
    env.after(100, run_maze)
    env.mainloop()
    RL.plot_cost()  # 观看神经网络的偏差曲线

 

8.3 Experience Replay 经验回放

Q learning 是一种 off-policy 离线学习法, 它能学习当前经历着的, 也能学习过去经历过的, 甚至是学习别人的经历. 因此每次 DQN 更新的时候, 咱们均可以随机抽取一些以前的经历进行学习. 随机抽取这种作法打乱了经历之间的相关性, 也使得神经网络更新更有效率。

其将系统探索环境获得的数据储存起来,而后随机采样样本更新深度神经网络的参数(有了一个记忆库以后再开始学习)。



Experience Replay 的动机是:

  • 深度神经网络做为有监督学习模型,要求数据知足独立同分布,
  • 但 Q Learning 算法获得的样本先后是有关系的。为了打破数据之间的关联性,Experience Replay 方法经过存储-采样的方法将这个关联性打破了。

之因此加入 experience replay 是由于样本是从游戏中的连续帧得到的,这与简单的 reinforcement learning 问题(好比maze)相比,样本的关联性大了不少,若是没有 experience replay,算法在连续一段时间内基本朝着同一个方向作 gradient descent,那么一样的步长下这样直接计算 gradient 就有可能不收敛。所以 experience replay 是从一个 memory pool 中随机选取了一些 experience,而后再求梯度,从而避免了这个问题。

原文的实验中指出mini batch是32,而replay memory存了最近的1000000帧。

 

8.4 Fixed Q-targets

Fixed Q-targets 也是一种打乱相关性的机理, 若是使用 fixed Q-targets, 咱们就会在 DQN 中使用到两个结构彻底相同但参数不一样的神经网络 (有时差), 预测 Q 估计 的神经网络 (evaluate net) 具有最新的参数, 而预测 Q 现实 的神经网络 (target net) 使用的参数则是好久之前的

例如一开始有两个彻底同样的网络,一个进行训练,另外一个不训练,到了训练10000次后,把训练过的网络参数彻底复制给冻结的网络,以后还是一个训练,持续更新参数,一个冻结,每10000次才更新一次。

target_net 用于预测 q_target 目标值, 他不会及时更新参数.

eval_net 用于预测 q_eval 估计值, 这个神经网络拥有最新的神经网络参数





 

8.5 总结

在 Q-Learning 算法中,计算经验得分的公式以下:

$$\text{Q(state, action) = Q(state, action) + }\alpha\text{ (R(state, action) + }\gamma \text{ Max[Q(next state, all actions)] - Q(state, action))}$$

当 \(\alpha\) 的值是 \(1\) 时,公式以下:

$$\text{Q(state, action) = R(state, action) +} \gamma\text{ Max[Q(next state, all actions)]}$$

  • state: 表示 Agent 当前状态。
  • action: 表示 Agent 在当前状态下要作的行为。
  • next state: 表示 Agent 在 state 状态下执行了 action 行为后达到的新的状态。
  • Q(state, action): 表示 Agent 在 state 状态下执行了 action 行为后学习到的经验,也就是经验分数。
  • R(state, action): 表示 Agent 在 state 状态下作 action 动做后获得的即时奖励分数。
  • Max[Q(next state, all actions)]: 表示 Agent 在 next state 状态下,自个人经验中,最有价值的行为的经验分数。
  • Gamma: \(\gamma\) ,表示折损率,也就是将来的经验对当前状态执行 action 的重要程度。



算法流程:

Agent 经过经验去学习。Agent将会从一个状态到另外一个状态这样去探索,直到它到达目标状态。咱们称每一次这样的探索为一个场景(episode)。

每一个场景就是 Agent 从起始状态到达目标状态的过程。每次 Agent 到达了目标状态,程序就会进入到下一个场景中。

  1. 初始化 Q 矩阵,并将初始值设置成 0
  2. 设置好参数 γ 和得分矩阵 R
  3. 循环遍历场景(episode):

    1. 随机初始化一个状态 s
    2. 若是未达到目标状态,则循环执行如下几步:

      1. 在当前状态 s 下,随机选择一个行为 a
      2. 执行行为 a 获得下一个状态 s`
      3. 使用 \(\text{Q(state, action) = R(state, action) +} \gamma\text{ Max[Q(next state, all actions)]}\) 公式计算 \(\text{Q(state, action)}\)
      4. 将当前状态 s 更新为 s`

参考

  1. DQN 从入门到放弃
  2. 经验回放(Experience replay)
  3. 强化学习系列之九:Deep Q Network (DQN)
  4. 莫烦 PYTHON 强化学习 Reinforcement Learning