ChatGPT通俗笔记:从GPT-N、RL之PPO算法到instructGPT、ChatGPT

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

前言

自从我那篇BERT通俗笔记一经发布然后就不断改、不断找人寻求反馈、不断改其中一位朋友倪老师(之前我司NLP高级班学员现课程助教老师之一)在谬赞BERT笔记无懈可击的同时给我建议到“后面估计可以尝试尝试在BERT的基础上讲一讲prompt学习了”然后我就看了下prompt学习一看果然牛..

再然后当我还在各种改BERT笔记的时候12月初突然出来了一个ChatGPT刷爆朋友圈即便很多之前不接触AI的朋友也在问ChatGPT这种类似聊天机器人却又胜过聊天机器人各种问题(上一次出现这种盛况的还是16年的AlphaGo)还有人让其根据要求写代码、写诗比如让其学千古第一才女李清照写词看大家真是乐在其中甚至还有人惊呼ChatGPT会不会替代Google这类搜索引擎。

虽然大部分技术者对待ChatGPT还是比较冷静的毕竟它给的答案不像Google那样给出来源从而不能比较好的验证其正确程度(注意我这里的措辞“不能比较好的”、“正确程度”^_^)但最近遇到的几件事改变了我的一些看法

  1. 这两天我刷到一条新闻微软欲用 ChatGPT 扶必应“上位”对抗 Google导致即便很多技术从业者也不一定淡定了当然依然会有不少人始终淡定如一
  2. ChatGPT直接让其所在的公司OpenAI估值翻倍而我司七月在线的最新一期NLP大课NLP11也加入了chatGPT的原理解析
  3. 因为ChatGPT太火技术朋友经常会转发一些解释ChatGPT原理的资料目前看到的资料里先不说英文原始论文中文资料里现在各方面的知识、书籍、课程、资料很多但真正能让人一看就懂的非常非常少
  4. 当少数文章具备比较好的可读性之后你又会发现一旦涉及算法细节就千篇一律的泛泛而谈如果不是泛泛而谈的则更多堆砌概念和公式总之中文资料里可能因为instructGPT/ChatGPT刚出来不久的缘故兼顾可读性和细节性的文章少的可怜

本篇ChatGPT笔记会全力做到通俗易懂且循序渐进(尽最大努力让每一个初学者哪怕是文科生都能没有障碍的读懂每一字一句、每一个概念、每一个公式另本文配图均来自文末的参考文献可以认为是针对文末参考文献的学习笔记)

  • 一方面对于想了解ChatGPT背后原理和如何发展而来的逐一阐述从GPT/GPT2/GPT3到强化学习、PPO算法最后再到instructGPT、ChatGPT、SeqGAN
    且本文之前99%的文章都不会把PPO算法从头推到尾本文会把PPO从零推到尾按照“RL-策略梯度-重要性采样(重要性权重)-TRPO(增加信任区域和KL散度约束)-PPO”的顺序逐步介绍每一步推导(此部分内容核心参考自Easy RL教程)
  • 二方面为彻底照顾初学者本文会解释/说明清楚每一个公式甚至符号包括推导过程中不省任何一个必要的中间推导步骤以及必要的背景知识十步推导绝不略成三步

本笔记从1.6日开始写(1.15日完成初稿之后反复修改春节期间基本成型预计1月底完全成型届时质量将是1.15日初稿的1.5-2倍)ChatGPT之后再下一篇笔记应该是强化学习极简入门了。

第一部分 从GPT/GPT2到GPT3微调到prompt学习的过渡

1.1 GPT基于Transformer Decoder预训练 + 微调/Fineturn

在上一篇BERT笔记中我们已经了解到GPT是“Generative Pre-Training”的简称从名字看其含义是指的生成式的预训练。

GPT也采用两阶段过程第一个阶段是利用语言模型进行预训练第二阶段通过Fine-tuning的模式解决下游任务。 

下图展示了GPT的预训练过程其实和ELMO是类似的主要不同在于两点

  1. 首先特征抽取器不是用的LSTM而是用的Transformer毕竟它的特征抽取能力要强于LSTM这个选择很明显是很明智的
  2. 其次GPT的预训练虽然仍然是以语言模型作为目标任务但是采用的是单向的语言模型

    801922b26169dd269be29abc282b1ce8.png

有两点值得提一下

  • 作为侧重生成式任务的GPT选择了Transformer Decoder部分作为核心架构Decoder具备文本生成能力故GPT在Transformer Decoder的基础上搭建语言模型Transformer Block前馈神经网络feed forward + 自注意力机制self attention + 求和与归一化的前置LN层 + 残差
  • 关于Transformer 原理细节可以参看上一篇笔记BERT笔记(介绍的很细致)至于GPT的代码实现网上有不少资料可以参看比如GitHub

    61a6cc2a71dd2e3b126ff058cd5d045e.png

1.2 GPT2舍弃微调直接干zero-short learning

很多同学一看到DL便会想到大数据而数据量一大还用CPU处理的话很可能训练一个小任务都得半天而如果用GPU跑可能一两分钟就出来了。于此在深度学习大火的那几年特别是AlphaGo出来的16年起我司七月在线便分别为VIP、AI系统大课、在职提升大课、求职/论文/申博/留学1V1辅导提供GPU云平台进行实战训练。

然很多情况下高质量数据的获取是比较困难的比如医疗数据那怎么办呢既然暂时改变不了高质量数据匮乏的现状那就改变模型! 如此让模型能从少量样本中学习规律并具备推理能力便显得至关重要了。

最终针对小样本/零样本的N-shotLearning应运而生分为如下三种

  • Zero-shot Learning (零样本学习)是指在没有任何训练样本进行微调训练的情况下让预训练语言模型完成特定任务
  • One shot Learning (单样本学习)顾名思义是指在一个训练样本进行微调训练的情况下预训练语言模型完成特定任务
  • Few-shot Learning (少样本或小样本学习)类似的是指在只有少量样本进行微调训练的情况下预训练语言模型完成特定任务

而GPT-2不再使用二阶段训练模式(预训练+微调)而是彻底放弃了微调阶段仅通过大规模多领域的数据预训练让模型在Zero-shot Learming的设置下自己学会解决多任务的问题而且效果还不错(虽然GPT2通过Zero-shot Learming在有些任务的表现上尚且还不如SOTA模型但基本超越了一些简单模型说明潜力巨大)你说神不神奇

而GPT2在GPT1的基础上规模更大、模型更复杂。至于小样本学习的具体应用可以看下参考文献6。

1.3 GPT3开启NLP新范式prompt从而实现小样本学习

GPT3简单来说就是规模大、有钱多金、效果出奇好具体而言它的参数规模达到了1750亿并且使用45TB数据进行训练其预训练任务就是“句子接龙”给定前文持续预测下一个字而且只要有少量的文本数据就能作为模型的训练数据。

总之只需将自然语言的提示信息prompt和任务示例demonstration作为上下文输入给GPT-3它就可以在零样本或小样本的情况下执行任何NLP任务包括所谓的完形填空任务比如举个例子

比如假如我要判断“我喜欢这个电影" 这句话的情感“正面" 或者 "负面"原有的任务形式是把他看成一个分类问题

输入我喜欢这个电影

输出“正面" 或者 "负面"

而如果用Prompt Learning去解决的话任务可以变成“完形填空"

输入我喜欢这个电影整体上来看这是一个 __ 的电影

输出“有趣的" 或者 "无聊的"


言外之意即是即便是面对完形填空似的任务也能很好的解决

正因为GPT3首次把模型的规模带到了千亿级别开辟了大模型赛道其次也为NLP带来了一种新的范式promptprompt为GPT3带来了0样本、单样本、小样本的学习能力。而且更为关键的是在小样本的情况下其性能表现一度超越SOTA模型。

为形象描述举一个GPT-3在只有少量样本下的机器翻译使用范例如下图

  • 图中右侧是普通模型微调的过程模型通过大量训练预料进行训练然后基于特定的任务数据进行梯度迭代更新(gradient update)训练至手链后的模型才具备良好的翻译能力
  • 图中左侧是GPT3分别在0样本(只给出任务描述)、单样本(只给出任务描述+一个翻译样本)、小样本(给出任务描述+少量样本)的情况下所展示出的能力即便是小样本的情况下也远少于微调过程所需要的训练数据
    说白了就是在同等训练数据下GPT的性能远高于微调模式的SOTA模型

b74c354d63fc4bb1bd8fa73b87739185.png

至此我们对比下Fine-tuning和prompt learning的区别就是从Pre-train、Fine-tune到Pre-train、Prompt、Predict的过程

  • Fine-tuning中是预训练语言模型“迁就“各种下游任务。具体体现就是通过引入各种辅助任务loss将其添加到预训练模型中然后继续pre-training以便让其更加适配下游任务。总之这个过程中预训练语言模型做出了更多的牺牲
  • Prompting中是各种下游任务“迁就“预训练语言模型。我们需要对不同任务进行重构使得它达到适配预训练语言模型的效果。总之这个过程中是下游任务做出了更多的牺牲

1.4 GPT3.5爆火ChatGPT所基于的GPT模型

考虑到下文要讲的instructGPT和ChatGPT分别预计GPT3、GPT3.5所以本文还得再讲下GPT3.5相比GPT3的差别。

粗略的讲GPT-3.5 模型使用与 GPT-3 相同的预训练数据集但进行了额外的微调从而更擅长以下两点

  1. 更擅长上下文学习、对话
  2. 可以生成更加符合人类期待的反馈或者说模型与人类对齐例如零样本问答、生成安全和公正的对话回复、拒绝超出模型它知识范围的问题

    91147cd7289babf52ec3dbef29fd8656.png

考虑到本文的主旨核心ChatGPT用到了RLHF和PPO所以本文的第二部分将从强化学习讲到PPO算法。

第二部分 ChatGPT中的几个RL关键概念从策略梯度到PPO算法

2.1 强化学习必须掌握的基础

2.1.1 什么是强化学习

强化学习里面的概念、公式相比ML/DL特别多初学者刚学RL时很容易被接连不断的概念、公式给绕晕而且经常忘记概念与公式符号表达的一一对应为此我建议学习RL的第一步就是一定要扎实关于RL的一些最基本的概念、公式(不要在扎实基础的阶段图快或图囵吞枣不然后面得花更多的时间、更大的代价去弥补)且把概念与公式的一一对应关系牢记于心这很重要。

当然为最大限度的提高本文的可读性我会尽可能的多举例、多配图。

但RL之外像高等数学里的什么叫导数、多元函数、偏导数、以及AI一些最基本的概念比如损失函数、梯度/梯度下降等可以直接Wikipedia上查看相关概念本文则不赘述了毕竟可以为通俗而增加篇幅但不为了介绍而介绍式的增加篇幅避免影响完读率^_^。话休絮烦下面开始正题。

强化学习reinforcement learningRL基于智能体agent在复杂、不确定的环境environment中最大化它能获得的奖励从而达到自主决策的目的。

经典的强化学习模型可以总结为下图的形式你可以理解为任何强化学习都包含这几个基本部分智能体、行为、环境、状态、奖励

e8fc39f9f7f291dc8b121858a201545b.png

一般的文章在介绍这些概念时很容易一带而过这里我把每个概念都逐一解释下

  • Agent一般译为智能体就是我们要训练的模型类似玩超级玛丽的时候操纵马里奥做出相应的动作而这个马里奥就是Agent
  • action(简记为a)玩超级玛丽的时候你会控制马里奥做三个动作即向左走、向右走和向上跳而马里奥做的这三个动作就是action
  • Environment即环境它是提供reward的某个对象它可以是AlphaGo中的人类棋手也可以是自动驾驶中的人类驾驶员甚至可以是某些游戏AI里的游戏规则
  • reward(简记为r)这个奖赏可以类比为在明确目标的情况下接近目标意味着做得好则奖远离目标意味着做的不好则惩最终达到收益/奖励最大化且这个奖励是强化学习的核心
  • State(简介为s)可以理解成状态或环境状态

总的而言Agent通过感知环境Environment从而获取环境的状态state进而依据策略决策从而执行动作action最后得到奖励reward然后再继续按此流程“感知状态-依据策略执行动作-得到奖励”循环进行。

