一、策略梯度1、策略梯度的一些概念强化学习有 3 个组成部分演员actor、环境和奖励函数。智能体玩视频游戏时演员负责操控游戏的摇杆 比如向左、向右、开火等操作环境就是游戏的主机负责控制游戏的画面、负责控制怪兽的移动等奖励函数就是当我们做什么事情、发生什么状况的时候可以得到多少分数 比如打败一只怪兽得到 20 分等。在强化学习里环境与奖励函数不是我们可以控制的它们是在开始学习之前给定的。我们唯一需要做的就是调整演员里面的策略使得演员可以得到最大的奖励。演员里面的策略决定了演员的动作即给定一个输入它会输出演员现在应该要执行的动作。图1.1 强化学习的组成部分演员Actor/策略一个决策神经网络参数为输入的是观测如像素输出的是动作的概率分布是可控的。类似于玩家操控遥杆左右开火。环境Environment:世界的物理规则和游戏引擎接收到动作返回到下一个状态。这个是不可控的。类似于游戏渲染画面、控制怪兽移动或者是围棋对手的落子位置。奖励函数给分机制定义了我们想要什么是不可控的例如打死怪兽的20分围棋赢棋的1分。核心目标环境与奖励函数在训练开始前就已固定唯一能做的是调整策略网络里的参数让智能体在与环境交互中获得“总分数”尽可能的高。接下来我们用一个例子来说明演员与环境交互的过程。如图 1.2 所示首先演员会看到一个视频游戏的初始画面接下来它会根据内部的网络内部的策略来决定一个动作。假设演员现在决定的动作是向右决定完动作以后它就会得到一个奖励奖励代表它采取这个动作以后得到的分数。我们把游戏初始的画面记作 把第一次执行的动作记作把第一次执行动作以后得到的奖励记作。不同的人有不同的记法有人觉得在执行得到的奖励应该记为这两种记法都可以。演员决定一个动作以后就会看到一个新的游戏画面。把输入给演员演员决定要开火它可能打败了一只怪兽就得到五分。这个过程反复地持续下去直到在某一个时间点执行某一个动作得到奖励之后环境决定这个游戏结束。例如如果在这个游戏里面我们控制宇宙飞船去击杀怪兽如果宇宙飞船被毁或是把所有的怪兽都清空游戏就结束了。图 1.2回报的例子如图 1.3 所示一场游戏称为一个回合(Episode)。将这场游戏里面得到的所有奖励都加起来就是总奖励total reward也就是回报我们用R来表示它。演员要想办法来最大化它可以得到的奖励。图 1.3 回报的例子如图 1.4 所示首先环境是一个函数我们可以把游戏的主机看成一个函数虽然它不一定是神经网络可能是基于规则的rule-based模型但我们可以把它看作一个函数。1.初始状态这个函数一开始先“吐”出一个状态游戏画面2.决策与执行接下来演员看到游戏画面以后根据内部网络计算动作概率随机采样就“吐”出动作3.环境反馈环境把动作当作它的输入再“吐”出新的游戏画面。4.循环往复演员看到新的游戏画面再采取新的动作。环境看到再“吐”出 ......这个过程会一直持续下去直到环境觉得应该要停止为止。图 1.4 演员和环境在一场游戏里面我们把环境输出的 s与演员输出的动作 a全部组合起来就是一个轨迹即给定演员的参数我们可以计算某个轨迹发生的概率为其中公式中是来自环境的项是初始环画面的概率是状态转移概率这是完全是游戏主机内部的机制这些不包含参数无法改变。来自智能体的项是策略网络输出的概率比入看到怪兽网络输出“开火”概率0.8左移概率0.2这是唯一我们能够调整来改变的部分。注虽然轨迹的概率受环境的影响但是当我们对求导时与环境相关的导数全部为0因此不会影响到梯度的计算方向。如果主机输出游戏画面的时候没有概率游戏的每次的画面都一样我们只要找到一条路径就可以过关了这样的游戏没有意义。所以输出游戏画面时通常有一定概率给定同样的前一个画面我们采取同样的动作下次产生的画面不一定是一样的。反复执行下去我们就可以计算一个轨迹出现的概率有多大。某个轨迹出现的概率取决于环境的动作和智能体的动作。环境的动作是指环境根据其函数内部的参数或内部的规则采取的动作。演员的动作不同每个同样的轨迹就有不同的出现的概率。在强化学习里面除了环境与演员以外还有奖励函数。如图 1.5 所示奖励函数根据在某一个状态采取的某一个动作决定这个动作可以得到的分数。对奖励函数输入、它会输出输入、奖励函数会输出。 我们把轨迹所有的奖励都加起来就得到了其代表某一个轨迹的奖励。图1.5 期望的奖励在某一场游戏的某一个回合里面我们会得到。我们要做的就是调整演员内部的参数 使得的值越大越好。 但实际上并不只是一个标量scalar它是一个随机变量因为演员在给定同样的状态下会采取什么样的动作这是有随机性的。环境在给定同样的观测时要采取什么样的动作要产生什么样的观测本身也是有随机性的所以是一个随机变量。我们能够计算的是的期望值。给定某一组参数我们可计算的期望值为我们要穷举所有可能的轨迹 每一个轨迹都有一个概率。比如对应的模型很强如果有一个回合很快就死掉了因为这种情况很少会发生所以该回合对应的轨迹的概率就很小如果有一个回合一直没死因为这种情况很可能发生所以该回合对应的轨迹的概率就很大。我们可以根据算出某一个轨迹出现的概率接下来计算的总奖励。总奖励使用出现的概率进行加权对所有的进行求和就是期望值。给定一个参数我们可以计算期望值为从分布采样一个轨迹计算的期望值就是期望奖励expected reward。我们要最大化期望奖励。因为我们要让奖励越大越好所以可以使用梯度上升gradient ascent来最大化期望奖励。要进行梯度上升我们先要计算期望奖励的梯度。我们对做梯度运算。假设在执行某一个回合时发现该轨迹的奖励是正的因此要增加这个轨迹的概率反之如果奖励为负就要减少该轨迹的概率。这句话表述是错误的因为整个轨迹包含了环境转移概率这个概率我们控制不了唯一能控制的就是策略网络输出的条件概率应该这样叙述当整条轨迹的奖励是正的所以逆向传播这个奖励在该轨迹经过的每一个状态—动作对上他们各自的概率都按比例增加反之则减少以上的这个操作该怎么实现呢咱们使用梯度上升来更新参数原来有一个参数把加上梯度当然我们要有一个学习率学习率也是要调整可以用Adam、PMSProp等方法来调整学习率即实际上要计算梯度首先需要收集很多s与a的对还要知道这些s与a在于环境交互的时候会得多少奖励这些数据怎么收集呢我们要用参数为的智能体与环境交互 也就是拿已经训练好的智能体先与环境交互交互完以后就可以得到大量游戏的数据我们会记录在第一场游戏里面我们在状态采取动作在状态采取动作。 智能体本身是有随机性的在同样的状态下不是每次都会采取动作的所以我们要记录在状态采取、在状态采取等整场游戏结束以后得到的奖励是。我们会采样到另外一些数据也就是另外一场游戏。在另外一场游戏里面在状态采取在状态采取我们采样到的就是得到的奖励是。然后把采样到的数据代入到这个梯度公式从而更新模型。图 策略梯度更新完模型之后需要重新采样数据进行更新一般策略梯度policy gradientPG采样的数据只会用一次。我们可以把强化学习想成一个分类问题这个分类问题就是输入一个图像输出某个类。在解决分类问题时我们要收集一些训练数据数据中要有输入与输出的对。在实现的时候我们把状态当作分类器的输入就像在解决图像分类的问题只是现在的类不是图像里面的东西而是看到这张图像我们要采取什么样的动作每一个动作就是一个类。比如第一个类是向左第二个类是向右第三个类是开火。在解决分类问题时我们要有输入和正确的输出要有训练数据。但在强化学习中我们通过采样来获得训练数据。假设在采样的过程中在某个状态下我们采样到要采取动作 那么就把动作当作标准答案ground truth。比如我们在某个状态下采样到要向左。因为是采样所以向左这个动作不一定概率最高。假设我们采样到向左在训练的时候让智能体调整网络的参数 如果看到某个状态我们就向左。在一般的分类问题里面我们在实现分类的时候目标函数都会写成最小化交叉熵cross entropy最小化交叉熵就是最大化对数似然log likelihood。图 策略梯度实现细节我们在解决分类问题的时候目标函数就是最大化或最小化的对象因为我们现在是最大化似然likelihood所以其实是最大化我们要最大化强化学习与分类问题唯一不同的地方是损失前面乘一个权重就是整场游戏得到的总奖励而不是在状态s采取动作a的时候得到的奖励即自动求梯度2、策略梯度实现技巧2.1 技巧1 添加基线如果给定状态采取动作整场游戏得到正的奖励就要增加的概率。如果给定状态执行动作整场游戏得到负的奖励就要减小的概率。但在很多游戏里面奖励总是正的最低都是 0。比如打乒乓球游戏 分数为 0 ~ 21 分所以总是正的。假设我们直接使用上面的公式在训练的时候告诉模型不管是什么动作都应该要把它的概率提升。假设在某状态下有 3 个动作A好动作、B极好动作、C没被采样到的动作。A 的权重是 1概率提升少。B 的权重是 20概率提升多。C 没有被采样到概率不变。因为所有动作概率之和必须等于 1Softmax 归一化提升少的 A 和提升多的 B会挤压掉 C 的概率空间导致 C 的概率下降。但 C 不一定是个坏动作它只是运气不好没被采样到。这会导致模型错误地惩罚了 C。基线的解决方案引入一个偏置项基线将权重变为。通常取即历史平均分。更新后的梯度效果现在权重有正有负了。拿到 10 分低于平均 20 分的动作会被抑制拿到 30 分高于平均的动作会被鼓励。这极大地降低了训练的方差让模型更稳定。2.2 技巧2 分配合适的分数假设一局游戏有 3 步第 1 步状态 A动作 左得了 100 分。第 2 步状态 B动作 右得了 -2 分。第 3 步状态 C动作 跳得了 -1 分。总分97。按照原始公式状态 B 的“右”和状态 C 的“跳”都因为沾了第一步的光而被乘以 97 去提升概率。但事实上这两步明明是扣分的应该被抑制。把整局的功劳/罪过平均分配给每一步是非常不公平的。解决方案强化学习遵循马尔可夫性质当前动作只会影响未来不会影响过去。因此在评估时间步 tt 的动作 atat 时我们不应该把 tt 时刻之前获得的奖励算进来。我们引入未来折扣总回报其中是折扣因子0.9 或 0.99。为什么引入折扣因子a. 虽然动作会影响未来所有奖励但时间越久远影响越模糊。b. 如果 tt 时刻的动作导致 10 步后得了 100 分这 100 分可能只是巧合。乘上如 0.910≈0.350.910≈0.35可以削弱远期奖励的影响强调“即时反馈”。c. 在数学上折扣因子能保证无限长轨迹的奖励和是有限的收敛。公式即事实上通常是一个网络估计出来的是一个网络的输出我们把这一项称为优势函数用来代表优势函数。优势函数取决于和我们就是要计算在某个状态采取某个动作的时候优势函数的值。在计算优势函数值时我们要计算需要有一个模型与环境交互才能知道接下来得到的奖励。优势函数的上标是代表用模型与环境交互。从时刻 t开始到游戏结束为止所有的加和减去这就是优势函数。优势函数的意义是假设我们在某一个状态执行某一个动作相较于其他可能的动作有多好。优势函数在意的不是绝对的好而是相对的好即相对优势relative advantage。因为在优势函数中我们会减去一个基线所以这个动作是相对的好不是绝对的好。通常可以由一个网络估计出来这个网络称为评论员critic。3、蒙特卡洛策略梯度REINFORCE算法3.1 算法工作模式REINFORCE 采用回合制更新Monte Carlo Updatea. 交互拿着当前的策略网络从头到尾完整地玩一局游戏记录下每一步的b. 计算回报游戏结束后我们从最后一步倒推计算每个时刻的因为需要知道未来才能算现在。c. 更新网络利用这一整局的所有数据一次性计算损失并更新网络参数。d. 丢弃数据更新完参数后这局的数据立即作废。下一次更新必须用新的策略重新玩游戏采样同策略 On-policy 特性。3.2 代码层面的理解很多初学者对损失函数L - G_t * log(prob)感到困惑。我们可以通过与“手写数字识别监督学习”对比来透彻理解手写数字识别监督学习1、输入图片网络输出每个数字的概率。2、标准答案是[0, 0, 1, 0, ...]独热向量数字 9。3、损失是交叉熵。这是绝对的指导不管什么情况看到这张图必须输出 9。REINFORCE强化学习1、输入游戏画面网络输出“左、右、开火”的概率。2、智能体根据概率随机采样得到了“右”假设这次采样命中了概率较小的动作。3、我们把采样到的动作“右”当作临时的“标准答案”[0, 1, 0]。4、交叉熵告诉网络你要尽量增大“右”的概率。策略梯度损失损失计算Reinforce算法示意关键这个“右”不一定正确所以我们要乘以权重。如果这局游戏输了 很小甚至是负的说明“右”是个坏动作我们要轻柔地增大或者通过归一化变相减少它的概率。如果这局游戏赢了很大说明“右”是个好动作我们要猛力增大它的概率。总结损失 交叉熵(预测概率, 采样的动作) × 该动作的未来总回报。3.3 为什么数据只能用一次同策略的痛点因为更新了参数后策略网络的行为变了。之前用旧策略采样得到的轨迹在旧策略下出现的概率很高但在新策略下出现的概率已经改变了。用旧数据计算出的梯度方向已经不再指向新策略的最优方向。所以每次更新后必须丢掉所有旧数据重新采样。这也是后续 Actor-Critic 和 PPO 算法试图解决的效率问题。3.4 伪代码初始化策略网络参数 θ基线 b 0 对于每一轮迭代 1. 使用当前策略 π_θ 生成一个完整的轨迹 {s_1, a_1, r_1, ..., s_T, a_T, r_T} 2. 初始化 G 0创建一个空列表存放每一步的损失权重 3. 从最后一步 T 开始向前循环倒推 G r_t γ * G 将 (s_t, a_t, G) 存入列表 4. 计算基线 b 列表里所有 G 的平均值或者使用移动平均 5. 初始化损失 L 0 对于列表里的每一个 (s_t, a_t, G_t) prob 网络输出在 s_t 下选择 a_t 的概率 L - (G_t - b) * log(prob) 6. 执行梯度下降更新 θ使用 Adam 等优化器最小化 L 7. 清空轨迹列表以上内容参考磨菇树 Easy RL