Loading... ## 概述 有关强化学习(Reinforcement Learning, RL)是什么,有什么用,能够解决什么等问题,网上优秀的回答有很多,此处不做赘述。一言以蔽之,强化学习是一类让智能体通过不断地尝试,获得奖励/惩罚,并从中学习,最后找到“规律”,取得更好效果的算法。强化学习目前多与深度学习技术相结合,利用神经网络拟合传统强化学习中Q表格,在解决“维度灾难”问题的同时也能提高强化学习算法的感知、决策能力。 ![算法示意图](http://qiniu.ljcheng.cc/image/1.jpg) 强化学习目前多被用于机器人控制、决策,游戏开发,推荐系统等领域。与传统算法相比,强化学习的优势在于灵活性高,效果好,在很多鼓吹RL的文章中,强化学习被描述成一个效果好到令人难以置信的万金油,理论上来讲,一个强大的、高性能的RL系统可以解决任何问题,而且从目前来看,RL也是最符合人们对AGI幻想的算法之一——毕竟,谁会不喜欢一个无需训练数据,仅需与环境交互就能不断提升自身的智能体呢? 然而,强化学习目前仍面临着诸多问题,最大的莫过于“没法用”(来自[俞扬老师在知乎上的吐槽]( https://www.zhihu.com/question/449478247/answer/2001407526)),现实落地困难、仿真实物效果差距大的问题已经成为了飘浮在RL领域上的那朵乌云。其次,稳定性差,难以收敛,没有理论依据来保证下限等也是强化学习在应用中不得不面临的问题。 ![面临问题](http://qiniu.ljcheng.cc/image/2.jpg) 强化学习算法整体上可分为**Value-Based**和**Policy-Based**两类,前者输入s,输出Q(s, a),并采用如greedy/epsilon-greedy的策略选择出当前状态s下执行的动作a;后者输入s,输出p(s, a)(即输出当前状态s下动作a的分布),并采取如Softmax的策略选择出当前状态s下执行的动作a。二者的代表算法分别是DQN和PPO。Policy-Based相较Value-Based能够学习到一些随机策略(VB仅能输出确定策略),同时能够更自然地处理连续动作空间的场景,加之具有更好的收敛性,因此这些年来发展形势力压Value-Based一头。当然,Policy-Based也存在一些缺点,如评估策略通常效率低下,且方差较大(之后出现TRPO、PPO等算法对此进行了改进)等。而**Actor-Critic**算法则结合了Value-Based和Policy-Based两种算法的思想。 强化学习领域存在着两大流派——DeepMind和Open AI,前者是Google的子公司,后者则隶属于Elon Musk旗下,二者的代表作分别是AlphaGo和GPT-3。有关这两大强化学习流派的区别可参考[周博磊老师的这篇知乎回答](https://www.zhihu.com/question/316626294/answer/627373838),讲得非常透彻。 强化学习本身需要的强大的先导数学和优化知识,包括但不限于概率论,随机过程,博弈论,优化理论等。在学习时,个人推荐一开始不要扎的太深,可以先进行一些整体的了解,写一些小项目自己实践一下(Open AI Gym 和MuJoCo,若有N卡可以试试Isaac Gym),有一定了解和基础后再进行深入实践。 ## 强化学习路线 由于本人在初识强化学习时是整体跟着 David Silver 的课件进行学习的,故在此以他课件划分的结构对强化学习整体框架进行梳理,大体可以分为: ### 一、强化学习导论 属于强化学习的一个总览内容,介绍了强化学习的定义以及它的一些常见分类和应用场景,包括: 1. 什么是强化学习,与其他机器学习范式间的本质区别; 2. 常见强化学习的应用场景; 3. Value-Based、Policy-Based 和 Actor-Critic; 4. Model-Based 和 Model-Free; 5. 学习和规划; 6. 试探和开发; 7. 预测和控制。 ### 二、马尔可夫决策过程 这章主要是关于强化学习的一些基本概念,这些概念会在后面的章节中反复用到,它们包括: 1. 马尔可夫性(未来只与现在的状态有关而与过去无关)、马尔可夫(随机)过程(MP)、马尔可夫链($<S,P>$)、马尔可夫收益过程(MRP,$<S,P,R,\gamma>$)和马尔可夫决策过程(MDP,$<S,A,P,R,\gamma>$); 2. 策略$\pi (a|s)=P(A_t=a|S_t=s)$,即为一个**概率分布**; 3. **回报$G_t$、价值函数$v_{\pi}(s)=E_{\pi}[G_t|S_t=s]$和动作价值函数$q_{\pi}(s,a)=E_{\pi}[G_t|S_t=s,A_t=a]$**; 4. 在MRP中:已知立即收益$R$、状态转移矩阵P和折扣率$\gamma$,求解**贝尔曼方程**:$ v=R+\gamma Pv $,有直接求解(解线性方程组)和间接求解(DP、MC、TD等)两种方法; 5. 在MDP中:**贝尔曼期望方程**:$ v_{\pi}=R^{\pi}+\gamma P^{\pi}v_{\pi} $,解法同理贝尔曼方程; 6. 关于价值函数和动作价值函数,二者间存在关系: $$ v_{\pi}(s)=\sum_{a\epsilon A}\pi (a|s)q_{\pi}(s,a) $$ $$ 因此有: v_{\pi}(s)=\sum_{a\epsilon A}\pi (a|s)(R_{s}^{a}+\gamma \sum_{s'\epsilon S}P_{ss'}^{a}v_{\pi}(s')) $$ $$ q_{\pi}(s,a)=R_{s}^{a}+\gamma \sum_{s'\epsilon S}P_{ss'}^{a}\sum_{a'\epsilon A}\pi (a'|s')q_{\pi}(s',a') $$ 7. **贝尔曼最优方程**:取贝尔曼期望方程中最优值,即通过选择策略$\pi$使得$v_{\pi}(s)$和$q_{\pi}(s,a)$最大化(通过**最大化最优动作价值函数$q_{*}(s,a)=max_{\pi}q_{\pi}(s,a)$来寻找**);贝尔曼最优方程为**非线性方程**,无闭式解,只能通过间接方法求解(DP、Sarsa、Q-Learning等);此时有: $$ v_{*}(s)=max_{a}(R_{s}^{a}+\gamma \sum_{s'\epsilon S}P_{ss'}^{a}v_{*}(s'))\\ q_{*}(s,a)=R_{s}^{a}+\gamma \sum_{s'\epsilon S}P_{ss'}^{a}max_{a'}q_{*}(s',a') $$ ### 三、动态规划 1. 动态规划:一种解决问题的思想,通过**把复杂问题分解为子问题**,通过求解子问题从而得到整个问题的解。在解决子问题时,各子问题的结果通常要存储起来,在解决后续复杂问题时可以用到(即通常是以空间换时间); 2. 使用DP的条件:最优子结构 && 子问题在复杂问题中重复出现,而马尔可夫决策过程(MDP)具有上述两个属性:贝尔曼方程将问题递归为求解子问题 && 价值函数相当于存储了一些子问题的解,可以复用 => 因此可用DP来求解MDP; 3. DP用于解决“**规划**”(**Planning**)问题(指在知道整个MDP的基础上求解最优策略,包括状态/动作空间、转换矩阵、奖励等),即是一种**model-based**的算法,可用规划进行**预测**和**控制**; 4. * 预测:给定一个MDP和策略$\pi$,输出基于当前策略$\pi$的价值函数$v_{\pi}(s)$; * 控制:给定一个MDP,要求确定最优价值函数$v_{*}(s)$和最优策略$\pi_{*}$。 5. **策略评估**(即解决“预测”问题):**反向迭代**应用Bellman期望方程:**同步**反向迭代,对于第k+1次迭代,使用第k次结果进行迭代,如状态s的所有后继状态s'都用$v_{k}(s')$进行计算,并更新$v_{k+1}(s)$,即: $$ v_{k+1}(s)=\sum_{a\epsilon A}\pi (a|s)(R_{s}^{a}+\gamma \sum_{s'\epsilon S}P_{ss'}^{a}v_{k}(s')) $$ $$ 矩阵形式: v^{k+1}=R^{\pi}+\gamma P^{\pi}v^{k} $$ 即用到了“**自举**”(**bootstrapping**)的思想:用一个估算值去更新同类的估算值; 6. 改善策略: * 策略迭代; * 价值迭代。 7. **策略迭代(Policy Iteration)**:在当前策略上迭代计算v值,再根据v值贪婪地更新策略,如此反复多次得到最优策略和最优状态价值函数(有时不需要得迭代至最优价值函数,可通过设置迭代次数,比较两次迭代v的平方差等方法提前终止迭代)。分为policy evaluation(策略评估)和policy improvement(策略改善)两步; 8. 广义策略迭代:通过任何算法进行策略评估和策略改善,即相当于就是一个“评估-改善”的过程(**所有RL算法**); 9. **价值迭代(Value Iteration)**:同步反向迭代,若当前知道子问题$v_{*}(s')$的解,则$v_{*}(s)$可通过**一步前瞻**找到,即: $$ v_{*}(s)=\max_{a\epsilon A}R_{s}^{a}+\gamma \sum_{s'\epsilon S}P_{ss'}^{a}v_{*}(s') $$ 然后迭代地应用这些更新即可。与策略迭代不同,价值迭代中算法**不会给出明确的策略**,迭代过程中得到的v不对应任何策略; 10. 异步动态规划。 ### 四、无模型(model-free)的预测 1. **蒙特卡洛(MC)**:利用频率估计概率,无模型(即分布未知 => 进行采样!),没有“自举”,使用完整的episode数据,思想是**用平均收获代替价值**,仅能用于有终止的MDP; 2. MC分类: * 首次访问:在每个episode中,仅当状态s第一次出现时列入计算; * 每次访问:在每个episode中,状态s每次出现时都列入计算。 3. 使用MC求解平均收获时,需要预先存储所有的数据 => 改用**增量式更新平均值**: $$ \mu_{k}=\mu_{k-1}+\frac{1}{k}(x_k-\mu_{k-1}) $$ 此时仅需要存储上一时刻的平均值$\mu_{k-1}$即可;=> 进一步改进:$\alpha MC$,$\alpha$为学习率,控制了更新的速度,原始的MC中$\alpha$即为$\frac{1}{N(S_t)}$,更新公式为: $$ V(S_t)\leftarrow V(S_t)+\alpha(G_t-V(S_t)) $$ 4. **时序差分(TD)**:与MC一样,无模型,直接从episode经验中学习,但TD可以从不完整的episode中学习(通过“**自举**”的思想,利用猜测的episode的结果来更新猜测(同时持续更新这个猜测));TD结合了MC的**采样**方法(即做实验)和DP中的bootstrapping(利用上轮中后继状态的价值估计该轮中当前状态的价值);TD可以在每步后在线学习,而无需等到整个episode结束; 5. TD在更新价值V时用的不是实际的收获$G_t$,而是用的是离开该状态的即时奖励$R_{t+1}$与对下一状态$S_{t+1}$的预估价值成一衰减系数$\gamma$组成,即为: $$ V(S_t)\leftarrow V(S_t)+\alpha(R_{t+1}+\gamma V(S_{t+1})-V(S_t)) $$ $$ 其中 \enspace R_{t+1}+\gamma V(S_{t+1})\enspace 称为TD目标值; $$ $$ \delta_t=R_{t+1}+\gamma V(S_{t+1})-V(S_t)\enspace称为TD误差 $$ 6. * MC没有偏差,但有较高的方差(**无偏估计**),且对初始值不敏感; * TD低方差,但有一定程度的偏差(**有偏估计**),且对初始值较为敏感,通常比MC更高效。 7. * MC没有利用马尔可夫性,通常在非Markov环境下更有效; * TD利用了MDP问题的马尔可夫性,在Markov环境下更有效。 8. MC && TD && DP: ![MC](http://qiniu.ljcheng.cc/image/3.jpg) ![TD](http://qiniu.ljcheng.cc/image/4.jpg) ![DP](http://qiniu.ljcheng.cc/image/5.jpg) 9. $TD(\lambda)$:默认的TD是**TD(0)**,代表在当前状态下向前多看1步(即$G_t^{n}$**中n为1**),MC则相当于**TD($\infty $)**,即跑完一条轨迹直到terminal state。定义n步回报为: $$ G_t^{(n)}=R_{t+1}+\gamma R_{t+2}+...+\gamma^{n-1}R_{t+n}+\gamma^{n}V(S_{t+n}) $$ n从1到$\infty$。TD($\lambda$)中使用的是$\lambda$回报$G_t^{\lambda}$,其结合了**所有的n步回报$G_t^{(n)}$**,并对每项使用权重$(1-\lambda)\lambda^{n-1}$(使得$n\rightarrow \infty$时各项权重之和为1),即为: $$ G_t^{\lambda}=(1-\lambda)\sum_{n=1}^{\infty}\lambda^{n-1}G_t^{(n)} $$ 其中$\lambda\epsilon [0,1]$;$\lambda=0$时,退化成TD(0),$\lambda=1$时,退化成MC;$\lambda$仅为衰减参数,TD($\lambda$)恒考虑的是所有n步的回报; 10. * TD($\lambda$)前向视角:表达式为$V(S_t)\leftarrow V(S_t)+\alpha(G_t^{\lambda}-V(S_t))$,从中可看到需要用到将来时刻的值函数,因此前向视角只能从完整的episode中学习; * TD($\lambda$)后向视角:前向视角提供理论,后向视角提供更新机制(在线、实时、单步更新);后向视角中用到了**资格迹**,结合了**频率启发**和**就近启发**两种启发方式,为每一个状态引入一个资格迹,**资格迹反映了当前状态$S_t$对目标状态$S$(过去某一状态)的影响**,表达式为: $$ E_0(s)=0\\E_t(s)=\gamma\lambda E_{t-1}(s)+1(S_t=s) \enspace即以\gamma\lambda衰减 $$ 后向视角更新时与误差$\delta_t$和资格迹$E_t(s)$成正比,更新公式为: $$ \delta_t=R_{t+1}+\gamma V(S_{t+1})-V(S_t)\\V(S_t)\leftarrow V(S_t)+\alpha\delta_tE_t(s) $$ 后向视角对每一个状态s保持一个资格迹,每步更新之前每个状态的V(用当前的$\delta_t$和目标状态的$E_t(s)$; * 前向和后向视角的关系:前向和后向视角的**离线更新总和相同**。 11. * **offline**:离线学习,在整个更新过程中仅更新一次,即**采集完所有数据**(如10个episodes)后再更新; * **online**:在线学习,更新时边更新边采集数据,更新间隔最多为一个episode(如MC为一个episode,TD为1个step); 注:online和offline与on-policy和off-policy不同,并不是一种固定的模式,**所有RL的方法都可是online/offline的**。 ### 五、无模型的控制(model-free control) 1. 第四章中的MC和TD只是用于估计未知MDP的价值函数(即V(s)和Q(s, a)),并未进行优化;第五章则是介绍了一些优化MDP价值函数的方法; 2. * **on-policy**:待优化策略(**目标策略**)和采样遵循的策略(**采样策略**)相同; * **off-policy**:目标策略和采样策略不同,“站在别人肩膀上可以看得更远”的思想。 3. 对于无模型的策略迭代,使用动作价值函数Q(s, a)而非价值函数V(s):因为基于V(s)的贪婪策略提升需要MDP模型,而基于Q(s, a)的贪婪策略提升不需要MDP模型; 4. $\varepsilon-greedy$:以$1-\varepsilon$的概率去选择贪婪策略,以$\varepsilon$的概率去选择一个随机动作; 5. 由于TD相比MC具有低方差、在线学习、可以从不完整episode中学习的优势,因此**使用TD来代替MC进行控制**,即: * 应用TD来更新Q(s, a); * 使用$\varepsilon-greedy$策略进行改进; * 每个时间步都进行更新。 6. **SARSA**:使用TD来更新Q(s, a),即可得到SARSA,更新公式为: $$ Q(S, A)\leftarrow Q(S, A)+\alpha(R+\gamma Q(S', A')-Q(S, A)) $$ $$ 其中A'采用\varepsilon-greedy策略选出 $$ 即将TD中更新V换为了更新Q,使用Q(s, a)去逼近目标值$G_t=\sum_{k=0}^{\infty }\gamma ^{k}R_{t+k+1}$;软更新,每次更新$\alpha$; 7. n-step SARSA:将原始TD($\lambda$)中V换为Q,其余均保持一致; 8. off-policy:异策学习,有如下优点: * 可以从人类或其他智能体的经验中学习; * 重用旧策略的经验; * 在使用一个探索性策略的同时学习一个确定性策略; * 使用一个策略采样,同时学习多个策略。 **重要性采样(IS)**: $$ E_{X\sim P}[f(X)]=E_{X\sim Q}[\frac{P(X)}{Q(X)}f(X)] $$ $$ E_{X\sim P}[\enspace]:定义在P(X)上的采样 $$ $$ E_{X\sim Q}[\enspace]:定义在Q(X)上的采样 $$ $$ \frac{P(X)}{Q(X)}:重要性权重 $$ * 异策MC方法重要性采样:使用由$\mu$(采样策略)产生的回报值来评估$\pi$(目标策略),并根据策略之间的相似性对$G_t$进行加权,即沿着整个episode对重要性采样的权重进行连乘: $$ G_t^{\frac{\pi}{\mu}}=\frac{\pi(A_{t}|S_{t})}{\mu(A_{t}|S_{t})}\frac{\pi(A_{t+1}|S_{t+1})}{\mu(A_{t+1}|S_{t+1})}...\frac{\pi(A_{T}|S_{T})}{\mu(A_{T}|S_{T})}G_t $$ $$ V(S_t)\leftarrow V(S_t)+\alpha(G_t^{\frac{\pi}{\mu}}-V(S_t)) $$ 重要性采样会**显著增加方差**; * 异策TD方法重要性采样:根据策略之间的相似性对TD目标$R+\lambda V(S_{t+1})$进行加权,只需要进行一次重要性抽样校正(因为是TD(0)): $$ V(S_t)+\alpha(\frac{\pi(A_{t}|S_{t})}{\mu(A_{t}|S_{t})}(R+\lambda V(S_{t+1}))-V(S_t)) $$ **方差比异策MC重要性采样低得多**,策略只需在一个时间步上相似; * 注意:在重要性采样中,$\pi$并不影响采样的走向。它并不通过自己在当前状态的Q来选择动作,整个采样序列均是由$\mu$独立完成,重要性采样的方法是:**在状态$S_{t}$时比较目标策略$\pi$和采样策略$\mu$产生行为$A_t$的概率大小**,如果策略$\pi$得到的概率值与当前策略$\mu$得到的概率值相近(即$\frac{\pi(A_{t}|S_{t})}{\mu(A_{t}|S_{t})}\approx 1$),即在状态$S_t$时,两个策略有接近的概率选择行为$A_t$,说明这一更新操作比较有说服力;若比值很小,则表明目标策略在此时选择动作$A_t$的概率很小,这时我们在更新$S_t$价值的时候就不能过多的考虑基于采样策略得到的$R+\lambda V(S_{t+1})$;比值很大时同理。$\pi$可以在$\mu$采样的同时更新(online),也可以在采样结束后更新(offline)。 9. **Q-Learning**:对Q(S, A)进行异策学习(上面的MC和TD是对于V(S)的),**Q-Learning中不需要用到重要性采样**(因为Q-Learning中对于某个状态s,使用贪婪策略的$\pi$选择a的概率要么是1,要么是0。当为1时,使用$\varepsilon-greedy$策略的$\mu$选择该动作a的概率也比较大(因为$\varepsilon$一般比较小),因此此时$\frac{\pi}{\mu}\approx 1$;当为0时$\frac{\pi}{\mu}= 0$),目标策略$\pi$为对应于Q(s, a)的贪婪策略,采样策略$\mu$为对应与Q(s, a)的$\varepsilon-greedy$策略,即在Q-Learning中会**同时改善目标策略和采样策略**,对应更新公式为: $$ Q(S, A)\leftarrow Q(S, A)+\alpha(R+\gamma Q(S', A')-Q(S, A)) $$ $$ 其中\enspace A'=argmax(S',A') $$ 由于Q-Learning直接学习的是最优策略,而SARSA再来学习最优策略的同时还在探索,因此Q-Learing学习到的策略通常比SARSA更为激进。 注意:IS(重要性采样)和off-policy间并没有必然联系,二者间不可互推(如Q-Learning中并没有用到重要性采样): * off-policy:更新的数据并非是由当前策略采样得到的(当前策略的变形也算,如Q-Learning); * IS:一个技巧,当采样数据的分布和目标数据的分布不同时使用。 ### 六、价值函数近似 1. 即向强化学习中引入神经网络,利用神经网络函数拟合的功能来近似估计实际的价值函数,从而代替原始强化学习中查表的方法,即: $$ \hat{v}(s,w)\approx v_{\pi}(s)\\or \enspace \hat{q}(s,a,w) \approx q_{\pi}(s,a) $$ 这样除了可以对状态空间“维数灾难”的问题进行解决(连续状态空间或状态空间很大);还可以把从见过的状态中学到的函数,推广至那些未见过的状态中。使用MC或TD方法来更新神经网络参数w; 2. 更新参数w:使用随机梯度下降SGD,更新表达式为: $$ \Delta w=\alpha (v_{\pi}(s)-\hat{v}(s,w))\bigtriangledown_w\hat{v}(s,w) $$ 其中$\hat{v}(s,w)$为近似函数,$v_{\pi}(s)$为实际函数,$\bigtriangledown_w\hat{v}(s,w)$为求$\hat{v}(s,w)$关于w的梯度,$\alpha$为步长; 在上公式中,假定存在了真实的价值函数$v_{\pi}(s)$,而强化学习中没有监督数据,只有即时奖励,因此需进行替换: * 对于MC,使用回报$G_t$; * 对于TD(0),使用TD目标值$R_{t+1}+\gamma \hat{v}(S_{t+1},w)$; * 对于TD($\lambda$),使用$\lambda$回报$G_t^{\lambda}$。 3. 对于线性函数近似,用特征向量$x(s)$来表示状态,此时更新规则较为简单,为: $$ \because \bigtriangledown_w\hat{v}(s,w)=x(s) $$ $$ \therefore \Delta w=\alpha (v_{\pi}(s)-\hat{v}(s,w))x(s) $$ 即:参数更新量=步长$\times$预测误差$\times$特征值; 4. 前面使用的均为**增量方法**,都是基于数据流的,每经历一步,更新算法后,就不再使用这些数据,数据利用率不够高效;**批方法**则是将一段时间以内的数据集中起来(即一段经验),通过学习来使得参数能够更好地拟合这段时间内的数据; 5. **最小二乘法**预测:已知一段时期内的经验为$D=\{<s_1,v_1^{\pi}>,<s_2,v_2^{\pi}>,...,<s_t,v_t^{\pi}>\}$,最小二乘法即要求找到参数w,使得下式值最小: $$ LS(w)=\sum_{t=1}^{T}(v_t^{\pi}-\hat{v}(s_t,w))^2=E_D[(v_t^{\pi}-\hat{v}(s_t,w))^2] $$ 6. 带**经验回放**的随机梯度下降:经验回放指把一段时期内的经验重新过一遍,更新参数,算法步骤为: * 从经验中随机采样一个$<s,v>$; * 应用随机梯度下降来更新参数:$\Delta w=\alpha (v_{\pi}(s)-\hat{v}(s,w))\bigtriangledown_w\hat{v}(s,w)$。 结果收敛至:针对这段经验数据的最小二乘法的最优解:$w^{\pi}=argmin_wLS(w)$。 7. **DQN**:目标策略:$greedy$ on Q;采样策略:$\epsilon -greedy$ on Q。DQN使用了监督学习的思想,使用了监督学习中的SGD来最小化Q-estimation($Q$)和Q-target($\hat{Q}$)间的MSE(让$Q$尽可能接近$y=r_i+max_{a}\hat{Q}$,$y$相当于是监督学习中的**标签**),每隔一段时间将$Q$的参数直接拷贝给$\hat{Q}$,更新公式为: $$ L(w)=E_{s,a,r,s'\sim D}[(r+\gamma max_{a'}Q(s',a';w^-)-Q(s,a;w))^2] $$ $$ 其中w^-在更新参数中是固定的,w则是动态更新的参数 $$ DQN算法流程图: ![DQN算法流程图](http://qiniu.ljcheng.cc/image/6.png) DQN Tips: * 使用了CNN作为$\hat{q}(s,a,w)$来近似估计实际的价值函数$ q_{\pi}(s,a)$,解决了“维数灾难”问题(连续状态空间或状态空间很大); * Fixed Q-target:由于要使用监督学习中的SGD来最小化Q-target和Q-estimation间的MSE,就像一个猫捉老鼠的游戏,其中猫是Q-estimation,老鼠是Q-target。由于Q-target也是与模型参数相关的,所以每次优化后,Q-target也会动。这就会导致一个问题,猫和老鼠都在动,即它们都会在优化空间里面到处乱动,这会产生非常奇怪的优化轨迹,使得训练过程十分不稳定。所以我们可以固定Q-target,让老鼠动得不那么频繁,可能让它每 5 步动一次,猫则是每一步都在动。如果老鼠每 5 次动一步,猫就有足够的时间来接近老鼠,它们之间的距离会随着优化过程越来越小,最后它们就可以拟合,拟合后就可以得到一个最好的Q网络: ![猫和老鼠](http://qiniu.ljcheng.cc/image/7.png) * Experience replay:加入了经验回放机制,使得数据利用更加充分高效。 注:DQN中经验池D中的经验可能来自于与自身完全不同的策略,即可以利用其他智能体采样得到的经验进行学习。 8. DQN进阶:DDQN,Dueling DQN,D3QN,DRQN等。 ### 七、策略梯度 1. 之前使用的均是value-based的方法,即直接利用的是价值函数,得到V(s)和Q(s, a),再通过如$greedy$ 或$\epsilon -greedy$的方法来选取$\pi$;这章介绍的则是policy-based的方法,即直接参数化策略(直接对$\pi$建模并选择):$\pi_{\theta}(s,a)=P[a|s,\theta]$; 2. 优势: * value-based输出的是确定性策略,对1.动作空间连续;2.观测受限;3.随机策略等学习问题时仍会力不从心,而policy-based可以解决这些问题,它可以输出连续策略,同时也可以学习到一些随机策略。 劣势: * 评估策略通常效率低且方差较大(之后出现TRPO、PPO等算法对此进行了改进)。 3. policy-based实际上是一个优化问题,即找到参数$\theta$来最大化目标函数$J(\theta)$,本章主要聚焦于使用梯度的策略优化(使用与梯度下降相反的**梯度上升法**); 4. **策略梯度**:用$\tau $表示每次放真的状态-行为序列$s_1,a_1,s_2,a_2,...,s_T,a_T$,每个轨迹代表了强化学习的一个样本,即 Trajectory $\tau = \{s_1,a_1,s_2,a_2,...,s_T,a_T\}$,该轨迹的回报为: $$ R(\tau)=\sum_{t=1}^{T}\gamma^tR(s_t,a_t) $$ 在某一场游戏的某一个回合里面,我们会得到$R(\tau)$。我们要做的是调整智能体内部的参数 $\theta$, 使得$R(\tau)$的值越大越好。 但实际上$R(\tau)$并不是一个标量,而是一个**随机变量**,因为智能体在给定同样的状态下会采取什么样的动作是有随机性的,环境在给定同样的观测时要采取什么样的动作,要产生什么样的观测,本身也是有随机性的。我们能够计算的是$R(\tau)$的期望值。给定某一组参数$\theta$,我们可计算$R(\tau)$的期望值为: $$ \bar{R}_{\theta}=\sum_{\tau}R(\tau)p_{\theta}(\tau) $$ $$ 其中p(\theta)表示在参数\theta下轨迹\tau出现(完美复现s_1,a_1,s_2,a_2,...,s_T,a_T)的概率 $$ $$ 即:轨迹回报的期望值=该轨迹出现的概率\times该轨迹的回报值,即加权求和 $$ 目标:调整参数$\theta$使得$\bar{R}_{\theta}$越大越好,即$\bar{R}_{\theta}$作为**目标函数**,因此RL的目标可以表示为: $$ max_{\theta}\bar{R}_{\theta}=max\sum_{\tau}R(\tau)p_{\theta}(\tau) $$ 其中不同的策略$\pi_{\theta}$影响了不同轨迹出现的概率,因为$p_{\theta}(\tau)$是一个**分布**,我们感兴趣的是通过移动这个分布(通过改变参数$\theta$)来提高回报值。 策略梯度的推导:已知函数在某个变量处的梯度等于该处的函数值与该函数的对数函数在此处梯度的乘积,即: $$ \bigtriangledown f(x)=f(x)\bigtriangledown logf(x) $$ 则有: $$ \bigtriangledown \bar{R}_{\theta}=\sum_{\tau}R(\tau)\bigtriangledown p_{\theta}(\tau) $$ $$ =\sum_{\tau}R(\tau)p_{\theta}(\tau)\bigtriangledown logp_{\theta}(\tau) $$ $$ =E_{\tau \sim p_{\theta}(\tau)}[R(\tau)\bigtriangledown logp_{\theta}(\tau)] $$ $$ \approx \frac{1}{N}\sum_{n=1}^{N}R(\tau^n)\bigtriangledown logp_{\theta}(\tau^n) $$ $$ =\frac{1}{N}\sum_{n=1}^{N}\sum_{t=1}^{T}R(\tau^n)\bigtriangledown logp_{\theta}(a_t^n|s_t^n) $$ 理解:对于$\bigtriangledown \bar{R}_{\theta}=\frac{1}{N}\sum_{n=1}^{N}R(\tau^n)\bigtriangledown logp_{\theta}(\tau^n)$,其中$\bigtriangledown logp_{\theta}(\tau^n)$是轨迹$\tau$的概率随参数$\theta$变化最陡的方向($log$是单调递增的函数,对$logp_{\theta}(\tau)$求梯度相当于对$p_{\theta}(\tau)$求梯度),沿正方向,轨迹出现的概率会变大,沿负方向会变小;$R(\tau)$控制了参数更新的方向和步长,正负决定了方向,大小决定了增大/减小的幅度。 策略梯度更新策略为: ![策略梯度](http://qiniu.ljcheng.cc/image/image-20221231153539777.png) 注意: * 其中$R(\tau^1)$,$R(\tau^2)$...指每个episode结束后获得的总奖励; * PG采样的数据仅会使用一次,用完就回丢掉(仅存储单回合记忆); * 更新公式中,$\eta$为学习率,N指共有N个episode,T指各个episode中各有T个采样时刻。 PG可以分为以下**两大类**: 1. MC 蒙特卡洛:REINFORCE算法:$\bigtriangledown \bar{R}_{\theta}\approx\frac{1}{N}\sum_{n=1}^{N}\sum_{t=1}^{T}G_t^n\bigtriangledown logp_{\theta}(a_t^n|s_t^n)$; 2. TD 时序差分:Actor-Critic算法:$\bigtriangledown \bar{R}_{\theta}\approx\frac{1}{N}\sum_{n=1}^{N}\sum_{t=1}^{T}Q^n(s_t^n,a_t^n)\bigtriangledown logp_{\theta}(a_t^n|s_t^n)$。 Tips:通过使用**基线(baseline)**的方式来减小方差:从原始的策略梯度中减去一个基线函数B(s),这样可以**减小方差,且不改变期望**,一个很好的基线是**状态价值函数V(s)**,如对于A2C和A3C中,此时更新的从$Q_{\pi_{\theta}}(s,a)$变为**优势函数**$A_{\pi_{\theta}}(s,a)=Q_{\pi_{\theta}}(s,a)-V_{\pi_{\theta}}(s)$,理解:价值函数V(s)是该状态下所有的动作价值函数Q(s,a)关于动作概率的平均值,Q(s,a)是单个动作所对应的值函数,优势函数是**评价当前的动作价值函数相对于平均值的大小**,“优势”指当前的动作价值函数相较于当前状态的价值函数的优势。 5. **蒙特卡洛策略梯度(REINFORCE)**:即在每个episode结束后,利用这个回合的数据计算每个步骤的未来总奖励$G_t$,再通过随机梯度上升来更新参数,即: $$ \bigtriangledown \bar{R}_{\theta}\approx\frac{1}{N}\sum_{n=1}^{N}\sum_{t=1}^{T}G_t^n\bigtriangledown logp_{\theta}(a_t^n|s_t^n) $$ 可以表示为: $$ \theta \leftarrow \theta+\alpha\bigtriangledown _{\theta} log\pi_{\theta}(s_t,a_t)G_t $$ 其中$\pi_{\theta}(s_t,a_t)$和$p_{\theta}(a_t^n|s_t^n)$一样,均反映了Agent的策略;$\bigtriangledown _{\theta} log\pi_{\theta}(s_t,a_t)=\frac{\bigtriangledown _{\theta} \pi_{\theta}(s_t,a_t)}{\pi_{\theta}(s_t,a_t)}$,即每次的更新大小都**正比于回报,且反比于选择动作的概率**,前者的意义在于使得参数向着更有利于产生最大回报的动作的方向更新,后者的意义在于如果不这样做的话,会使得频繁被选择的动作占优,即使这些动作不是产生最大回报的动作,最后也可能会胜出。 6. **演员-评论家算法(Actor-Critic)**:REINFORCE具有很高的方差,因为每次需要根据一个策略采集一条完整的轨迹,并计算这条轨迹上的回报。这种采样方式的方差比较大,学习效率也比较低。我们可以借鉴TD时序差分学习的思想,使用动态规划方法来提高采样效率并降低方差,使用一个评论家来拟合Q,即:$Q_w(s,a)\approx Q_{\pi_{\theta}}(s,a)$,更新公式为: $$ \bigtriangledown \bar{R}_{\theta}\approx\frac{1}{N}\sum_{n=1}^{N}\sum_{t=1}^{T}Q^n(s_t^n,a_t^n)\bigtriangledown logp_{\theta}(a_t^n|s_t^n) $$ AC是一种结合了**策略梯度**和**时序差分**的算法(即是一种结合了Value-Based和Policy-Based的方法),其中,演员Actor是指策略函数 $\pi_{\theta}(a|s)$,即学习一个策略以得到尽可能高的回报;评论家Critic是指动作价值函数 $q_{w}(s,a)$,对当前策略的值函数进行估计,即评估演员的好坏。借助于动作价值函数,AC可以进行单步参数更新,不需要等到回合结束才进行更新。其中每步Critic通过随机梯度下降来更新参数$w$,Actor通过随机梯度上升来更新$\theta$。 延伸:优势演员-评论家算法(advantage actor-critic,A2C);A3C:A2C+异步;TRPO,PPO等。 ### 八、整合学习与规划 1. 之前的强化学习算法是从经验中学习价值函数,或直接从经验中学习策略,此章的算法是**从经验中学习(learning)模型,并使用规划(planning)来构建一个价值函数或策略,将学习和规划集成到一个单一的架构中**; 2. * model-free RL:没有模型,从经验中直接学习价值函数或策略; * model-based RL:**从经验中学习模型,从模型中“规划”价值函数或策略**,即: ![model-based RL](http://qiniu.ljcheng.cc/image/image-20221119160152938.png) 3. **model-based RL**: 优势: * **当学习价值函数或策略比较困难时**,学习模型是一种不错的途径,如下棋这类活动,模型是相对直接的,相当于就是**游戏规则**; * 可以使用**监督学习**的方法来学习模型; * 模型能够对智能体理解环境提供帮助,即具备一定的推理能力。 劣势: * 模型实际上是智能体对环境运行机制的描述,存在一定程度的近似,而当使用一个近似的模型去学习价值函数或策略时,又回引入一次近似,因此会带来**双重的近似误差**; * 不是所有情况下都能学习到一个准确的模型,如环境较为复杂时就学习不到。 4. 模型M:是一个MDP$<S,A,P,R,\gamma>$的参数化表现形式(参数为$\eta$),模型$M=<P_n,R_n>$呈现了**状态转移**$P_n\approx P$和**奖励**$R_n\approx R$;对模型的学习过程是从经验$\{s_1,a_1,r_1,...,s_t\}$中估计一个模型$M_n$,这是一个**监督学习**问题: * 从s, a学习r的过程是一个**回归问题**; * 从s, a学习s'的过程是一个**密度估计问题**。 选择损失函数(如MSE、KL散度等),通过最小化经验损失来寻找参数$\eta$; 5. **查表模型**:通过采样得到的经验得到各状态行为的转移概率和奖励,把这些数据存入表中,使用时直接检索: $$ \hat{P}_{s,s'}^{a}=\frac{1}{N(s,a)}\sum_{t=1}^{T}1(S_t,A_t,S_{t+1}=s,a,s') $$ $$ \hat{R}_{s}^{a}=\frac{1}{N(s,a)}\sum_{t=1}^{T}1(S_t,A_t=s,a)R_t $$ 在学习中的每一步,记录如下的状态转换(作为经验片段):$<S_t,A_t,R_{t+1},S_{t+1}>$,从模型采样构建虚拟经验时,从符合$<s,a,.,.>$的tuples中**随机选择**一个符合的tuple,提供给智能体进行价值或策略的更新(这里的随机选择体现了状态s的各种后续状态的概率分布)。实例如下: ![实例:AB状态](http://qiniu.ljcheng.cc/image/image-20221129193044919.png) 6. 在进行了模型的学习后,可以对其进行“规划”,即给定一个模型$M=<P_n,R_n>$,求解MDP$<S,A,P,R,\gamma>$,即找到基于该模型的最优价值函数或最优策略,可以使用: * 价值迭代; * 策略迭代; * 树搜索方法等。 其中前两者属于DP; 7. **基于采样的规划(Sample-Based Planning)**:很常用的一个方法,即在规划过程中,模型并非像DP那样将这些概率值传递给迭代过程,而仅仅是利用模型来产生一个虚拟的状态转换,即一个时间步长的虚拟经验,并利用这些采样所得的虚拟经验,使用**无模型的强化学习方法**(如MC control, Sarsa, Q-learning等)来学习得到价值或策略函数;**这种基于采样的规则方法通常更加有效**。实例如下: ![实例:AB状态](http://qiniu.ljcheng.cc/image/image-20221202220434006.png) 若使用DP则状态A,B的价值定均为0.75;从实例中也能看出,通过构建模型并使智能体与之交互,可以得到无数条采样轨迹(即虚拟经验),这些虚拟经验是立即得到的,而不像与现实交互那样需要等很久; 8. **整合学习与规划**:有两种经验来源: * 真实经验:直接从环境中采样(真实MDP):$S'\sim P_{s,s'}^{a},R=R_s^a$; * 模拟经验:从模型中采样(近似MDP):$S'\sim P_{\eta}(S'|S,A),R=R_{\eta}(R|S,A)$。 根据经验来源,RL算法可分为三类: 1. model-free RL:learning * 无模型; * 从真实经验中直接学习价值函数或策略。 2. model-based RL:planning * 从真实经验中学习模型; * 从模拟经验中“规划”价值函数或策略。 3. **Dyna**:**learning + planning** * 从真实经验中学习模型; * 从**真实和模拟经验**中学习和规划价值函数或策略。 9. **Dyna**:结构: ![Dyna结构](http://qiniu.ljcheng.cc/image/image-20221202221907967.png) Dyna-Q算法:使用了Dyna思想的Q-learning: ![Dyna-Q算法流程图](http://qiniu.ljcheng.cc/image/image-20221202222050479.png) 10. **前向搜索**:通过往前看来采取最好的行为,这种算法把当前状态$S_t$作为根节点构建了一棵搜索树,使用MDP模型进行前向搜索。 ![前向搜索](http://qiniu.ljcheng.cc/image/image-20221202222721534.png) 核心思想:无需解决整个MDP,而**仅需构建一个从当前状态开始与眼前的未来相关的子MDP**。 11. **基于模拟的搜索**:是**前向搜索的一种形式**,从当前时刻开始,使用**基于模拟采样的规划**,构建一棵专注于短期未来的前向搜索树;然后将这颗搜索树作为一个学习资源,使用**model-free**的强化学习算法来寻找最优策略: ![基于模拟的搜索](http://qiniu.ljcheng.cc/image/image-20221202223157673.png) 算法流程: * 从当前时刻t开始,从**模型**或**实际经历**中进行采样,形成从当前状态开始到终止状态$S_T$的一系列episode:$\{s_t^k,A_t^k,R_{t+1}^k,...,S^k_T\}^K_{k=1}\sim M_v$; * 有了这些episode资源后,使用model-free的RL算法,若使用的是MC control,则该算法称为蒙特卡洛搜索;若使用的是Sarsa,则称为TD搜索; 12. **简单蒙特卡洛搜索(Simple Monte-)**: 1. 给定一个模型$M_v$(已训练好的,可以与之交互的)和一个**模拟策略**$\pi$(任意策略,可以是训练好的也可以是随机策略); 2. 针对动作空间中的每一个行为$a \epsilon A$: * 从当前(实际)状态$s_t$开始模拟出K个episodes: $$ \{s_t,a,R_{t+1}^k,S_{t+1}^k,A_{t+1}^k,...,S^k_T\}^K_{k=1}\sim M_v,\pi $$ * 使用**平均收获**(蒙特卡洛收获)来评估当前动作a的行为价值$Q(s_t,a)$: $$ Q(s_t,a)=\frac{1}{K}\sum_{k=1}^{K}G_t\overset{P}{\rightarrow}q_{\pi}(s_t,a) $$ 3. 选择一个有最大$Q(s_t,a)$的行为作为实际要采取的行为$a_t$: $$ a_t=\underset{a\epsilon A}{argmax}Q(s_t,a) $$ 13. **蒙特卡洛树搜索(Monte-Carlo Tree Search)**:蒙特卡洛树搜索是一种高效的搜索方法,它使用当前的模拟策略构建一棵基于当前状态$s_t$的搜索树。**和简单蒙特卡洛搜索不同的是**,蒙特卡洛树搜索方法将**评估整棵搜索树中每一个状态行为对的价值,并在此基础上改善基于模拟采样的策略**。具体算法为: 1. 给定一个模型$M_v$; 2. 从当前状态$s_t$开始,使用当前的模拟策略$\pi$,模拟生成K个episodes: $$ \{s_t,A_t^k,R_{t+1}^k,S_{t+1}^k,A_{t+1}^k,...,S^k_T\}^K_{k=1}\sim M_v,\pi $$ 3. 构建一棵**包括个体所有经历过的状态和行为**的搜索树; 4. 对于搜索树中的每一个状态行为对(s,a),**计算从该(s,a)开始的所有完整episode收获的平均值**(即$\frac{1}{K}\sum_{k=1}^{K}G_t$),以此来估算该状态行为对的价值Q(s,a); 5. 当搜索过程结束,即所有s, a的Q值都得到更新后,选择搜索树中一个有最大$Q(s_t,a)$的行为作为实际要采取的行为$a_t$: $$ a_t=\underset{a\epsilon A}{argmax}Q(s_t,a) $$ 蒙特卡洛树搜索的一个特点是在构建搜素树的过程中更新了搜索树内状态动作对的价值,利用这些信息可以更新模拟策略,**使得模拟策略得到改进**。 蒙特卡洛树搜索的每次过程称为一次**模拟(simulation)**,每一次模拟结束,策略将得到改进,每次模拟包括两个阶段(in-tree,out-of-tree): * 树内确定性策略(Tree Policy):选择动作以最大限度提高Q(s,a); * 树外默认策略(Default Policy):随机选择动作; 每次模拟重复: * 使用蒙特卡洛评估评估状态Q(s,a); * 同时使用基于$\varepsilon-greedy$的搜索策略使得搜索树不断地扩展,策略也将不断得到改善。 上述方法就相当于在某一个状态$s_t$时,针对模拟的经历使用MC control来寻找以当前状态$s_t$为根状态的最优策略,并使得策略最终收敛至最优策略。 实例:围棋游戏。 优点: * 蒙特卡洛树搜索是高度选择性的,是一种基于导致最好结果的行为越优先被选择的搜索方法; * 蒙特卡洛树搜索可以动态地评估各状态的价值,这种动态更新的方法与DP不同,后者聚焦于整个状态空间,而蒙特卡洛树搜索则立足于当前状态,动态更新与当前状态相关的状态价值;同时使用了采样避免维度灾难;同时,由于它仅依靠采样,因此适用于那些“黑盒”模型。 这些优点决定了蒙特卡洛树搜索是可以**并行训练和处理**的。 14. **TD搜索**:使用TD而不是MC进行搜索,用到了bootstrapping的思想。MC搜索是对从当前状态开始的一个子MDP问题应用MC控制,DP搜索则可以看成对从当前状态开始的一个子MDP问题应用SARSA学习。 相比于MC搜索,TD搜索不必模拟Episode到终止状态,其仅聚焦于某一个节点的状态,这对于一些有回路或众多旁路的节点来说更加有意义(即对应可能无终止状态的MDP),这是因为在使用下一个节点估计当前节点的价值时,下一个节点的价值信息可能已经是经过充分模拟探索了的,在此基础上更新的当前节点价值会更加准确。 15. **Dyna-2**:在Dyna-2中,智能体存储了两组**特征权重**: * 一组反映了智能体的**长期记忆**,该记忆是智能体从真实经历中使用TD学习得到,它反映了智能体对于某一特定强化学习问题的**普遍性**的经验; * 另一组反映了智能体的**短期记忆**,该记忆是智能体从基于模拟经历中使用TD搜索得到,它反映了智能体对于某一特定强化学习问题**在特定条件下(如某一episode、某一状态下)**的特定的、局部适用的经验; Dyna-2算法最终**将两套特征权重下产生的价值综合起来**进行决策,以期望得到更优秀的策略。 ## 学习资源 ### 一、视频 1. 李宏毅老师,yyds![视频链接](https://www.bilibili.com/video/BV1UE411G78S?spm_id_from=333.337.search-card.all.click) 2. 莫烦永远是你想在快速入门一项技术时的不二之选:[视频链接]( https://www.bilibili.com/video/BV13W411Y75P?spm_id_from=333.337.search-card.all.click) 3. 个人非常喜欢的一套教程,王树森老师的课程深入浅出,以一种很明白的方式讲述了从上层算法思想到涉及的底层数学和优化理论,适合零基础且想系统地学习强化学习的小白,需要科学上网(B站上的那个不太全):[视频链接]( https://www.youtube.com/watch?v=vmkRMvhCW5c&list=PLvOO0btloRnsiqM72G4Uid0UWljikENlU) 4. David Silver(DeepMind总工程师,AlphaGo创始人之一)经典教程,只是中文字幕机翻感觉太严重:[视频链接](https://www.bilibili.com/video/BV1nW411r7c7?spm_id_from=333.337.search-card.all.click) 5. UC Berkeley CS 285 深度强化学习的经典教程:[视频链接](https://www.youtube.com/watch?v=JHrlF10v2Og&list=PL_iWQOsE6TfXxKgI1GgyV1B_Xa0DxE5eH) ### 二、博客 1. EasyRL(又称“蘑菇书”),融合了多套经典教程,**个人认为最好的在线RL教程(没有之一)**,[教程链接]( https://datawhalechina.github.io/easy-rl/#/); 2. 王树森老师视频的配套教材,[GitHub仓库链接](https://github.com/wangshusen/DRL); 3. 莫烦视频教程的文字版,附有代码实现(TF1版本),[博客链接](https://mofanpy.com/tutorials/machine-learning/reinforcement-learning/),在这里还能看到PyTorch版本的DQN代码,[博客链接](https://mofanpy.com/tutorials/machine-learning/torch/DQN/)。 ### 三、课本 1. 《Reinforcement Learning: An Introduction》,Sutton老爷子经典之作,David Silver的教程也是以这本书作为教材进行讲解; 2. 《动手学强化学习》,这本书个人没有看过,但在网上人气很高,同时也得到了如李沐、李航等大牛的力荐,因此我把它放在这里; 3. 《深入浅出强化学习:原理入门》,这是我开始学习强化学习时买的一本书,整体结构类似于《Reinforcement Learning: An Introduction》,但在此基础上加入了不少当前流行的算法,有时也会对当前章节涉及的一些数学基础进行扩充,内容比较全面,但某些地方的语句感觉不太连贯,看起来有些生硬。整体上还是推荐的。 ## 参考链接 [EasyRL](https://datawhalechina.github.io/easy-rl/#/) 最后修改:2022 年 12 月 31 日 03 : 48 PM © 允许规范转载 赞赏 如果觉得我的文章对你有用,请随意赞赏 赞赏作者 支付宝微信
39 条评论
《橙花盛开》爱情片高清在线免费观看:https://www.jgz518.com/xingkong/56908.html
《老中医》国产剧高清在线免费观看:https://www.jgz518.com/xingkong/32923.html
《家有活宝国语》剧情片高清在线免费观看:https://www.jgz518.com/xingkong/128716.html
《为何那样,奉尚先生》韩国剧高清在线免费观看:https://www.jgz518.com/xingkong/105505.html
《橙花盛开》爱情片高清在线免费观看:https://www.jgz518.com/xingkong/56908.html
《老中医》国产剧高清在线免费观看:https://www.jgz518.com/xingkong/32923.html
《为何那样,奉尚先生》韩国剧高清在线免费观看:https://www.jgz518.com/xingkong/105505.html
《家有活宝国语》剧情片高清在线免费观看:https://www.jgz518.com/xingkong/128716.html
《为何那样,奉尚先生》韩国剧高清在线免费观看:https://www.jgz518.com/xingkong/105505.html
《双面线索》动作片高清在线免费观看:https://www.jgz518.com/xingkong/29857.html
《阿尔法狗》剧情片高清在线免费观看:https://www.jgz518.com/xingkong/6004.html
《阿尔法狗》剧情片高清在线免费观看:https://www.jgz518.com/xingkong/6004.html
《触摸未来第二季》欧美剧高清在线免费观看:https://www.jgz518.com/xingkong/118320.html
真棒!
真棒!
真棒!
揭秘传奇私服:单职业九魔版全新冒险之旅:https://501h.com/heji/2024-10-11/41404.html
文章的确不错啊https://www.cscnn.com/
文章的确不错啊https://www.cscnn.com/
文章的确不错啊https://www.cscnn.com/
想想你的文章写的特别好www.jiwenlaw.com
看的我热血沸腾啊www.jiwenlaw.com
看的我热血沸腾啊https://www.ea55.com/
不错不错,我喜欢看 https://www.ea55.com/
不错不错,我喜欢看 https://www.ea55.com/
想想你的文章写的特别好https://www.237fa.com/
不错不错,我喜欢看 https://www.237fa.com/
不错不错,我喜欢看 https://www.237fa.com/
怎么收藏这篇文章?
怎么收藏这篇文章?
叼茂SEO.bfbikes.com
想想你的文章写的特别好https://www.jiwenlaw.com/
看的我热血沸腾啊
想想你的文章写的特别好https://www.jiwenlaw.com/
叼茂SEO.bfbikes.com
叼茂SEO.bfbikes.com
博主真是太厉害了!!!
博主真是太厉害了!!!
太强了,写的太棒了!!!为什么不分成几个博客发呢?