另外有两点值得一提

  • 第一不同状态出现的概率不一样比如明天是天晴还是下雨不一定即便看了天气预报也只是预测大概率是天晴而已同一状态下执行不同动作的概率也不一样比如即便在明天是天晴的概率下你大概率不会带伞但依然不排除你可能会防止突然下雨而带伞
  • 第二另外值得一提的是人的一言一行会受到评估好优化言行对于智能体也类似比如有状态则有对状态的评估有状态下执行的动作则有对状态下执行动作的评估那怎么评估状态的价值、怎么评估状态下动作的价值呢
    于此也就出来了所谓的状态价值函数、动作价值函数

    最终一切评估结合奖励毕竟我们的目的是需要最大化奖励从而不断采取最优的策略所谓最优策略就是在同一环境或不同环境下采取的最佳动作实践

进一步具体而言“感知状态-依据策略执行动作-得到奖励”的整个过程分为两步

  • 第一步它会根据当前状态State来采取动作action
    我们会通过“状态价值函数”对当前状态进行评估可以用gif.latex?V_%7B%5Cpi%20%7D%28s_%7Bt%7D%29表示状态gif.latex?s在策略\pi下的价值
    而采取什么样的动作就涉及到策略policy策略函数可以表述为gif.latex?%5Cpi函数(当然这里的gif.latex?%5Cpi跟圆周率没半毛钱关系)从而可得gif.latex?a%3D%5Cpi%20%28s%29意味着输入状态gif.latex?s策略函数输出动作gif.latex?a
    此外还会有这样的表述gif.latex?a%3D%5Cpi%20%28s%7C%5Ctheta%20%29在输入状态s确定的情况下输出的动作gif.latex?a纸盒后面的参数gif.latex?%5Ctheta有关这个gif.latex?%5Ctheta就是策略函数的参数

    再比如这种gif.latex?%5Cpi%20%28a%7Cs%29%20%3D%20p%28a_%7Bt%7D%3Da%7Cs_%7Bt%7D%3Ds%29而这相当于输入一个状态gif.latex?s下智能体采取某个动作的概率这个啥意思呢意思是在状态gif.latex?s确定之下智能体采取不同动作的概率是不同的比如当到了中午吃饭的时刻但家里没有食材了这个时候你可能有50%的概率去买食材也可能有30%的概率直接订外卖有20%的概率到冰箱里随便找点吃的
  • 第二步记录被反馈的奖赏reward以便下次再到相同状态时能采取更优的动作
    所谓是指我们在当前状态采取了某个动作可以得到多大的奖励奖励函数是状态和动作的函数即gif.latex?r%3DR%28a%7Cs%29如果和这个公式结合起来gif.latex?a%3D%5Cpi%20%28s%7C%5Ctheta%20%29就是gif.latex?r%3DR%28%5Cpi%20%28s%7C%5Ctheta%29%7Cs%29

    实际中因为一个状态可以得到的奖励是持久的(当然越往后某个事给的回报率越低也即奖励因子越小)故某个这个状态导致的期望回报奖励为 gif.latex?R%28s%2Ca%29%3D%5Cmathbb%7BE%7D%5Cleft%5Br_%7Bt+1%7D%20%5Cmid%20s_%7Bt%7D%3Ds%2C%20a_%7Bt%7D%3Da%5Cright%5D

    举个例子一个少年在面对“上大学、去打工、在家啃老”这三种状态哪一种更能实现人生的价值呢
    相信很多人为长远发展都会选择上大学因为身边有太多人因为上了大学而好事连连比如读研读博留学深造、进入大厂、娶个漂亮老婆、生个聪明孩子
    当然了上大学好处肯定多多但上大学这个状态对上面4件好事所给予的贡献必然是逐级降低毕竟越往后越会有更多或更重要的因素成就后面的好事总不能因为所有好事都百分百归功于最开头选择了“上大学”这个状态/决策嘛

    且即便同一种状态下不同策略下采取不同的动作这就涉及到“动作价值函数”对动作的评估可以用gif.latex?Q_%7B%5Cpi%20%7D%28s_%7Bt%7D%2Ca_%7Bt%7D%29表示为状态gif.latex?s在策略gif.latex?%5Cpi下选取动作a的价值这就是大名鼎鼎的Q函数得到Q函数后进入某个状态要采取的最优动作便可以通过Q函数得到即Q_{\pi}\left(s_{t}, \pi^{\prime}(s_{t})\right)=\max _{a \in A} Q_{\pi}(s_{t}, a_{t})=Q_{\pi}(s_{t}, \pi(s_{t}))=V_{\pi}(s_{t})
    比如我希望最短时间内把柴砍完如果我鼠目寸光可能会选择不磨刀直接砍看似一开始柴被一个个劈开了 好像很快但因为刀口有绣实际全部砍完可能花了30分钟但如果我明白磨刀不误砍柴工则我可能花了1分钟磨刀然后再用10分钟就把柴砍完了

2.1.2 RL与监督学习的区别和RL方法的分类

