强化学习进阶——DQN
⽬录
在中,我们已经登堂⼊室,初窥强化学习的门径。不断探索的我们,怎么可能停滞不前呢?所以接下来,我会我们将重点介绍强化学习进阶——DQN。
预备知识
基本概念
在⼈⼯智能领域,⼀般⽤智能体Agent来表⽰⼀个具备⾏为能⼒的物体,⽐如机器⼈,⽆⼈车,⼈等等。那么增强学习考虑的问题就是智能体Agent和环境Environment之间交互的任务。
不管是什么样的任务,都包含了⼀系列的动作Action,观察Observation还有反馈值Reward。所谓的Reward就是Agent执⾏了动作与环境进⾏交互后,环境会发⽣变化,变化的好与坏就⽤Reward来表⽰。
agent、environment、state、action、reward共同构建了强化学习,如下图:
⽬标和约束条件
强化学习⽬标是获取尽可能多的reward,如何量化reward?
Agent都是根据当前的观察来确定下⼀步的动作。观察Observation的集合就作为Agent的所处的状态state。状态state和动作action之间存在映射关系,即⼀个状态对应不同的动作的概率。
状态state到动作action过程,称为策略policy,表⽰为。
因此,增强学习的任务就是到⼀个最优的策略Policy从⽽使Reward最多。
⼀开始并不知道最优的策略是什么,因此往往从随机的策略开始,使⽤随机的策略进⾏试验,就可以得到⼀系列的状态,动作和反馈:
这就是⼀系列的样本sample,增强学习需要这些样本改进policy。
MDP马尔可夫决策过程
假设
马尔可夫决策过程(MDP,Markov Decision Process)基本假设如下:
未来只取决于当前,即下⼀步的状态只取决于当前的状态,与过去的状态没有关系;
上帝不摘骰⼦,如果输⼊是确定的,那么输出也⼀定是确定的;
基本概念
⼀个基本MDP可以⽤(S,A,P)表⽰,S表⽰状态,A表⽰动作,P表⽰状态转移概率。状态对应动作的概率,有了动作,下⼀个状态也是确定的。
那么怎么描述状态的好坏?引⼊回报Return来表⽰某个时刻t的状态将具备的回报:
上⾯R是Reward反馈,λ是discount factor折扣因⼦,⼀般⼩于1,就是说⼀般当下的反馈是⽐较重要的,时间越久,影响越⼩。
实际上除⾮整个过程结束,否则显然我们⽆法获取所有的reward来计算出每个状态的Return,因此引⼊价值函数(Value Function)来表⽰未来潜在的价值:
计算价值函数
基于反复试验value Function评估,数学公式如下:
Bellman公式表明,value function是可以通过迭代计算出来的。
Action-Value Function动作价值函数
考虑到每个状态之后都有多种动作可以选择,每个动作之下的状态⼜多不⼀样,我们更关⼼在某个状态下的不同动作的价值。显然。如果知道了每个动作的价值,那么就可以选择价值最⼤的⼀个动作去执⾏了。动作价值函数表⽰为:
Optimal value function最优价值函数
计算动作价值函数是不够的,需要的是最有策略,求解最有策略⽅法有value-based,policy-based和model-based⽅法。
最优价值策略函数和⼀般动作价值函数关系:
最优价值策略函数是所有策略的价值函数的最⼤值。
策略迭代和值迭代
策略迭代
Policy Iteration是直接使⽤Bellman⽅程,其⽬的是通过迭代计算value function 价值函数的⽅式来使policy收敛到最优。其基本步骤如下:
Policy Evaluation 策略评估。⽬的是 更新Value Function,或者说更好的估计基于当前策略的价值;
Policy Improvement 策略改进。 使⽤ greedy policy 产⽣新的样本⽤于第⼀步的策略评估;
本质上就是使⽤当前策略产⽣新的样本,然后使⽤新的样本更好的估计策略的价值,然后利⽤策略的价值更新策略,然后不断反复。理论可以证明最终策略将收敛到最优。
值迭代
Value Iteration是使⽤Bellman 最优⽅程得到,和Policy Iteration有什么区别:
policy iteration使⽤bellman⽅程来更新value,最后收敛的value 即是当前policy下的value值(所以叫做对policy进⾏评估),⽬的是为了后⾯的policy improvement得到新的policy。
⽽value iteration是使⽤bellman 最优⽅程来更新value,最后收敛得到的value即就是当前state状态下的最优的value值。因此,只要最后收敛,那么最优的policy也就得到的。因此这个⽅法是基于更新value的,所以叫value iteration。
value iteration⽐policy iteration更直接,不过理想条件下需要遍历所有的状态,这在复杂⼀些的问题上就基本不可能了。
Q-Learning
介绍以上强化学习储备知识后,下⾯开始进⼊正题了。⾸先从Q-Learning开始。
Q-Learning算法
Q Learning是基于value iteration得到。但value iteration每次都对所有的Q值更新⼀遍,也就是所有的状态S和动作A。⼀个s⼀个a对应⼀个Q值,需要维护⼀张S*A的Q值表,如下:
因此只能使⽤有限的样本进⾏操作。为此Q Learning提出了⼀种更新Q值的办法:
这⾥并没有直接将这个Q值(是估计值)直接赋予新的Q,⽽是采⽤渐进的⽅式类似梯度下降,朝target迈近⼀⼩步,取决于α,这就能够减少估计误差造成的影响。类似随机梯度下降,最后可以收敛到最优的Q值。其算法流程如下:
EE问题
Q-Learning完全不考虑model模型也就是环境的具体情况,只考虑看到的环境及reward,因此是model-free的⽅法。那么怎样选择policy 来⽣成action呢?有两种做法:
探索阶段:随机⽣成动作;
利⽤阶段:根据当前的Q值计算出⼀个最优的动作,这个policy π称之为greedy policy贪婪策略
;
使⽤随机的动作就是exploration,有利于更新Q值,获得更好的policy。⽽使⽤greedy policy则是exploitation,利⽤policy,可以得到更好的测试效果⽤于判断算法是否有效。
将两者结合起来就是所谓的策略,⼀般是⼀个很⼩的值,决定exploration和exploitation 的⽐例。
DQN
Q-Learning神经⽹络化
当状态和动作空间是⾼维连续时,使⽤Q-Table不现实。如何解决维度灾难问题呢?答案是价值函数近似(Value Function Approximation)。其本质就是⽤⼀个函数近似Q值的分布,即:
DQN不⽤Q表记录Q值,⽽是⽤神经⽹络来预测Q值,并通过不断更新神经⽹络从⽽学习到最优的⾏动路径。
⽽Q值神经⽹络化要有海量带有标签的样本,如何实现呢?
利⽤Q-Learning中Reward和Q计算出来的⽬标Q值:
把⽬标Q值作为标签,让Q值趋近于⽬标Q值。
因此,Q⽹络训练的损失函数就是:
DQN算法及其改进
NIPS DQN
第⼀个版本的DQN(NIPS 2013提出的),在基本的Deep Q-Learning算法的基础上使⽤了Experience Replay经验池,算法流程如下:
主要涉及存储样本和采样问题,考虑到样本之间具有连续性,如果每次得到样本就更新Q值,受样本分布影响,效果会不好。因此,把样本先存起来,然后随机采样,降低数据相关性,这就是Experience Replay的意思。按照脑科学的观点,⼈的⼤脑也具有这样的机制,就是在回忆中学习。
Natural DQN
variable怎么记
Nature DQN是在NPIS DQN上增加Target Q⽹络。也就是我们在计算⽬标Q值时使⽤专门的⼀个⽬标Q⽹络来计算,⽽不是直接使⽤预更新的Q⽹络。这样做的⽬的是为了减少⽬标计算与当前值的相关性。
如上公式,计算⽬标Q值的⽹络使⽤的参数是w-,⽽不是w。Target Q仍从Q⽹络中来,只不过是延迟更新。也就是每次等训练了⼀段时间再将当前Q⽹络的参数值复制给⽬标Q⽹络。
Double DQN
⽬的是减少max Q值计算带来的计算偏差,或者称为过度估计(over estimation)问题,⽤当前的Q⽹络w来选择动作,⽤⽬标Q⽹络来计算⽬标Q。其改进公式如下:
部分伪代码如下:
# 定义双⽹络结构
def build_layers(s,c_name,n_l1,w_initializer,b_initializer):
with tf.variable_scope('l1'):
w1 = tf.get_variable(name='w1',shape=[self.n_features,n_l1],initializer=w_initializer,collections=c_name)
b1 = tf.get_variable(name='b1',shape=[1,n_l1],initializer=b_initializer,collections=c_name)
l1 = lu(tf.matmul(s,w1)+b1)
with tf.variable_scope('l2'):
w2 = tf.get_variable(name='w2',shape=[n_l1,self.n_actions],initializer=w_initializer,collections=c_name)
b2 = tf.get_variable(name='b2',shape=[1,self.n_actions],initializer=b_initializer,collections=c_name)
out = tf.matmul(l1,w2) + b2
return out
# ------------------ build evaluate_net ------------------
with tf.variable_scope('eval_net'):
c_names = ['eval_net_params',tf.GraphKeys.GLOBAL_VARIABLES]
n_l1 = 20
w_initializer = tf.random_normal_initializer(0,0.3)
b_initializer =tf.constant_initializer(0.1)
self.q_eval = build_layers(self.s,c_names,n_l1,w_initializer,b_initializer)
# ------------------ build target_net ------------------
with tf.variable_scope('target_net'):
c_names = ['target_net_params', tf.GraphKeys.GLOBAL_VARIABLES]
self.q_next = build_layers(self.s_, c_names, n_l1, w_initializer, b_initializer)
Prioritised replay
不同样本的重要性是不⼀样的,优化记忆库抽取。其改进数学公式如下:
按误差的⼤⼩进⾏重要程度排序,误差越⼤说明越需要被学习。但是为了效率,不能每次都排⼀遍太⿇烦,所以使⽤sumtree(线段树)排序相对来说就简单了。
SumTree 是⼀种树形结构, 每⽚树叶存储每个样本的优先级 p, 每个树枝节点只有两个分叉, 节点的值是两个分叉的合, 所以 SumTree 的顶端就是所有p的和,如下:

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。