此外RL和监督学习supervised learning的区别

  • 监督学习有标签告诉算法什么样的输入对应着什么样的输出譬如分类、回归等问题一开始的分类不准没关系通过建立损失函数+反向传播不断调整优化
    所以对于监督学习目标是找到一个最优的模型函数使其在训练数据集上最小化一个给定的损失函数相当于最小化预测误差
    最优模型 = arg minE_{(特征,标签)-数据分布} [损失函数(标签,模型(特征)]

    RL没有标签告诉它在某种情况下应该做出什么样的行为只有一个做出一系列行为后最终反馈回来的reward然后判断当前选择的行为是好是坏
    相当于RL的目标是最大化智能体策略在和动态环境交互过程中的价值而策略的价值可以等价转换成奖励函数在策略的占用度量期望即最大化累计下来的奖励期望
    最优策略 = arg maxE(状态,动作)-策略的占用度量 [奖励函数(状态,动作)]

    注所谓占用度量是为了衡量一个智能体决策与动态环境的交互过程中采样到一个具体的动作状态对(state-action pair)的概率分布
  • 监督学习如果做了比较坏的选择则会立刻反馈给算法
    RL的结果反馈有延时有时候可能需要走了很多步以后才知道之前某步的选择是好还是坏
  • 监督学习中输入是独立分布的即各项数据之间没有关联
    RL面对的输入总是在变化每当算法做出一个行为它就影响了下一次决策的输入

进一步我们有(先做个简单了解下文会详细阐述特别是其中的PPO算法)

  • 基于值函数的方法通过求解一个状态或者状态下某个动作的估值为手段从而寻找最佳的价值函数找到价值函数后再提取最佳策略
    比如Q-learning、DQN等适合离散的环境下比如围棋和某些游戏领域

    BTW因为本文主旨ChatGPT用的RL算法是PPO和Q-learning没有最直接的联系所以本文不阐述Q-learning但下一篇笔记强化学习极简入门会仔细讲
  • 基于策略的方法一般先进行策略评估即对当前已经搜索到的策略函数进行估值得到估值后进行策略改进不断重复这两步直至策略收敛
    比如策略梯度法PG算法policy gradient适合连续动作的场景比如机器人控制领域
    以及Actor-Criti(一般被翻译为演员-评委算法)既学习价值函数有学习策略函数不过Actor-Criti本质上是属于基于策略的算法毕竟算法的目标是优化一个带参数的策略只是会额外学习价值函数从而帮助策略函数更好的学习

    此外还有对策略梯度算法的改进比如TRPO算法、PPO算法当然也有的文章会把PPO算法称之为是一种Actor-Critic架构本文会重点阐述

2.1.3 RL的两个关键概念马尔科夫、KL散度

RL通常是一个马尔科夫决策过程但何谓马尔科夫呢据强化学习2一书的第47页所说

在马尔科夫决策过程中gif.latex?S_%7Bt%7Dgif.latex?R_%7Bt%7D的每个可能的值出现的概率只取决于前一个状态gif.latex?S_%7Bt-1%7D和前一个动作gif.latex?A_%7Bt-1%7D并且与更早之前的状态和动作完全无关这个限制不是针对决策过程而是针对状态的状态必须包括过去智能体和环境交互的方方面面的信息这些信息会对未来产生一定影响这样状态就被认为具有马尔科夫性。

换言之下一步的状态取决于当前的状态以及当前采取的动作。它由状态转移概率和奖励函数两个部分组成

  • 状态转移概率即gif.latex?p_%7Bs%20s%5E%7B%5Cprime%7D%7D%5E%7Ba%7D%3Dp%5Cleft%28s_%7Bt+1%7D%3Ds%5E%7B%5Cprime%7D%20%5Cmid%20s_%7Bt%7D%3Ds%2C%20a_%7Bt%7D%3Da%5Cright%29
  • 奖励函数即gif.latex?R%28s%2Ca%29%3D%5Cmathbb%7BE%7D%5Cleft%5Br_%7Bt+1%7D%20%5Cmid%20s_%7Bt%7D%3Ds%2C%20a_%7Bt%7D%3Da%5Cright%5D

当我们有了策略、价值函数和模型3个组成部分后就形成了一个马尔可夫决策过程Markov decision process。如下图所示这个决策过程可视化了状态之间的转移以及采取的动作。

1dd8b918fb687a41272d5ad52d0d19e6.png

接下来再KL散度KL 散度衡量两个数据分布pq之间的差异。

ce4fe6fcbea84d2f9e5b15938b495777.png

我们将其重新用于衡量两个分布之间的差异

e9655a6ca8b64843a0707db4baa093cb.png

那么我们如何限制政策变化以确保我们不会做出错误的决定呢事实证明我们可以找到一个下界函数 M作为
6854d5edf3354891a7011af6e68a51ed.png

3afb507130294a619257823a3eda8651.png

 其中L(\theta)等于

7a63752b0edf4558aa0627922c018fb3.png

2.3 策略梯度与其两个问题采样效率低下与步长难以确定

2.3.1 什么是策略梯度

本节推导的核心内容参考自Easy RL教程等资料。另都说多一个公式则少一个读者本文要打破这点虽然本节推导很多但每一步推导都有介绍到不会省略任何一步推导故不用担心看不懂。

策略梯度的核心算法思想是参数为\theta的策略\pi_{\theta }接受状态s输出动作概率分布在动作概率分布中采样动作执行动作(形成运动轨迹\tau)得到奖励r跳到下一个状态。在这样的步骤下我们可以使用策略\pi收集一批样本然后使用梯度下降算法学习这些样本不过当策略\pi的参数更新后这些样本不能继续被使用还要重新使用策略\pi与环境互动收集数据。类似下图所示(下图以及本节大部分配图/公式均来自easy RL教程)

 接下来详细阐述。首先我们已经知道了策略函数可以如此表示gif.latex?a%3D%5Cpi%20%28s%7C%5Ctheta%20%29如何评价策略的好坏呢

假设机器人在策略\pi_{\theta }的决策下形成如下的运动轨迹(类似你玩三国争霸时你控制角色在各种不同的游戏画面/场景/状态下作出一系列动作而当完成了系统布置的某个任务时则会得到系统给的奖励如此运动轨迹用 \tau 表示从而\tau表示为一个状态s、动作a、奖励值r不断迁移的过程) 

\tau = (s_{1},a_{1},r_{1},s_{2},a_{2},r_{2},...,s_{t},a_{t},r_{t})

给定智能体或演员的参数\theta我们可以计算某一条轨迹\tau发生的概率为

\begin{aligned} p_{\theta}(\tau) &=p\left(s_{1}\right) p_{\theta}\left(a_{1} | s_{1}\right) p\left(s_{2} | s_{1}, a_{1}\right) p_{\theta}\left(a_{2} | s_{2}\right) p\left(s_{3} | s_{2}, a_{2}\right) \cdots \\ &=p\left(s_{1}\right) \prod_{t=1}^{T} p_{\theta}\left(a_{t} | s_{t}\right) p\left(s_{t+1} | s_{t}, a_{t}\right) \end{aligned}

那策略的评价函数便可以设为(以\theta为参数的策略\pi_{\theta }的条件下产生一系列奖励值且为客观综合起见最终取的是多个策略的平均值即总奖励R_{\theta}数学期望E

R_{\theta}= E[r_{0} + r_{1} + r_{2} +...+r_{t}\pi _{\theta }]

其中\pi _{\theta}可以理解为一个我们所熟知的神经网络

  • 当你对神经网络有所了解的话你一定知道通过梯度下降求解损失函数的极小值忘了的可以复习下首先通过正向传播产生拟合值与标签值做“差”计算产生误差值然后对误差值求和产生损失函数最后对损失函数用梯度下降法求极小值而优化的对象就是神经网络的参数\theta
  • 类比到\pi _{\theta}这个问题上我们现在是正向传播产生动作然后动作在环境中产生奖励值通过奖励值求和产生评价函数气氛都到这了此时是不可以针对评价函数做梯度上升gradient ascent呢毕竟能求极小值便能求极大值正如误差能最小化奖励/得分就能最大化

好手段接下来我们把上面的R_{\theta}改写一下。由于每一个轨迹 \tau 都有一个概率所以我们要计算总奖励便得穷举所有可能的轨迹 \tau然后对所有gif.latex?%5Ctau出现的概率进行加权并求和出总期望值

\bar{R}_{\theta}=\sum_{\tau} R(\tau) p_{\theta}(\tau)=\mathbb{E}_{\tau \sim p_{\theta}(\tau)}[R(\tau)]

上述整个过程如下图所示

通过上文我们已经知道想让奖励越大越好可以使用梯度上升来最大化期望奖励。而要进行梯度上升我们先要计算期望奖励 gif.latex?%5Cbar%7BR%7D_%7B%5Ctheta%7D的梯度

我们对 gif.latex?%5Cbar%7BR%7D_%7B%5Ctheta%7D做梯度运算(其中只有 gif.latex?p_%7B%5Ctheta%7D%28%5Ctau%29与 gif.latex?%5Ctheta 有关。Em忘了什么是梯度的可以通过这个梯度的Wikipedia页面复习下)

gif.latex?%5Cnabla%20%5Cbar%7BR%7D_%7B%5Ctheta%7D%3D%5Csum_%7B%5Ctau%7D%20R%28%5Ctau%29%20%5Cnabla%20p_%7B%5Ctheta%7D%28%5Ctau%29

考虑到\nabla f(x)=f(x)\nabla \log f(x)可得

\frac{\nabla p_{\theta}(\tau)}{p_{\theta}(\tau)}= \nabla \log p_{\theta}(\tau)

从而进一步转化可得gif.latex?%5Cnabla%5Cbar%7BR%7D_%7B%5Ctheta%7D%3D%5Cmathbb%7BE%7D_%7B%5Ctau%20%5Csim%20p_%7B%5Ctheta%7D%28%5Ctau%29%7D%5Cleft%5BR%28%5Ctau%29%20%5Cnabla%20%5Clog%20p_%7B%5Ctheta%7D%28%5Ctau%29%5Cright%5D

EM怎么来的别急具体推导是第一步 先分母分子都乘以一个gif.latex?p_%7B%5Ctheta%7D%28%5Ctau%29第二步 把上面公式代入计算第三步 做个简单转换

\begin{aligned} \nabla \bar{R}_{\theta}&=\sum_{\tau} R(\tau) \nabla p_{\theta}(\tau)\\&=\sum_{\tau} R(\tau) p_{\theta}(\tau) \frac{\nabla p_{\theta}(\tau)}{p_{\theta}(\tau)} \\&= \sum_{\tau} R(\tau) p_{\theta}(\tau) \nabla \log p_{\theta}(\tau) \\ &=\mathbb{E}_{\tau \sim p_{\theta}(\tau)}\left[R(\tau) \nabla \log p_{\theta}(\tau)\right] \end{aligned}

然不巧的是期望值 \mathbb{E}_{\tau \sim p_{\theta}(\tau)}\left[R(\tau) \nabla \log p_{\theta}(\tau)\right]无法计算所以我们只能用采样的方式采样 N 个\tau并计算每一个的值再把每一个的值加起来如此得到梯度即

\begin{aligned} \mathbb{E}_{\tau \sim p_{\theta}(\tau)}\left[R(\tau) \nabla \log p_{\theta}(\tau)\right] &\approx \frac{1}{N} \sum_{n=1}^{N} R\left(\tau^{n}\right) \nabla \log p_{\theta}\left(\tau^{n}\right) \\ &=\frac{1}{N} \sum_{n=1}^{N} \sum_{t=1}^{T_{n}} R\left(\tau^{n}\right) \nabla \log p_{\theta}\left(a_{t}^{n} \mid s_{t}^{n}\right) \end{aligned}

任何必要的中间推导步骤咱不能省所以还是要说明下。即其中\nabla \log p_{\theta}(\tau)的具体计算过程是

\begin{aligned} \nabla \log p_{\theta}(\tau) &= \nabla \left(\log p(s_1)+\sum_{t=1}^{T}\log p_{\theta}(a_t|s_t)+ \sum_{t=1}^{T}\log p(s_{t+1}|s_t,a_t) \right) \\ &= \nabla \log p(s_1)+ \nabla \sum_{t=1}^{T}\log p_{\theta}(a_t|s_t)+ \nabla \sum_{t=1}^{T}\log p(s_{t+1}|s_t,a_t) \\ &=\nabla \sum_{t=1}^{T}\log p_{\theta}(a_t|s_t)\\ &=\sum_{t=1}^{T} \nabla\log p_{\theta}(a_t|s_t) \end{aligned}

完成我们可以直观地理解上面gif.latex?%5Cbar%7BR%7D_%7B%5Ctheta%7D的梯度计算公式

  1. 即在我们采样到的数据里面采样到在某一个状态s_t 要执行某一个动作a_t(s_t,a_t)是在整个轨迹\tau的里面的某一个状态和动作的对
  2. 假设我们在s_t执行a_t最后发现\tau的奖励是正的我们就要增加在 s_t 执行 a_t的概率。反之如果在s_t执行 a_t 会导致 \tau 的奖励变成负的 我们就要减少在  s_t执行 a_t 的概率。这怎么实现呢
  3. 我们用梯度上升来更新参数原来有一个参数\theta把 \theta 加上梯度\nabla \bar{R}_{\theta}当然我们要有一个学习率 \eta学习率也是要调整的可用 Adam、RMSProp 等方法来调整学习率即

\theta \leftarrow \theta+\eta \nabla \bar{R}_{\theta}

 总之至此我们已经得到了gif.latex?%5Cbar%7BR%7D_%7B%5Ctheta%7D的梯度计算的公式

\nabla \bar{R}_{\theta}=\frac{1}{N} \sum_{n=1}^{N} \sum_{t=1}^{T_{n}} R\left(\tau^{n}\right) \nabla \log p_{\theta}\left(a_{t}^{n} | s_{t}^{n}\right)


有一点值得说明的是...为了提高可读性还是举个例子来说明吧。

比如到80/90后上大学时喜欢玩的另一个游戏CF(即cross fire10多年前我在东华理工的时候也经常玩这个另一个是DNF)虽然玩的是同一个主题比如沙漠战场但你每场的发挥是不一样的即便玩到同一个地方(比如A区埋雷的地方)你也可能会控制角色用不同的策略做出不同的动作比如

  • 在第一场游戏里面我们在状态s_1采取动作 a_1在状态s_2采取动作 a_2。且你在同样的状态s_1​下不是每次都会采取动作a_1​的所以我们要记录在状态 s_1^1 采取 a_1^1、在状态 s_2^1 采取 a_2^1等整场游戏结束以后得到的奖励是 R(\tau^1)
  • 在第一场游戏里面在状态s_1^2采取a_1^2​在状态 s_2^2采取 a_2^2我们采样到的就是\tau^2得到的奖励是R(\tau^2)

这时我们就可以把采样到的数据用梯度计算公式把梯度算出来

  1. 也就是把每一个sa的对拿进来计算在某一个状态下采取某一个动作的对数概率\log p_{\theta}\left(a_{t}^{n} | s_{t}^{n}\right)对这个概率取梯度\nabla \log p_{\theta}\left(a_{t}^{n} | s_{t}^{n}\right)
  2. 然后在梯度前面乘一个权重R\left(\tau^{n}\right)权重就是这场游戏的奖励
  3. 计算出梯度后就可以通过\theta \leftarrow \theta+\eta \nabla \bar{R}_{\theta}更新模型了

2.3.2 重要性采样解决策略梯度采样效率低下

策略梯度有个问题在于 gif.latex?%5Cmathbb%7BE%7D_%7B%5Ctau%20%5Csim%20p_%7B%5Ctheta%7D%28%5Ctau%29%7D是对策略  gif.latex?%5Cpi_%7B%5Ctheta%7D采样的轨迹  gif.latex?%5Ctau求期望。一旦更新了参数从 gif.latex?%5Ctheta 变成  gif.latex?%5Ctheta%27在对应状态s下采取动作的概率  gif.latex?p_%5Ctheta%28%5Ctau%29就不对了之前采样的数据也不能用了。
换言之策略梯度是一个会花很多时间来采样数据的算法其大多数时间都在采样数据。智能体与环境交互以后接下来就要更新参数我们只能更新参数一次然后就要重新采样数据 才能再次更新参数。

0dbb490df24a8ddc53d81df6b09c9c76.png

这显然是非常花时间的怎么解决这个问题呢

首先我们先来明确两个概念

  • 如果要学习的智能体和与环境交互的智能体是相同的我们称之为同策略
  • 如果要学习的智能体和与环境交互的智能体不是相同的我们称之为异策略

回到策略梯度这个采样到的数据只能使用一次的问题是否可以把同策略模式转变成异策略模式呢

  1. 想要从同策略变成异策略这样就可以用另外一个策略gif.latex?%5Cpi_%7B%5Ctheta%27%7D、另外一个演员gif.latex?%5Ctheta%27与环境交互gif.latex?%5Ctheta%27被固定了用gif.latex?%5Ctheta%27采样到的数据去训练gif.latex?%5Ctheta
  2. 假设我们可以用 gif.latex?%5Ctheta%27采样到的数据去训练gif.latex?%5Ctheta我们可以多次使用gif.latex?%5Ctheta%27采样到的数据可以多次执行梯度上升gradient ascent可以多次更新参数 都只需要用gif.latex?%5Ctheta%27采样到的同一批数据

这个过程具体的做法就叫重要性采样即通过使用另外一种分布来逼近所求分布的一种方法。

2.3.3 解决重要性采样两个分布差异大的问题加上重要性权重

在上节为解决梯度计算采样效率低下的问题我们使用了重要性采样但重要性采样还有另一个问题。

具体什么问题呢为更好的说明这个问题我们先通过一个例子回顾下重要性采样。

假设有一个函数f(x)x需要从分布p中采样我们应该如何怎么计算𝑓(𝑥)的期望值呢

如果分布p不能做积分那么只能从分布p尽可能多采样更多的x^{i}然后全都代入到f(x)取它的平均值就可以得到近似𝑓(𝑥)的期望值

\mathbb{E}_{x \sim p}[f(x)] \approx \frac{1}{N} \sum_{i=1}^N f(x^i)

恩那万一不能在分布p中采样数据而只能从另外一个分布q中去采样数据呢q可以是任何分布而我们想要在q中采样的的话就需要做些变换。

首先期望值\mathbb{E}_{x \sim p}[f(x)]的另一种写法是\int f(x) p(x) \mathrm{d}x对其进行变换如下式所示

\int f(x) p(x) \mathrm{d}x=\int f(x) \frac{p(x)}{q(x)} q(x) \mathrm{d}x=\mathbb{E}_{x \sim q}[f(x){\frac{p(x)}{q(x)}}]

整理下可得左边是分布p右边是分布q

\mathbb{E}_{x \sim p}[f(x)]=\mathbb{E}_{x \sim q}\left[f(x) \frac{p(x)}{q(x)}\right]

如此我们便就可以从q里面采样 x再计算f(x) \frac{p(x)}{q(x)}再取期望值。所以就算我们不能从p里面采样数据但只要能从 q里面采样数据就可以计算从 p 采样 x 然后代入f 以后的期望值。 

即虽然我们可以把 p换成任何的 q。但是在实现上p和 q的差距不能太大。差距太大会出问题。

比如虽然上述公式成立但如果不是计算期望值而是计算方差\operatorname{Var}_{x \sim p}[f(x)]和 \operatorname{Var}_{x \sim q}\left[f(x) \frac{p(x)}{q(x)}\right]是不一样的。因为两个随机变量的平均值相同并不代表它们的方差相同。

此话怎讲以下是推导过程

我们可以将 f(x)、分别 f(x) \frac{p(x)}{q(x)}代入方差的公式\operatorname{Var}[X]=E\left[X^{2}\right]-(E[X])^{2}则分别可得

\operatorname{Var}_{x \sim p}[f(x)]=\mathbb{E}_{x \sim p}\left[f(x)^{2}\right]-\left(\mathbb{E}_{x \sim p}[f(x)]\right)^{2}

\begin{aligned} \operatorname{Var}_{x \sim q}\left[f(x) \frac{p(x)}{q(x)}\right] &=\mathbb{E}_{x \sim q}\left[\left(f(x) \frac{p(x)}{q(x)}\right)^{2}\right]-\left(\mathbb{E}_{x \sim q}\left[f(x) \frac{p(x)}{q(x)}\right]\right)^{2} \\ &=\mathbb{E}_{x \sim p}\left[f(x)^{2} \frac{p(x)}{q(x)}\right]-\left(\mathbb{E}_{x \sim p}[f(x)]\right)^{2} \end{aligned}

两项对比可以很明显的看出后者的第一项多乘了\frac{p(x)}{q(x)}如果\frac{p(x)}{q(x)}差距很大f(x)\frac{p(x)}{q(x)}的方差就会很大。

所以结论就是如果我们只要对分布p采样足够多次对分布q采样足够多次得到的期望值会是一样的。但是如果我们采样的次数不够多会因为它们的方差差距可能是很大的所以就可能得到差别非常大的结果。

那怎么办呢需要加一个重要性权重以修正。

为备忘我把2.3.1节得出的gif.latex?%5Cbar%7BR%7D_%7B%5Ctheta%7D梯度计算的公式再贴一下

\begin{aligned} \mathbb{E}_{\tau \sim p_{\theta}(\tau)}\left[R(\tau) \nabla \log p_{\theta}(\tau)\right] &\approx \frac{1}{N} \sum_{n=1}^{N} R\left(\tau^{n}\right) \nabla \log p_{\theta}\left(\tau^{n}\right) \\ &=\frac{1}{N} \sum_{n=1}^{N} \sum_{t=1}^{T_{n}} R\left(\tau^{n}\right) \nabla \log p_{\theta}\left(a_{t}^{n} \mid s_{t}^{n}\right) \end{aligned}

基于重要性采样的原则我们用另外一个策略\pi _{\theta^{'}}它就是另外一个演员与环境做互动采样出轨迹\theta^{'}来间接计算R(\tau) \nabla \log p_{\theta}(\tau)

我们通过\theta^{'}去跟环境做互动采样数据来训练\theta。因为不能从p做采样所以把pq最后R(\tau) \nabla \log p_{\theta}(\tau)的基础上补上一个重要性权重\frac{p_{\theta}(\tau)}{p_{\theta^{\prime}}(\tau)}。这个重要性权重针对某一个轨迹\tau\theta算出来的概率除以这个轨迹\tau\theta^{'}算出来的概率

\nabla \bar{R}_{\theta}=\mathbb{E}_{\tau \sim p_{\theta^{\prime}(\tau)}}\left[\frac{p_{\theta}(\tau)}{p_{\theta^{\prime}}(\tau)} R(\tau) \nabla \log p_{\theta}(\tau)\right]

实际在做策略梯度的时候并不是给整个轨迹\tau都一样的分数而是每一个状态-动作的对会分开来计算。所以实际上更新梯度的时候如下式所示 我们用演员\theta去采样出s_{t}a_{t}采样出状态跟动作的对(s_{t},a_{t})并计算这个状态跟动作对的优势A^{\theta }(s_{t},a_{t}) 

\mathbb{E}_{\left(s_{t}, a_{t}\right) \sim \pi_{\theta}}\left[A^{\theta}\left(s_{t}, a_{t}\right) \nabla \log p_{\theta}\left(a_{t}^{n} | s_{t}^{n}\right)\right]

其中A^{\theta}(s_t,a_t)有一个上标\theta\theta代表A^{\theta}(s_t,a_t)是演员\theta与环境交互的时候计算出来的。但是实际上从 \theta 换到 \theta' 的时候A^{\theta}(s_t,a_t)应该改成A^{\theta'}(s_t,a_t)为什么呢因为A(s_t,a_t)这一项是想要估测在某一个状态采取某一个动作。


我们怎么估计A(s_t,a_t)

在之前梯度计算的公式基础上

\nabla \bar{R}_{\theta}=\frac{1}{N} \sum_{n=1}^{N} \sum_{t=1}^{T_{n}} R\left(\tau^{n}\right) \nabla \log p_{\theta}\left(a_{t}^{n} | s_{t}^{n}\right)

得加一个基准线b

\nabla \bar{R}_{\theta} \approx \frac{1}{N} \sum_{n=1}^{N} \sum_{t=1}^{T_{n}}\left(R\left(\tau^{n}\right)-b\right) \nabla \log p_{\theta}\left(a_{t}^{n} \mid s_{t}^{n}\right)

我们在状态s_t采取动作a_t接下来会得到的奖励的总和R(\tau ^n)再减去基线b就是A(s_t,a_t)。之前是 \theta与环境交互所以我们观察到的是 \theta 可以得到的奖励。但现在是\theta'与环境交互所以我们得到的这个优势是根据 \theta' 所估计出来的优势。

但我们现在先不要管那么多就假设A^{\theta}(s_t,a_t)和 A^{\theta'}(s_t,a_t)可能是差不多的我个人理解这里应该是一个隐患点所以TRPO/PPO处理这个问题的时候在重要性权重的基础上还加了个KL散度约束。

A^{\theta }(s_{t},a_{t})就是累积奖励减掉偏置项这一项是估测出来的。它要估测的是在状态s_{t}采取动作a_{t}是好的还是不好的即如果A^{\theta }(s_{t},a_{t})是正的就要增加概率如果是负的就要减少概率。   

然后用加个重要性权重修下即把s_{t}a_{t}\theta采样出来的概率除掉 s_{t}a_{t}\theta^{'}采样出来的概率公式如下

\mathbb{E}_{\left(s_{t}, a_{t}\right) \sim \pi_{\theta^{\prime}}}\left[\frac{p_{\theta}\left(s_{t}, a_{t}\right)}{p_{\theta^{\prime}}\left(s_{t}, a_{t}\right)} A^{\theta}\left(s_{t}, a_{t}\right) \nabla \log p_{\theta}\left(a_{t}^{n} | s_{t}^{n}\right)\right]

接下来我们可以拆解p_{\theta}(s_{t}, a_{t})p_{\theta'}\left(s_{t}, a_{t}\right)

\begin{aligned} p_{\theta}\left(s_{t}, a_{t}\right)&=p_{\theta}\left(a_{t}|s_{t}\right) p_{\theta}(s_t) \\ p_{\theta'}\left(s_{t}, a_{t}\right)&=p_{\theta'}\left(a_{t}|s_{t}\right) p_{\theta'}(s_t) \end{aligned}

于是可得公式

\mathbb{E}_{\left(s_{t}, a_{t}\right) \sim \pi_{\theta^{\prime}}}\left[\frac{p_{\theta}\left(a_{t} | s_{t}\right)}{p_{\theta^{\prime}}\left(a_{t} | s_{t}\right)} \frac{p_{\theta}\left(s_{t}\right)}{p_{\theta^{\prime}}\left(s_{t}\right)} A^{\theta^{\prime}}\left(s_{t}, a_{t}\right) \nabla \log p_{\theta}\left(a_{t}^{n} | s_{t}^{n}\right)\right]

这里需要做一件事情假设模型是\theta的时候我们看到s_{t}的概率跟模型是\theta^{'}的时候看到s_{t}的概率是差不多的即p_{\theta}(s_t)=p_{\theta'}(s_t)

为什么可以这样假设呢一种直观的解释就是p_{\theta}(s_t)很难算这一项有一个参数\theta需要拿\theta去跟环境做互动算s_{t}出现的概率。 尤其是如果输入是图片的话同样的s_{t}根本就不会出现第二次。我们根本没有办法估这一项所以就直接无视这个问题。


但是p_{\theta}(a_t|s_t)是很好算我们有\theta这个参数它就是个网络。我们就把s_{t}带进去s_{t}就是游戏画面。 我们有个策略的网络输入状态s_{t}它会输出每一个a_{t}的概率。所以我们只要知道\theta\theta'的参数就可以算\frac{p_{\theta}\left(a_{t} | s_{t}\right)}{p_{\theta^{\prime}}\left(a_{t} | s_{t}\right)}。 

所以实际上在更新参数的时候我们就是按照下式来更新参数

\mathbb{E}_{\left(s_{t}, a_{t}\right) \sim \pi_{\theta^{\prime}}}\left[\frac{p_{\theta}\left(a_{t} | s_{t}\right)}{p_{\theta^{\prime}}\left(a_{t} | s_{t}\right)} A^{\theta^{\prime}}\left(s_{t}, a_{t}\right) \nabla \log p_{\theta}\left(a_{t}^{n} | s_{t}^{n}\right)\right]

所以实际上我们可以从梯度\nabla f(x)=f(x) \nabla \log f(x)来反推目标函数当使用重要性采样的时候要去优化的目标函数如下式所示我们把它记J^{\theta^{\prime}}(\theta)

J^{\theta^{\prime}}(\theta)=\mathbb{E}_{\left(s_{t}, a_{t}\right) \sim \pi_{\theta^{\prime}}}\left[\frac{p_{\theta}\left(a_{t} | s_{t}\right)}{p_{\theta^{\prime}}\left(a_{t} | s_{t}\right)} A^{\theta^{\prime}}\left(s_{t}, a_{t}\right)\right]

括号里面的\theta代表我们需要去优化的参数然后用\theta'去做示范采样数据采样出s_{t}a_{t}以后要去计算s_{t}a_{t}的优势A^{\theta^{\prime}}\left(s_{t}, a_{t}\right)再乘上重要性权重\frac{p_{\theta}\left(a_{t} | s_{t}\right)}{p_{\theta^{\prime}}\left(a_{t} | s_{t}\right)}

终于大功告成值得一提的是这个修正的方法在下文要介绍的TRPO、PPO算法中都用到了。

2.3.4 基于信任区域的TRPO解决步长难以确定且增加KL散度约束

采样效率低效的问题通过重要性采样解决了但策略梯度还有一个问题即梯度步长难以确定。

具体而言当策略网络是深度模型时沿着策略梯度更新参数很有可能由于步长太长策略突然显著变差进而影响训练效果。

这是2.3.1节我们已经得到的梯度计算和梯度更新公式

\nabla \bar{R}_{\theta}=\frac{1}{N} \sum_{n=1}^{N} \sum_{t=1}^{T_{n}} R\left(\tau^{n}\right) \nabla \log p_{\theta}\left(a_{t}^{n} | s_{t}^{n}\right)

\theta \leftarrow \theta+\eta \nabla \bar{R}_{\theta}

针对这个问题我们考虑在更新时找到一块信任区域(trust region)在这个区域上更新策略时能够得到某种策略性能的安全性保证这就是2015年被John Schulman等人提出的信任区域策略优化(trust region policyopimization, TRPO) 算法的主要思想。

举个例子比如爬两面都是悬崖的山。你首先选择最陡峭的方向然后向前移动一个步长。如果步长太小则需要很长时间才能到达峰值。但如果它太大我们就会掉下悬崖。

f967e40c3b6346b6a74e1909e0eb08c5.png

那怎么办呢我们会用目光选择一片信任区域从而尽量远离悬崖边在信任区域中我们首先确定要探索的最大步长下面的黄色圆圈然后我们在信任区域内找到最佳点并从那里继续搜索。

d7fff6ebbf9a42d3ba9c04e1c924d476.png

信任域中的最大步长是多少在信赖域方法中我们从初始猜测开始可选地然后动态地重新调整区域大小。例如如果新政策和当前政策的差异越来越大我们可以缩小信赖区域。

所以TRPO就是考虑到连续动作空间无法每一个动作都搜索一遍因此大部分情况下只能靠猜。如果要猜就最好在信任域内部去猜。而TRPO将每一次对策略的更新都限制了信任域内从而极大地增强了训练的稳定性。

至此我们分别通过重要性采样、基于信任区域的TRPO解决了PG算法的采样效率低下、步长难以确定的问题。

在2.3.3节我们得知重要性采样有一个问题如果 gif.latex?p_%7B%5Ctheta%7D%5Cleft%28a_%7Bt%7D%20%7C%20s_%7Bt%7D%5Cright%29与 gif.latex?p_%7B%5Ctheta%27%7D%5Cleft%28a_%7Bt%7D%20%7C%20s_%7Bt%7D%5Cright%29相差太多即这两个分布相差太多重要性采样的结果就会不好。怎么避免它们相差太多呢

在2.3.3节我们通过一个重要性权重修正但这还不够还需要再加一定的限制和约束。

所以TRPO在2.3.3节得到的目标函数基础上(下图第一个公式)增加了一个KL散度约束(如下图第二个公式)

J^{\theta^{\prime}}(\theta)=\mathbb{E}_{\left(s_{t}, a_{t}\right) \sim \pi_{\theta^{\prime}}}\left[\frac{p_{\theta}\left(a_{t} | s_{t}\right)}{p_{\theta^{\prime}}\left(a_{t} | s_{t}\right)} A^{\theta^{\prime}}\left(s_{t}, a_{t}\right)\right]

\begin{aligned} J_{\mathrm{TRPO}}^{\theta^{\prime}}(\theta)=\mathbb{E}_{\left(s_{t}, a_{t}\right) \sim \pi_{\theta^{\prime}}}\left[\frac{p_{\theta}\left(a_{t} | s_{t}\right)}{p_{\theta^{\prime}}\left(a_{t} | s_{t}\right)} A^{\theta^{\prime}}\left(s_{t}, a_{t}\right)\right],\mathrm{KL}\left(\theta, \theta^{\prime}\right)<\delta \end{aligned}

不过TRPO把 KL 散度约束当作一个额外的约束没有放在目标里面导致TRPO很难计算总之因为信任域的计算量太大了John Schulman等人于2017年又推出了TRPO的改进算法PPO。

2.4 近端策略优化PPO解决TRPO的计算量大的问题

2.4.1 什么是近端策略优化PPO

PPO算法是针对TRPO计算量的大的问题提出来了和TRPO一样也用上了KL散度约束但PPO的改进在于把KL散度约束直接放在了目标函数里。

  • PPO 需要优化目标函数gif.latex?J%5E%7B%5Ctheta%5E%7B%5Cprime%7D%7D%28%5Ctheta%29让其最大化
    但是这个目标函数又牵涉到重要性采样。在做重要性采样的时候gif.latex?p_%7B%5Ctheta%7D%5Cleft%28a_%7Bt%7D%20%7C%20s_%7Bt%7D%5Cright%29不能与gif.latex?p_%7B%5Ctheta%27%7D%5Cleft%28a_%7Bt%7D%20%7C%20s_%7Bt%7D%5Cright%29相差太多。做示范的模型不能与真正的模型相差太多相差太多重要性采样的结果就会不好
  • 所以在训练的时候应多加一个约束constrainJθ′​(θ)=Jθ′(θ)−βKL(θ,θ′)。这个约束是 gif.latex?%5Ctheta与 gif.latex?%5Ctheta%27输出的动作的 KL 散度KL divergence这一项用于衡量 gif.latex?%5Ctheta 与 gif.latex?%5Ctheta%27 的相似程度。我们希望在训练的过程中学习出的 gif.latex?%5Ctheta 与 gif.latex?%5Ctheta%27 越相似越好。因为如果 gif.latex?%5Ctheta 与 gif.latex?%5Ctheta%27 不相似最后的结果就会不好。

所以在 PPO 里面有两项一项是优化本来要优化的gif.latex?J%5E%7B%5Ctheta%5E%7B%5Cprime%7D%7D%28%5Ctheta%29另一项是一个约束。这个约束就好像正则化regularization的项term 一样它所做的就是希望最后学习出的  gif.latex?%5Ctheta 与 gif.latex?%5Ctheta%27 相差不大如下所示

gif.latex?%5Cbegin%7Baligned%7D%20%26J_%7B%5Cmathrm%7BPPO%7D%7D%5E%7B%5Ctheta%5E%7B%5Cprime%7D%7D%28%5Ctheta%29%3DJ%5E%7B%5Ctheta%5E%7B%5Cprime%7D%7D%28%5Ctheta%29-%5Cbeta%20%5Cmathrm%7BKL%7D%5Cleft%28%5Ctheta%2C%20%5Ctheta%5E%7B%5Cprime%7D%5Cright%29%20%5C%5C%20%26J%5E%7B%5Ctheta%5E%7B%5Cprime%7D%7D%28%5Ctheta%29%3D%5Cmathbb%7BE%7D_%7B%5Cleft%28s_%7Bt%7D%2C%20a_%7Bt%7D%5Cright%29%20%5Csim%20%5Cpi_%7B%5Ctheta%5E%7B%5Cprime%7D%7D%7D%5Cleft%5B%5Cfrac%7Bp_%7B%5Ctheta%7D%5Cleft%28a_%7Bt%7D%20%5Cmid%20s_%7Bt%7D%5Cright%29%7D%7Bp_%7B%5Ctheta%5E%7B%5Cprime%7D%7D%5Cleft%28a_%7Bt%7D%20%5Cmid%20s_%7Bt%7D%5Cright%29%7D%20A%5E%7B%5Ctheta%5E%7B%5Cprime%7D%7D%5Cleft%28s_%7Bt%7D%2C%20a_%7Bt%7D%5Cright%29%5Cright%5D%20%5Cend%7Baligned%7D

当然你也也可以把上述那两个式子合二为一为(可以更直观的看出PPO把约束作为惩罚项放在目标函数中从而可以用梯度上升的方法去最大化它。

gif.latex?%5Cbegin%7Baligned%7D%20%26J_%7B%5Cmathrm%7BPPO%7D%7D%5E%7B%5Ctheta%5E%7B%5Cprime%7D%7D%28%5Ctheta%29%3D%5Cmathbb%7BE%7D_%7B%5Cleft%28s_%7Bt%7D%2C%20a_%7Bt%7D%5Cright%29%20%5Csim%20%5Cpi_%7B%5Ctheta%5E%7B%5Cprime%7D%7D%7D%5Cleft%5B%5Cfrac%7Bp_%7B%5Ctheta%7D%5Cleft%28a_%7Bt%7D%20%5Cmid%20s_%7Bt%7D%5Cright%29%7D%7Bp_%7B%5Ctheta%5E%7B%5Cprime%7D%7D%5Cleft%28a_%7Bt%7D%20%5Cmid%20s_%7Bt%7D%5Cright%29%7D%20A%5E%7B%5Ctheta%5E%7B%5Cprime%7D%7D%5Cleft%28s_%7Bt%7D%2C%20a_%7Bt%7D%5Cright%29%5Cright%5D%20%5Cend%7Baligned%7D%20-%5Cbeta%20%5Cmathrm%7BKL%7D%5Cleft%28%5Ctheta%2C%20%5Ctheta%5E%7B%5Cprime%7D%5Cright%29

2.4.2 PPO算法的两个主要变种PPO-penalty与PPO-clip

PPO 算法有两个主要的变种近端策略优化惩罚PPO-penalty近端策略优化裁剪PPO-clip

我们先来看下近端策略优化惩罚PPO-penalty

  1. 它先初始化一个策略的参数gif.latex?%5Ctheta%5E0。在每一个迭代里面我们用前一个训练的迭代得到的actor的参数 gif.latex?%5Ctheta%5Ek与环境交互采样到大量状态-动作对。
  2. 根据 gif.latex?%5Ctheta%5Ek 交互的结果我们估测gif.latex?A%5E%7B%5Ctheta%5E%7Bk%7D%7D%5Cleft%28s_%7Bt%7D%2C%20a_%7Bt%7D%5Cright%29
  3. 最后我们使用 PPO 的优化公式gif.latex?J_%7B%5Cmathrm%7BPPO%7D%7D%5E%7B%5Ctheta%5E%7Bk%7D%7D%28%5Ctheta%29%3DJ%5E%7B%5Ctheta%5E%7Bk%7D%7D%28%5Ctheta%29-%5Cbeta%20%5Cmathrm%7BKL%7D%5Cleft%28%5Ctheta%2C%20%5Ctheta%5E%7Bk%7D%5Cright%29

上文有一个细节并没有讲到即gif.latex?%5Cbeta是怎么取值的呢关于gif.latex?%5Cbeta的设置有一个动态调整gif.latex?%5Cbeta的方法具体而言

  • 我们先设一个可以接受的 KL 散度的最大值。假设优化完gif.latex?J_%7B%5Cmathrm%7BPPO%7D%7D%5E%7B%5Ctheta%5E%7Bk%7D%7D%28%5Ctheta%29%3DJ%5E%7B%5Ctheta%5E%7Bk%7D%7D%28%5Ctheta%29-%5Cbeta%20%5Cmathrm%7BKL%7D%5Cleft%28%5Ctheta%2C%20%5Ctheta%5E%7Bk%7D%5Cright%29以后KL 散度的值太大这就代表后面惩罚的项gif.latex?%5Cbeta%5Cmathrm%7BKL%7D%5Cleft%28%5Ctheta%2C%20%5Ctheta%5E%7Bk%7D%5Cright%29 没有发挥作用我们就把gif.latex?%5Cbeta增大
  • 我们设一个 KL 散度的最小值。如果优化完式gif.latex?J_%7B%5Cmathrm%7BPPO%7D%7D%5E%7B%5Ctheta%5E%7Bk%7D%7D%28%5Ctheta%29%3DJ%5E%7B%5Ctheta%5E%7Bk%7D%7D%28%5Ctheta%29-%5Cbeta%20%5Cmathrm%7BKL%7D%5Cleft%28%5Ctheta%2C%20%5Ctheta%5E%7Bk%7D%5Cright%29以后KL 散度比最小值还要小就代表后面这一项的效果太强了我们怕他只优化后一项使gif.latex?%5Ctheta与 gif.latex?%5Ctheta%5Ek 一样这不是我们想要的所以我们要减小gif.latex?%5Cbeta

综上gif.latex?%5Cbeta是可以动态调整的因此我们称之为自适应KL惩罚adaptive KL penalty。最后总结一下自适应KL惩罚 

  • 如果 gif.latex?%5Cmathrm%7BKL%7D%28%5Ctheta%2C%5Ctheta%5Ek%29%3E%5Cmathrm%7BKL%7D_%7B%5Cmax%7D增大 gif.latex?%5Cbeta
  • 如果 gif.latex?%5Cmathrm%7BKL%7D%28%5Ctheta%2C%5Ctheta%5Ek%29%3C%5Cmathrm%7BKL%7D_%7B%5Cmin%7D减小 gif.latex?%5Cbeta

近端策略优化惩罚可表示为

gif.latex?%5Cbegin%7Baligned%7D%20%26J_%7B%5Ctext%7BPPO%7D%7D%5E%7B%5Ctheta%5E%7Bk%7D%7D%28%5Ctheta%29%3DJ%5E%7B%5Ctheta%5E%7Bk%7D%7D%28%5Ctheta%29-%5Cbeta%20%5Ctext%7BKL%7D%5Cleft%28%5Ctheta%2C%20%5Ctheta%5E%7Bk%7D%5Cright%29%20%5C%5C%20%26J%5E%7B%5Ctheta%5E%7Bk%7D%7D%28%5Ctheta%29%20%5Capprox%20%5Csum_%7B%5Cleft%28s_%7Bt%7D%2C%20a_%7Bt%7D%5Cright%29%7D%20%5Cfrac%7Bp_%7B%5Ctheta%7D%5Cleft%28a_%7Bt%7D%20%5Cmid%20s_%7Bt%7D%5Cright%29%7D%7Bp_%7B%5Ctheta%5E%7Bk%7D%7D%5Cleft%28a_%7Bt%7D%20%5Cmid%20s_%7Bt%7D%5Cright%29%7D%20A%5E%7B%5Ctheta%5E%7Bk%7D%7D%5Cleft%28s_%7Bt%7D%2C%20a_%7Bt%7D%5Cright%29%20%5Cend%7Baligned%7D

最后如果我们觉得计算 KL 散度很复杂那么还有一个 PPO2算法PPO2 即近端策略优化裁剪。近端策略优化裁剪的目标函数里面没有 KL 散度其要最大化的目标函数为

gif.latex?%5Cbegin%7Baligned%7D%20J_%7B%5Cmathrm%7BPPO2%7D%7D%5E%7B%5Ctheta%5E%7Bk%7D%7D%28%5Ctheta%29%20%5Capprox%20%5Csum_%7B%5Cleft%28s_%7Bt%7D%2C%20a_%7Bt%7D%5Cright%29%7D%20%5Cmin%20%26%5Cleft%28%5Cfrac%7Bp_%7B%5Ctheta%7D%5Cleft%28a_%7Bt%7D%20%7C%20s_%7Bt%7D%5Cright%29%7D%7Bp_%7B%5Ctheta%5E%7Bk%7D%7D%5Cleft%28a_%7Bt%7D%20%7C%20s_%7Bt%7D%5Cright%29%7D%20A%5E%7B%5Ctheta%5E%7Bk%7D%7D%5Cleft%28s_%7Bt%7D%2C%20a_%7Bt%7D%5Cright%29%2C%5Cright.%5C%5C%20%26%5Cleft.%5Coperatorname%7Bclip%7D%5Cleft%28%5Cfrac%7Bp_%7B%5Ctheta%7D%5Cleft%28a_%7Bt%7D%20%7C%20s_%7Bt%7D%5Cright%29%7D%7Bp_%7B%5Ctheta%5E%7Bk%7D%7D%5Cleft%28a_%7Bt%7D%20%7C%20s_%7Bt%7D%5Cright%29%7D%2C%201-%5Cvarepsilon%2C%201&plus;%5Cvarepsilon%5Cright%29%20A%5E%7B%5Ctheta%5E%7Bk%7D%7D%5Cleft%28s_%7Bt%7D%2C%20a_%7Bt%7D%5Cright%29%5Cright%29%20%5Cend%7Baligned%7D

如果用一句话简要阐述下其核心含义就是(好好体会下这句话^_^)如果新策略和旧策略之间的概率比落在范围1-ε和1+ε之外目标函数将被剪裁使得最终目标值最小不小于1-ε最大不大于1+ε

1798baf5dba54e21a19508e82d407a8a.png

更多细节可以看下文末的相关参考文献。

2.5 从强化学习到逆强化学习聊天对话等场景中不好定义reward

强化学习理论上可以不需要大量标注数据然而实际上它所需求的reward存在一些缺陷这导致强化学习策略很难推广

  1. reward的制定非常困难比如说游戏AI中可能要制定成百上千条游戏规则这并不比标注大量数据来得容易

  2. 部分场景下reward的效果不好比如说自动驾驶的多步决策sequential decision场景中学习器很难频繁地获得reward容易累计误差导致一些严重的事故

    d031d2873feecc4c67cf7d45ece4386e.png

  3. 再比如聊天机器人方面我们不好定义什么是好的对话、什么是不好的对话但我们可以手机很多人类的对话当做范例如此模仿学习Imitation Learning应运而生。

模仿学习的思路是不让模型在人类制定的规则下自己学习而是让模型模仿人类的行为。而逆强化学习就是模仿学习的其中一种何谓逆强化学习呢

  • 原来的强化学习里有Environment和Reward Model但逆强化学习刚好是相反的它没有奖励函数只有一些人类/专家的示范当然它还是有环境的
  • 换言之逆强化学习将强化学习的Environment替换成一个Reward Model而这个RM是通过人类标注数据去训练得到
  • 进一步有了环境和人类标注数据以后可以反推出奖励函数

8f9ca3e18f1c0e8f4e3c37c4f6d217a6.png

总之强化学习是由奖励函数推出什么样的动作/策略是最好的逆强化学习则反过来

  1. 我们有人类标注数据我们相信它是不错的我就反推人类因为什么样的奖励函数才会采取这些行为
  2. 有了奖励函数以后接下来我们就可以使用一般的强化学习的方法去找出最优策略/动作

所以逆强化学习是先找出奖励函数找出奖励函数以后再用强化学习找出最优策略/动作。

第三部分 instructGPT/ChatGPT的训练三阶段到多轮对话应用

3.1 InstructGPT训练三阶段

3.1.1 ChatGPT的前身之InstructGPT基于RLHF手段微调的GPT

根据instructGPT的原始论文可知InstructGPT的训练分为三个阶段总体上结合了监督学习和强化学习先是监督学习让GPT3有一个大致的微调方向然后用RL中的PPO算法来更新微调过的GPT3的参数

b64b91a3a14b46e7970550bbb3363092.png

  1. 阶段1利用人类的标注数据demonstration data去对GPT3进行有监督训练
    首先OpenAI是先设计了一个prompt dataset里面有大量的提示样本给出了各种各样的任务描述
    其次找了一个标注团队对这个prompt dataset进行标注(本质就是人工回答问题)
    最后用这个标注过的数据集微调GPT3这个微调好的GPT3我们称之为SFT模型监督微调全称Supervised fine-tuning简称SFT具备了最基本的预测能力

    BTW相信你还记得上文1.3节所说的GPT3通过prompt learning在小样本下令人惊艳的表现另再说句题外话咱们训练的最终目标就是通过不断缩小instructGPT与人类预测之间的差距从而不断提高instructGPT的预测能力

  2. 阶段2训练奖励模型RM
    把微调好的SFT模型去回答prompt dataset某个问题然后通过收集4个不同的SFT输出而获取4个回答接着人工对这4个回答的好坏进行标注且排序排序的结果用来训练一个奖励模型RM具体做法就是学习排序结果从而理解人类的偏好

  3. 阶段3通过训练好RM模型预测结果且通过PPO算法优化SFT模型策略
    具体做法是再次让SFT模型去回答prompt dataset某个问题然后此时不再让人工评估好坏而是让阶段2训练好的奖励模型去给SFT模型的预测结果进行打分排序
    就这样一个初始的语言模型SFT模型来生成文本以及一个奖励模型RM来判断模型生成的文本是否优质迎合人类偏好然后不断生成、不断评估交替进行

此外可能有读者疑问InstructGPT为什么要做这样的改进或者说它的novelty是什么

  • 事实上这个改进思路是为了尽可能地对齐AlignmentGPT的输出与对用户友好的语言逻辑即微调出一个用户友好型GPT。以往的GPT训练都是基于大量无标注的语料这些语料通常收集自互联网。我们都知道大量“行话”、“黑话”存在于互联网中这样训练出来的语言模型它可能会有虚假的、恶意的或者有负面情绪等问题的输出
  • 因此一个直接的思路就是通过人工干预微调GPT使其输出对用户友好避免乱说话

所以对InstructGPT的简单理解可以是基于人类反馈的强化学习RLHF手段微调的GPT。

值得一提的是这个训练过程是不和我们逆向强化学习很熟

为什么呢因为强化学习是利用奖励学习策略而所谓的逆向强化学习一般是从策略中反推奖励函数对应到这个instructGPT的训练过程中它通过人类专家的行为逆向强化学习出一个奖励函数最后再利用这个奖励函数进行强化学习训练这不是很眼熟


这里先提一嘴下文会再具体阐述

3.1.2 ChatGPT与InstructGPT的差别基于GPT3还是GPT3.5微调

而通过OpenAI公布的ChatGPT训练图可知ChatGPT的训练流程与InstructGPT是一致的差异只在于

  • InstructGPT是在GPT-3上做Fine-Tune
  • ChatGPT是在GPT-3.5上做Fine-TuneGPT3.5是OpenAI在2021年Q4训练的InstructGPT模型在自动编写代码方面有较强的能力

ed6f8d3ff5d744939af358649e61721d.png

接下来我们分别具体阐述上面的阶段2、阶段3。

自AlphaGo使得强化学习猛然进入大众视野以来大部分对于强化学习的理论研究都将游戏作为主要实验平台这一点不无道理强化学习理论上的推导看似逻辑通顺但其最大的弱点在于基于人工评判的奖励 Reward 的获得让实验人员守在电脑前对模型吐出来的结果不停地打分看来是不现实的游戏系统恰恰能会给出正确客观的打分输/赢 或 游戏Score。


基于RL的对话生成同样会面对这个问题研究人员采用了类似AlphaGo的实现方式AI棋手对弈——同时运行两个机器人让它们自己互相对话同时使用预训练pre-trained好的“打分器”给出每组对话的奖励得分 R(ai,xi) 关于这个预训练的“打分器” R 可以根据实际的应用和需求自己DIY是否通顺是否辞不达意是否总说重复的废话

3.1.3 instructGPT训练阶段2如何对多个输出排序及如何训练RM模型

可能又有读者有疑问了即instructGPT中人类对模型的多个输出做个排序为什么就能够提供监督信号或者说在训练RM时如何怎么做到loss的梯度回传

训练RM的核心是由人类对SFT生成的多个输出基于同一个输入进行排序再用来训练RM。按照模仿学习的定义直观上的理解可以是RM在模仿人类对语句的排序思路或者按照参考文献即Google DeepMind和OpenAI团队2017年的论文《Deep reinforcement learning from human preferences》的说法是模仿人类的偏好Preference。

那么到底是如何模仿的呢或者说如何实现梯度回传

这里我们代入一个场景如下图

c3296f55f2d685426b8f924a2f03b348.png

  1. SFT生成了ABCD四个语句然后人类对照着Prompt输入来做出合适的排序选择如D>C>A=B
  2. 这里的排序实质是人类分别给4个语句打分比如说D打了7分C打了6分A和B打了4分
  3. 为了让RM学到人类偏好即排序可以四个语句两两组合分别计算loss再相加取均值即分别计算gif.latex?C_%7B4%7D%5E%7B2%7D个即6个loss具体的loss形式如下图

    gif.latex?%5Ctext%7Bloss%7D%28%5Ctheta%29%3D-%5Cfrac%7B1%7D%7B%20%28_%7B2%7D%5E%7BK%7D%5Ctextrm%7B%7D%29%20%7DE_%7B%28x%2Cy_w%2Cy_l%29%5Csim%20D%7D%5B%5Clog%28%5Csigma%28r_%5Ctheta%28x%2Cy_w%29-r_%5Ctheta%28x%2Cy_l%29%29%29%5D

针对这个损失函数需要逐一说明的是

  1. 这是一个常见的排序模型其中gif.latex?x是提示Prompt输入gif.latex?y是SFT的预测输出因为答案得跟着问题所以问题答案的输出是一对输出比如(gif.latex?x,gif.latex?y_%7Bw%7D)、(gif.latex?x,gif.latex?y_%7Bl%7D)gif.latex?r_%7B%5Ctheta%20%7D是RM模型K是对多少个答案进行排序实际处理是针对每个prompt生成gif.latex?%28_%7B2%7D%5E%7BK%7D%5Ctextrm%29个比较比如4个输出有6次比较9个输出有36次比较gif.latex?D是人类比较的数据集。

    有一点要提下的是RLHF中的rank就好比监督学习中的弱标注——它并不提供直接的监督信号。但通过学习简单的排序RM可以学到人类的偏好。
    为何是排序而非直接打分呢道理很简单排序相比打分更容易接近客观事实即不同的标注员打分的偏好会有很大的差异比如同样一段精彩的文本有人认为可以打1.0但有人认为只能打0.8而这种差异就会导致出现大量的噪声样本若改成标注排序则发现不同的标注员的打分一致性就大大提升了

    再打个比方有一家冰箱工厂生产了好几种类型的冰箱虽然这些客户中没有一个懂得如何造冰箱的或者说他们不需要懂但他们可以通过消费者的各类行为(点赞/评价、复购等)让厂商明白消费者对冰箱类型的“偏好”从而引导冰箱厂商生产销量更好的冰箱。

    相当于一个非专家的普通人类无法向一个6岁小孩解释清楚什么是RL但他总能从多个备选答案判断出哪一个答案更好吧毕竟选择比创造更容易啊多么有创造性的解决方案
  2. 首先把你的问题gif.latex?x和答案gif.latex?y_%7Bw%7D放进奖励函数r中再把问题gif.latex?xgif.latex?y_%7Bl%7D也放进奖励函数gif.latex?r_%7B%5Ctheta%20%7D中然后分别输出假定gif.latex?y_%7Bw%7D是语句组合对中相对gif.latex?y_%7Bl%7D打分更高的所以两者一减这里面使用的是交叉熵损失函数奖励的差异表示一种应答比另一种应答更受人类标注者青睐的对数概率我们希望相减的结果越大越好
  3. 最后通过Logitech函数变成一个loss函数而因为loss函数最前面加了一个负号相当于最大化上面第2点最后相减的结果gif.latex?r_%7B%5Ctheta%20%7D(gif.latex?x,gif.latex?y_%7Bw%7D) − gif.latex?r_%7B%5Ctheta%20%7D (gif.latex?x,gif.latex?y_%7Bl%7D)等于是最小化这个loss函数

如此通过这种形式的梯度回传RM逐渐学会了给D这类语句打高分给A、B这类语句打低分从而模仿到了人类偏好。到了这一步不妨可以这么简单理解RLHF所谓的人类反馈的强化学习某种意义上来说就是由人类的打分来充当reward。

1b37ed859770ba388d86273e3c7c6517.png

3.1.4 instructGPT训练阶段3如何通过PPO算法进一步优化策略模型

instructGPT原始论文中的目标函数如下图所示

87fa4abfbdde486f9a080e4d85f3db20.png

大部分文章在分析这个目标函数时基本都是人云亦云、一带而过在这里我们逐一拆接下这个目标函数分为三个部分

  1. 第一部分是gif.latex?r_%7B%5Ctheta%20%7D%28x%2Cy%29相当于根据人类偏好的学习出来的RM模型
  2. 第二部分则是用KL散度对比RL学到的策略模型gif.latex?%5Cpi_%7B%5Cphi%7D%5E%7BRL%7D和原始策略模型gif.latex?%5Cpi%20%5E%7BSFT%7D的某种差距一开始时gif.latex?%5Cpi_%7B%5Cphi%7D%5E%7BRL%7D的初始化值就是gif.latex?%5Cpi%20%5E%7BSFT%7D且咱们希望它俩之间的差距不至于太大(为啥步子太大容易扯到那啥..)

    这个时候你就可以用到PPO算法了还记得PPO算法的用途么
    “我们可以通过重要性采样把同策略换成异策略但重要性采样有一个问题如果  gif.latex?p_%7B%5Ctheta%7D%5Cleft%28a_%7Bt%7D%20%7C%20s_%7Bt%7D%5Cright%29与 gif.latex?p_%7B%5Ctheta%27%7D%5Cleft%28a_%7Bt%7D%20%7C%20s_%7Bt%7D%5Cright%29相差太多即这两个分布相差太多重要性采样的结果就会不好。 怎么避免它们相差太多呢这就是PPO要做的事情。”
    顺带你可以对比下PPO算法的优化函数、和约束条件(别忘了KL散度可以衡量两个分布之间相似程度)

    gif.latex?%5Cbegin%7Baligned%7D%20%26J_%7B%5Cmathrm%7BPPO%7D%7D%5E%7B%5Ctheta%5E%7B%5Cprime%7D%7D%28%5Ctheta%29%3DJ%5E%7B%5Ctheta%5E%7B%5Cprime%7D%7D%28%5Ctheta%29-%5Cbeta%20%5Cmathrm%7BKL%7D%5Cleft%28%5Ctheta%2C%20%5Ctheta%5E%7B%5Cprime%7D%5Cright%29%20%5C%5C%20%26J%5E%7B%5Ctheta%5E%7B%5Cprime%7D%7D%28%5Ctheta%29%3D%5Cmathbb%7BE%7D_%7B%5Cleft%28s_%7Bt%7D%2C%20a_%7Bt%7D%5Cright%29%20%5Csim%20%5Cpi_%7B%5Ctheta%5E%7B%5Cprime%7D%7D%7D%5Cleft%5B%5Cfrac%7Bp_%7B%5Ctheta%7D%5Cleft%28a_%7Bt%7D%20%5Cmid%20s_%7Bt%7D%5Cright%29%7D%7Bp_%7B%5Ctheta%5E%7B%5Cprime%7D%7D%5Cleft%28a_%7Bt%7D%20%5Cmid%20s_%7Bt%7D%5Cright%29%7D%20A%5E%7B%5Ctheta%5E%7B%5Cprime%7D%7D%5Cleft%28s_%7Bt%7D%2C%20a_%7Bt%7D%5Cright%29%5Cright%5D%20%5Cend%7Baligned%7D

    其中 KL奖励系数gif.latex?%5Cbeta控制 KL 惩罚
  3. 第三部分是加在最后边的偏置项其中 gif.latex?D_%7Bpretrai%7D是预训练分布预训练损失系数gif.latex?%5Cgamma控制预训练梯度的强度且gif.latex?%5Cgamma设置为0则称为PPO模型否则称为PPO-ptx模型
    之所以加最后的这个偏置项是防止ChatGPT在RL的训练过程中过渡优化从而避免过于放飞自我通过某种刁钻的方式取悦人类而不是老老实实地根据人类的问题给出正确答案

最终迭代式的更新奖励模型RM和策略模型SFT让奖励模型对模型输出质量的刻画愈加精确使得输出文本变得越来越符合人的认知

78055db0e39e623f2e2b7b4efa4b3593.png

3.2 instructGPT如何基于RLHF运用到多轮对话场景中

既然RLHF能很好地解决RL甚至IL的一些问题也在InstructGPT中取得了很好的效果。那么是否可以顺理成章地将之迁移到多轮对话场景中呢或者说ChatGPT是如何将这一套框架应用到多轮对话场景中的

无限风光在险峰故继续攀登继续深入。

我们可以从强化学习的假设出发去理解这个问题。事实上以PPO为代表的强化学习模型基于马尔可夫性的假设。简单理解马尔科夫性就是它将来的状态只取决于现在与过去无关。也就是说马尔可夫性有一个很重要的特点无记忆性。

然而在多轮人机对话场景中模型却应该具备部分可观测马尔可夫性即要求语言模型有“记忆性”。这理解起来也比较直观在多轮对话场景里存在某一轮对话中的代词指向上一轮对话中的某个人或物的可能假如模型不具备记忆性那就无法很好地处理这种问题。显然强化学习的假设与多轮对话场景的相背不做一些优化的话很难直接应用。

那么进一步的问题来了InstructGPT/ChatGPT是如何做优化的呢

  1. 这里我们先从自然语言任务中最基本的语言模型简单说起。一个语言模型大概是说当你给定前面的若干个词后它会给你下一个词而当你有了下一个词后它会再给你接一个词以此递推。
  2. 这就好比我们使用手机输入法你打出一些词句后输入法会提供若干个候选词——这里的手机输入法其实就是一个语言模型。那么我们如何利用这个最基本的语言模型来建模多轮对话问题呢
  3. 实际上我们向ChatGPT提出的问题可以看成一句话或者说是下图的输入gif.latex?X。然后我们可以将ChatGPT给出的答案抽象成下图的输出gif.latex?Y。而ChatGPT这类语言模型提供了若干个类似手机输入法的“候选句”每个候选句对应的概率不一。所谓的语言模型的训练其实就是让模型调整候选句对应的概率使我们人类希望输出的候选句的概率尽可能大而不希望输出的概率尽可能小。

4ea27677bac93469d6143a5161d5b037.png

那么这个语言模型和强化学习又有什么样的联系呢在强化学习中我们确实有智能体/模型Agent和环境Environment交互这样的范式。但是在ChatGPT所使用的这种训练方式中环境从某种意义上说被直接被奖赏模型RM取代了如下图

725d62dd8d0f2997cc2329d5a50977bc.png

  1. 图中的状态State是之前提到的输入语句gif.latex?X而当智能体拿到一个gif.latex?X它给出的动作action其实是下一个单词gif.latex?x_%7Bk%7D。注意GPT确实可以输出一整句话gif.latex?X但其实要完成这个最终的输出需要做若干次如图所示的action。
  2. 当环境或RM接收到它给出的单词gif.latex?x_%7Bk%7D后会把这个单词放到已有的单词序列gif.latex?X末尾然后再把这个新的单词序列还给智能体之后依次类推
  3. 打个比方这里的智能体就是手机输入法而环境就是使用输入法的用户。用户所做的事情就是当输入法给出一系列候选词后基于某种偏好选择某个词然后让手机输入法再去猜下一个词直到输入法把整个句子猜出来为止

这里我们明白了在语言模型场景下强化学习的状态和动作对应什么那么奖赏Reward呢

上文已经分析过instructGPT的目标函数了这里就不再赘述直接上图

300d2c30d66a2fc2c9a96a2535790a19.png

至此还有一个细节问题即这个奖赏函数是对整个输入语句gif.latex?X和整个输出语句gif.latex?Y而言的而我们又在之前讨论过智能体是根据一个一个词来去拼凑出整个回答的。图中的奖赏函数只能给出完整回答的奖赏那么在智能体生成回答的过程中每个动作action给出的词gif.latex?x_%7Bk%7D对应的奖赏是什么呢

这个细节在InstructGPT中并没有给出。幸运的是OpenAI团队2020年的另一篇论文《Learning from summarize from Human feedback》中的一个引脚标注给出了关于这个疑问的答案。作者说奖赏模型只在最终生成回答之后才给出奖赏在中间的过程中是不给出奖赏的。在这里作者没有使用回答一词而是使用总结一词因为它的任务是将一篇长文章进行归纳总结。

 同时还有一个意外收获发现这篇论文里就已经提出了instructGPT/chatgpt类似的训练模式1 根据人来标注数据微调监督模型2 训练一个奖励函数3 通过PPO优化原始监督模型的策略

顺着这位作者的思路只有在ChatGPT输出了EOS token的时候整个轨迹才结束EOS token是自然语言处理中用来表示一段话结束的标志。

最后再让我们回顾梳理下这个问题RLHF是如何运用到ChatGPT中的多轮对话场景中的

  1. 由于多轮对话要求语言模型有记忆性因此无法直接使用强化学习。这里的矛盾具体体现在了奖赏函数中ChatGPT的奖赏函数是针对GPT的一整个输入语句gif.latex?X和一整个输出语句gif.latex?Y而言的
  2. 而ChatGPT的语言模型在强化学习的训练策略中每个action其实输出的是一个个词语。因此OpenAI的团队可能是采取不对序列的中间生成给予reward的方式解决上文提到的矛盾而这种解决方式十分接近SeqGAN的思路

问题又来了什么是SeqGAN(Sequence Generative Adversarial Nets with Policy Gradient)呢

第四部分 扩展seqGAN——NLP下对抗思想与RL的碰撞

4.1 SeqGAN模型改进GAN只能处理图像数据

4.1.1 从GAN到SeqGAN把GAN用到NLP领域里

非连续性序列生成比如说文本生成注意图像和文本的核心区别在于图像的 Pixel 表示是连续的而文本是由离散的token组成为什么单纯的使用GAN没有取得很好的效果呢主要的屏障有两点

  1. 在GAN中Generator 用于生成文本的而Discriminator则判别文本是真实的还是生成的

    一开始Generator通过随机抽样作为开始然后根据模型的参数进行确定性的转化。通过generative model G的输出discriminative model D计算的损失值根据得到的损失梯度(即把生成文本与真实文本之间的差异转化为loss)去指导generative model G做轻微改变从而使G产生更加真实的数据

    37025db937df9fde4c99f9ca0074e67d.png

    但在文本生成任务中G通常使用的是LSTM那么G传递给D的是一堆离散值序列即每一个LSTM单元的输出经过softmax之后再取argmax或者基于概率采样得到一个具体的单词那么这使得梯度下降很难处理

    说白了就是在处理离散数据时判别器难以使用SGD直接将梯度信息传递给生成器从而G和D都无法进行更新
  2. GAN只能评估出整个生成序列的score/loss不能够细化到去评估当前生成token的好坏和对后面生成的影响
    说白了就是判别器只能针对于完整的序列数据给出判别结果

如果可以想办法解决上面的两个问题我们就可以尝试将GAN用于NLP中。SeqGAN就提供了一种很巧妙的思路来解决这两个问题

a88b2513f55f1bf75c85aac8cf60681e.png

  • 再回想一下Policy Gradient的基本思想即通过reward作为反馈增加得到reward大的动作出现的概率减小reward小的动作出现的概率如果我们有了reward就可以进行梯度训练更新参数

    相当于如果GAN结合Policy Gradient后当G产生一个单词时如果我们能够得到一个反馈的Reward就能通过这个reward来更新G的参数而不再需要依赖于D的反向传播来更新参数因此较好的解决了上面所说的第一个屏障
    换言之无法直接使用常规的随机梯度下降进行参数的更新那就使用强化学习中的策略梯度policy gradient

    进一步讲如果我们把Generator 看成是一个 Agent他在每一 time step 上生成的 word token 作为 action此前生成的所有 tokens 作为 state我们就可以设计一个 reward function 来指导 Generator 生成更真实的句子。
    因为 Discriminator 输出是真实句子的概率 0-1直接拿来作为 reward于是就有了下面的式子

    gif.latex?Q_%7BD_%5Cphi%7D%5E%7BG_%5Ctheta%7D%3D%28a%20%3D%20y_%7BT%7D%2C%20s%3D%20Y_%7B1%3AT-1%7D%20%3D%20D_%7B%5Cphi%7D%28Y_%7B1%3AT%7D%29%29

    但是对于生成了一半的句子怎么评估其真实性呢用蒙特卡洛蒙特卡洛就是随机采样搜索在一个 Generator 的拷贝上为了避免搜索过程引入对梯度的影响补全句子然后再交给 Discriminator 评估。于是完成的 Q function 如下

    45bacd23a6fc5f412accc6b30c626e33.png

  • 对于第二个屏障当产生一个单词时我们可以使用蒙塔卡罗树搜索(Alpho Go也运用了此方法)立即评估当前单词的好坏而不需要等到整个序列结束再来评价这个单词的好坏
    换言之既然判别器无法直接处理部分生成的序列那就使用蒙特卡洛搜索Monte Carlo Search来将已生成的序列补成完整的序列再给出得分

因此强化学习和对抗思想的结合理论上可以解决非连续序列生成的问题而SeqGAN模型正是这两种思想碰撞而产生的可用于文本序列生成的模型。

4.1.2 SeqGAN在对话聊天中的应用

其实也有人将RL应用于对话生成的训练当中因为对话生成任务本身非常符合强化学习的运行机理让人类满意拿奖励。假设根据输入句子 a 返回的回答 x 从人类得到的奖励记为 R(a,x) 而Encoder-Decoder对话模型服从的参数被统一记为 θ 则基于RL的目标函数说白了就是最大化生成对话的期望奖励其中 Pθ(a,x) 表示在参数 θ 下一组对话 (a,x) 出现的概率。

a83ed6380093450e87c2ab14d9f45b0e.png

f95fd292909bab2b95f31b71676476b7.png

既然是一个最优化的问题很直接地便想到使用基于梯度Gradient的优化方法解决。当然在强化学习中我们要得到的是最优策略 θbest 继而我们可以用策略梯度算法解决。

我们把等式右边 arg⁡maxθ(⋅) 中的项单独记为 Rθ~ 它表示对话模型找到最优参数时所得到的奖励期望。在实做时设某句话的应答有N种可能性则每组对话 (ai,xi) 出现的概率可视为服从均匀分布故还可以进行如下变形

02f4e41050704a76a8fb09715e80a356.png

在优化过程中对话模型的权重 θ 更新如下 ∇Rθ~ 为所获奖励的变化梯度

gif.latex?%5Ctheta%20%5E%7B%28i&plus;1%29%7D%20%5Cleftarrow%20%5Ctheta%20%5E%7Bi%7D%20&plus;%20%5Ceta%20%5Ctriangledown%20%5Ctilde%7BR%7D_%7B%5Ctheta%20%5E%7Bi%7D%7D

借助复合函数的求导法则继续推导奖励的变化梯度

81d6161880f546759b1e609c169b91ea.png

这样一来梯度优化的重心就转化到了生成对话的概率上来也就是说通过对参数 θ 进行更新奖励会使模型趋于将优质对话的出现概率提高而惩罚则会让模型趋于将劣质对话的出现概率降低。

SeqGAN的提出为GAN用于对话生成Chatbot完成了重要的铺垫同样起到铺垫作用的还有另外一个GAN在图像生成领域的神奇应用——Conditional GAN[18~19]有条件的GAN顾名思义就是根据一定的条件生成一定的东西该工作根据输入的文字描述作为条件生成对应的图像比如

format,png

对话生成可以理解为同样的模式上一句对话作为条件下一句应答则为要生成的数据唯一的不同是需要生成离散的文本数据而这个问题SeqGAN已经帮忙解决了。综上我自己给它起名Conditional SeqGAN[20]。Conditional SeqGAN中的优化梯度可写成

d4c26fc6ee534834b02cb5ec73491e37.png

 不难看出此式子与上面的变化梯度仅一字之差只是把“打分器”给出的奖励得分 R(ai,xi) 换成了鉴别器认为生成对话来自真人的概率得分 D(ai,xi) 。

在原本的强化学习对话生成中虽然采用了AI互相对话并设定了 jugle 进行打分但这个 jugle 是预训练好的在对话模型的训练过程当中将不再发生变化RL + GAN 的文本生成乃至对话模型则不同鉴别器D与生成器G的训练更新将交替进行此消彼长故而给出奖励得分的鉴别器D在这里是动态的dynamic。

48e04408c105fff204cd8d28b8451f4b.png

总之RL+ GAN 利用强化学习中的 Reward 机制以及 Policy Gradient 等技术巧妙地避开了GAN面对离散数据时梯度无法BP的难题在使用强化学习的方法训练生成器G的间隙又采用对抗学习的原版方法训练判别器D。 在Conditional SeqGAN对话模型的一些精选结果中RL+ GAN 训练得到的生成器时常能返回一些类似真人的逼真回答。

此外值得一提的是我们所熟知的Actor-Critic是不是也是一种更广义上的GAN呢

4.2 逆强化学习就是GAN技术ChatGPT = Transformer + SeqGAN

终于即将达到顶峰了。

  1. 我们可以将ChatGPT这种聊天机器人理解为模仿学习在聊天机器人里面我们会收集到很多人交互对话的记录这些就是所谓专家的示范

    对于ChatGPT而言什么可以被称为一个最好的奖励函数呢最后我们学习出来的奖励函数应该是人类标注知识和ChatGPT本身在这个奖励函数上都会得到一样高的分数最终的奖励函数无法分辨出谁应该会得到比较高的分数也就是你不知道你在对话的背后到底是真实的人还是只是机器chatgpt了。
  2. 序列生成对抗网络对应逆强化学习逆强化学习就是一种生成对抗网络的技术。我们把逆强化学习的技术放在句子生成、聊天机器人里面其实就是序列生成对抗网络SeqGAN与它的种种变形

这里我们可以梳理下RLHF和GPT的本质关系。实际上这里使用RLHF就是为了解决我们无法对一个离散的训练进行求导的问题。而使用强化学习来解决这个问题也不是ChatGPT的独创早在2016年SeqGAN的作者就已经使用了这样的方法了。因此我们可以从问题本质的角度去这么理解ChatGPT它就是把Transformer和“SeqGAN”结合在一起。

当然这个“SeqGAN”并不是标准版本因为它不是像模仿学习那样通过指示来学习而是通过人类的偏好来进行学习。从问题本质上看ChatGPT与之前的工作的最大不同就体现在它使用了SeqGAN进行微调。

参考文献与推荐阅读

  1. BERT通俗笔记从Word2Vec/Transformer逐步理解到BERTJuly
  2. 预训练语言模型》电子工业出版
  3. GPTGPT-2GPT-3 论文精读
  4. GPT到GPT2、GPT3各自对应的原始论文可以在这里找到https://beta.openai.com/docs/model-index-for-researchers
  5. prompt提示学习一简要介绍
  6. CMU刘鹏飞近代自然语言处理技术发展的“第四范式”
  7. 大模型prompt Turing技术上
  8. NLP小样本学习如何用20条数据完成文本分类此外小样本学习也是七月NLP高级班上重点讲的技术之一最新一期NLP11则加入了ChatGPT背后原理的解析
  9. GPT-3.5 + ChatGPT: An illustrated overview - Life Architect
  10. 强化学习入门这一篇就够了
  11. 白话强化学习与Pytorch》此书让我1.6日起正式开启RL之旅没看此书之前很多RL资料都不好看懂
  12. 《Eazy RL强化学习教程》基于台大李宏毅和UCLA周博磊等人的RL公开课所编著其GitHub其在线阅读地址
  13. 台大李宏毅RL公开课这是其视频/PPT/PDF下载地址
  14. UCLA周博磊RL公开课这是其GitHub地址
  15. 关于Q-leaning的几篇文章1 如何用简单例子讲解 Q - learning 的具体过程 2 莫烦什么是 Q-Learning
  16. AlphaGo作者之一David Silver主讲的增强学习笔记1笔记2另附课件地址
  17.  huggingface的两篇RL教程An Introduction to Deep Reinforcement LearningGitHubThe Hugging Face Deep Reinforcement Learning Course

  18. TRPO原始论文Trust Region Policy Optimization
  19. PPO原始论文Proximal Policy Optimization Algorithms
  20. PPO算法解读(英文2篇)解读1 RL — Proximal Policy Optimization (PPO) Explained、解读2 Proximal Policy Optimization (PPO)
  21. PPO算法解读(中文3篇)Easy RL上关于PPO的详解详解近端策略优化详解深度强化学习 PPO算法
  22. PPO算法实现https://github.com/lvwerra/trl
  23. 如何选择深度强化学习算法MuZero/SAC/PPO/TD3/DDPG/DQN/等
  24. Google搜索instructGPT如何基于PPO算法进行训练出来的一系列文章
  25. InstructGPT原始论文(确实有68页^_^)Training language models to follow instructions with human feedback这是翻译版之一这是翻译之二
  26. InstructGPT 论文精读来自动手学深度学习一书作者李沐的解读
  27. ChatGPT: Optimizing Language Models for Dialogue
  28. Illustrating Reinforcement Learning from Human Feedback (RLHF)另这是中文翻译版之一
  29. OpenAI联合DeepMind发布全新研究根据人类反馈进行强化学习
  30. 基于人类偏好的深度强化学习Deep reinforcement learning from human preferences这是翻译版之一这是解读之一
  31. 《Learning from summarize from Human feedback》
  32. HuggingFace的视频分享RL from Human Feedback- From Zero to chatGPT
  33. OpenAI's InstructGPT: Aligning Language Models with Human Intent
  34. 不忽悠的ChatGPT作者Ben
  35. 别光顾着玩让我来告诉你ChatGPT的原理来自B站UP主弗兰克甜
  36. 浅析ChatGPT的原理及应用
  37. 如何通俗理解隐马尔可夫模型HMM
  38. HMM学习最佳范例
  39. GAN之父在NIPS 2016上做的报告两个竞争网络的对抗含译文下载
  40. AAAI 2017 《SeqGAN: Sequence Generative Adversarial Nets with Policy Gradient》
  41. SeqGAN —— GAN + RL +NLP
  42. 对抗思想与强化学习的碰撞-SeqGAN模型原理和代码解析
  43. Role of RL in Text Generation by GAN(强化学习在生成对抗网络文本生成中扮演的角色)
  44. 抱抱脸ChatGPT背后的算法——RLHF

后记下一篇笔记RL极简入门

事实上可能很多朋友也已经意识到本文的前大部分内容里GPT-N理解起来相对轻松而instructGPT/ChatGPT的整体架构思想也不算复杂但其中涉及到的强化学习部分则让想深挖细节的初学者变得立马吃力起来(除非你已“入一定门”或者你有课程/老师可以不断问)看似就两个概念一个RLHF一个PPO算法但要真正把这两个概念讲清楚、讲透彻则没那么容易了特别是PPO算法。

所以1.6日决定只是想写个ChatGPT通俗导论但为了讲清楚其中的PPO算法更考虑到ChatGPT笔记之后再下一篇是强化学习极简入门故中途花了大半时间去从头彻底搞懂RL最终把网上关于RL的大部分中英文资料都翻遍之外(详见参考文献与推荐阅读)还专门买了这几本强化学习中文书以系统学习

  • 第1本(1.7下午-1.8日)《白话强化学习与pytorch》偏通俗对初学者最友好可以最快最短时间内入门RL缺点是对部分前沿/细节比如PPO算法阐述不足毕竟19年出版的了
  • 第2本(1.9-1.10凌晨)《Eazy RL强化学习教程》基于台大李宏毅等人的公开课对于初学入门不错的入门之后可以下面的后3本
  • 第3本《深度强化学习图解》偏图表示例
  • ​第4本《动手学强化学习》张伟楠等人著偏代码实现
  • 第5本《深度强化学习》王树森等人著偏原理讲解此书对于已对RL有一定了解的是不错的选择对于尚未了解RL的则如果能再通俗易懂些会更好
  • 第6本《强化学习2》权威度最高但通俗性不足当然 也看人没入门之前你会觉得此书晦涩入门之后你会发现经典还是经典、不可替代另书之外可配套七月的强化学习2带读课

总之RL里面的概念和公式很多(相比ML/DLRL因为想要机器/程序具备更高、更好的自主决策能力)而​绝大部分的资料没有站在初学者的角度去通俗易懂化、没有把概念形象具体化、没有把公式拆解举例化(如果逐一做到了这三点何愁写不出通俗易懂的文章/书籍/课程)。

以下是本文自1.15发布初稿之后的修改记录

  1. //待改...
阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6
标签: ChatGPT