庆云古诗词

庆云古诗词

如何用chatgpt把代码做注释 chat gpt怎么让它输出完整的代码

互联资讯 0

2023年11月20日 每日一猜答案: 答案:ABC
每日一猜答案分析:

如何用chatGPT画图,如何用chatGPT写ppt,如何用chatGPT4,如何用chatGPT降重

最近一直在做类ChatGPT项目的部署 微调,关注比较多的是两个:一个LLaMA,一个ChatGLM,会发现有不少模型是基于这两个模型去做微调的,说到微调,那具体怎么微调呢,因此又详细了解了一下微调代码,发现微调LLM时一般都会用到Hugging face实现的Transformers库的Trainer类

从而发现,如果大家想从零复现ChatGPT,便得从实现Transformer开始,因此便开启了本文:如何从零起步实现Transformer、ChatGLM(至于LLaMA已在之前的博客里解读过),主要分为两个大部分

  • 按照transformer的每一步的原理逐步逐行从零实现,先编码器后解码器,特别是注意力机制(缩放点积、多头注意力)
  • 从头到尾解读ChatGLM-6B的整体代码架构,及逐行解读每一行代码 且本文的代码解读与其他代码解读最大的不同是:会对出现在本文的每一行代码都加以注释、解释、说明,甚至对每行代码中的变量都会做解释/说明

总之,一如既往的保持对初学者的足够友好,让即便没有太多背景知识的也能顺畅理解本文

transformer强大到什么程度呢,基本是17年之后绝大部分有影响力模型的基础架构都基于的transformer(比如,这里有200来个,包括且不限于基于decode的GPT、基于encode的BERT、基于encode-decode的T5等等)

通过博客内的这篇文章《Transformer通俗笔记:从Word2Vec、【【微信】】逐步理解到GPT、BERT》,我们已经详细了解了transformer的原理(如果忘了,建议必复习下再看本文,当然,如果你实在不想跳转,就只想呆在本文,也行,我努力..)

如果把上图中的各种细节也显示出来,则如下大图所示(此大图来源于七月在线NLP11里倪老师讲的Transformer模型源码解读,positional encoding、多头等没画)

考虑到Hugging face实现的Transformers库虽然功能强大,但3000多行,对于初次实现的初学者来说,理解难度比较大,因此,咱们一步步结合对应的原理来逐行编码实现一个简易版的transformer

?为了方便后面代码的编写,先引入一些库

对于模型来说,每一句话比如“七月的服务真好,答疑的速度很快”,在模型中都是一个词向量,但如果每句话都临时抱佛脚去生成对应的词向量,则处理起来无疑会费时费力,所以在实际应用中,我们会事先预训练好各种embedding矩阵,这些embedding矩阵包含常用领域常用单词的向量化表示,且提前做好分词

维度1维度2维度3维度4...维度512
教育
机构
在线
课程
..
服务
答疑
老师

从而当模型接收到“七月的服务真好,答疑的速度很快”这句输入时,便可以从对应的embedding矩阵里查找对应的词向量,最终把整句输入转换成对应的向量表示

这部分的代码 可以如下表示

然,如此篇文章所述,RNN的结构包含了序列的时序信息,而Transformer却完全把时序信息给丢掉了,比如“他欠我100万”,和“我欠他100万”,两者的意思千差万别,故为了解决时序的问题,Transformer的作者用了一个绝妙的办法:位置编码(Positional Encoding)。

即将每个位置编号,从而每个编号对应一个向量,最终通过结合位置向量和词向量,作为输入embedding,就给每个词都引入了一定的位置信息,这样Attention就可以分辨出不同位置的词了,具体怎么做呢?

  1. 如果简单粗暴的话,直接给每个向量分配一个数字,比如1到1000之间
  2. 也可以用one-hot编码表示位置
  3. transformer论文中作者通过sin函数和cos函数交替来创建 positional encoding,其计算positional encoding的公式如下 其中,pos相当于是每个token在整个序列中的位置,相当于是0, 1, 2, 3...(看序列长度是多大,比如10,比如100),代表位置向量的维度(也是词embedding的维度,transformer论文中设置的512维)?

    至于是embedding向量的位置下标对2求商并取整(可用双斜杠表示整数除法,即求商并取整),它的取值范围是,比如,,,,,, ...,,

    相当于是指向量维度中的偶数维,即第0维、第2维、第4维...,第510维,用sin函数计算 是向量维度中的奇数维,即第1维、第3维、第5维..,第511维,用cos函数计算

不要小看transformer的这个位置编码,不少做NLP多年的人也不一定对其中的细节有多深入,而网上大部分文章谈到这个位置编码时基本都是千篇一律、泛泛而谈,很少有深入,故本文还是细致探讨下

考虑到一图胜千言 一例胜万语,举个例子,当我们要编码「我 爱 你」的位置向量,假定每个token都具备512维,如果位置下标从0开始时,则根据位置编码的计算公式可得且为让每个读者阅读本文时一目了然,我计算了每个单词对应的位置编码示例(在此之前,这些示例在其他地方基本没有)

  • 当对上的单词「我」进行位置编码时,它本身的维度有512维
  • 当对上的单词「爱」进行位置编码时,它本身的维度有512维

    ?然后再叠加上embedding向量,可得

  • 当对上的单词「你」进行位置编码时,它本身的维度有512维
  • ....

最终得到的可视化效果如下图所示

代码实现如下

从下图可知,经过「embedding + 位置编码」得到的输入,会乘以「三个权重矩阵:??」得到查询向量Q、键向量K、值向量V(你可以简单粗暴的理解为弄出来了三个分身)

举个例子,针对「我想吃酸菜鱼」这句话,经过embedding + 位置编码后,可得(注:可以512维,也可以是768维,但由于transformer论文中作者设置的512维,所以除了这个酸菜鱼的例子暂为768维外,其他地方均统一为512维)

然后乘以三个权重矩阵得

?为此,我们可以先创建4个相同的线性层,每个线性层都具有 d_model 的输入维度和 d_model 的输出维度

前三个线性层分别用于对 Q向量、K向量、V向量进行线性变换(至于这第4个线性层在随后的第3点)

我们聚焦下transformer论文中原图的这部分,可知,输入通过embedding+位置编码后,先后做以下两个步骤

  1. 针对query向量做【【微信】】,得到的结果与原query向量,做相加并归一化 这个相加具体是怎么个相加法呢?事实上,Add代表的Residual Connection(残差连接),是为了解决多层神经网络训练困难的问题,通过将前一层的信息无差的传递到下一层,可以有效的仅关注差异部分,这一方法之前在图像处理结构如ResNet等中常常用到 具体编码时通过 SublayerConnection 函数实现此功能 而Norm则代表了Layer Normalization,通过对层的激活值的归一化,可以加速模型的训练过程,使其更快的收敛,编码时用?LayerNorm?函数实现
  2. 上面步骤得到的『输出结果output做feed forward』之后,再与『上面步骤的原输出结果output』也做相加并归一化

总而言之,上述过程用公式表达则如下

第一步中的X代表?Multi-Head Attention,第二步中的X代表FFN(本质上就是一个全连接层MLP),最终这个编码器层代码可以完整的写为

接下来,先看下缩放点积注意力(Scaled Dot-Product Attention)的整体实现步骤

  1. 为了计算每个单词与其他单词之间的相似度,会拿「每个单词/token的q向量包括自身在内所有单词/token的k向量一一做点积(两个向量之间的点积结果可以代表两个向量的相似度) 对应到矩阵的形式上,则是矩阵Q与K矩阵的转置做相乘 还是拿上面那个例子:「我想吃酸菜鱼」,则Q乘以K的转置如下图所示 最终得到的矩阵有6行6列,从上往下逐行来看的话,每一个格子里都会有一个数值,每一个数值依次代表:? 单词我与「我 想 吃 酸 菜 鱼」各自的点积结果或相似度,比如可能是0.3?0.2 0.2?0.1 0.1 0.1,代表编码1时放在「我 想 吃 酸 菜 鱼」上面的注意力大小 同时,可以看到模型在对当前位置的信息进行编码时,会过度的将注意力集中于自身的位置(当然 这无可厚非,毕竟自己与自己最相似嘛),而可能忽略了其它位置。很快你会看到,作者采取的一种解决方案就是采用多头注意力机制(Multi-Head Attention)? 想与「我 想 吃 酸 菜 鱼」各自的点积结果或相似度? 吃与「我 想 吃 酸 菜 鱼」各自的点积结果或相似度? 酸与「我 想 吃 酸 菜 鱼」各自的点积结果或相似度? 菜与「我 想 吃 酸 菜 鱼」各自的点积结果或相似度? 鱼与「我 想 吃 酸 菜 鱼」各自的点积结果或相似度?
  2. 由于会随着dimension的增大而增大,为避免过大,所以除以?,相当于对点积的结果做下缩放 其中,是向量的维度,且,如果只设置了一个头,那就是模型的维度,如果设置了8个头,则,且如果模型的维度是512维,则即等于8 上面两步的代码可以如下编写
  3. 接着使用 Softmax 计算每一个单词对包括自身在内所有单词的 Attention值,这些值加起来的和为1(相当于起到了归一化的效果) 这步对应的代码为
  4. 最后再乘以矩阵,即对所有values(【【微信】】),根据不同的attention值(???),做加权平均 对应到我想吃酸菜鱼这个例子上,则是
  5. 最终得到单词的输出,如下图所示(图中V矩阵的4行分别代表【【微信】】): 上述两步对应的代码为

同样的方法,也可以计算出,如下图8所示, b2就是拿q2去对其他的key做attention,最后再与其他的value值相乘取【【微信】】得到,最终每个单词都包含了上下文相关单词的语义信息,不再只是attention计算之前,每个单词只有它自己的信息,和上下文没有关联

另外,这里面还有一点值得注意的是,可能有同学疑问:当我们计算x1与x2、x3、x4的相似度之后,x2会再与x1、x3、x4再依次计算一遍相似度,这两个过程中,前者算过了x1和x2的相似度,后者则再算一遍x2与x1的相似度,这不是重复计算么?其实不然,这是两码事,原因很简单,正如你喜欢一个人 你会觉得她对你很重要,但那个人不一定喜欢你 她不会觉得你对她有多重要..

最终,Scaled Dot-Product Attention这部分对应的完整代码可以写为

先看2个头的例子,依然还是通过生成对应的三个矩阵、、,然后这三个矩阵再各自乘以两个转移矩阵得到对应的分矩阵,如

  • 矩阵对应的两个分矩阵、?
  • 矩阵对应的两个分矩阵为、
  • 矩阵对应的两个分矩阵为、

至于同理,也生成对应的6个分矩阵、、、、、

接下来编码时,分两步

  1. 先与做点积然后乘以然后再与做点积再乘以,再把这两个计算的结果相加得到
  2. 再分别与做点积然后乘以、然后再与做点积再乘以,再把这两个计算的结果相加得到

如果是8个头呢,计算步骤上也是一样的,只是从2个头变化到8个头而已,最终把每个头得到的结果直接concat,最后经过一个linear变换,得到最终的输出,整体如下所示

这部分Multi-Head Attention的代码可以写为

在上文,咱们逐一编码实现了embedding、位置编码、缩放点积/多头注意力,以及Add和Norm,整个编码器部分还剩最后一个模块,即下图框里的Feed Forward Network(简称FFN)

其中包括两个线性变换:维度上先扩大后缩小,最终输入和输出的维数为,内层的维度为,过程中使用ReLU作为激活函数

虽然线性变换在不同位置上是相同的,但它们在层与层之间使用不同的参数,相当于使用了两个内核大小为1的卷积

这部分的代码可以如下编写

N可以等于6或其他数值

其中的clone函数的代码为

咱们再回顾下transformer的整个模型架构,特别是解码器的部分,毕竟BERT外,GPT等很有影响力的模型都用的transformer decode结构

从底至上,

  • 输入包括2部分,下方是前一个time step的输出的embedding 再加上一个表示位置的Positional Encoding
  • 接着是Masked Multi-Head Self-attention,【【微信】】字面意思是屏蔽 然后做一下Add&Norm
  • 再往上是一个不带mask的Multi-Head Attention层,它的Key、Value矩阵使用 Encoder 的编码信息矩阵,而Query使用上一个 【【微信】】 的输出计算 然后再做一下Add&Norm
  • 继续往上,经过一个FFN层,也做一下Add&Norm
  • 最后做下linear变换后,通过Softmax 层计算下一个翻译单词的概率

由于在第一部分介绍过了embedding、positional encoding、FFN、Add&Norm、linear、softmax、【【微信】】,故本部分只重点介绍下Masked Multi-Head Self-attention

本过程和第一部分介绍的Multi-Head self-attention基本一致,区别在于加了个mask机制

  1. 输入经过embedding + 位置编码之后,还是乘以三个不同的权重矩阵:、、,依次得到三个不同的矩阵输入:Q、K、V
  2. Q矩阵乘以K矩阵的转置,得到,注意,紧接着会再乘以一个Mask矩阵,得到Masked Attention矩阵
  3. ?Masked Attention矩阵经过softmax后,乘以V矩阵得到矩阵
  4. 最终把、拼接之后,再做一个linear变换得到最终的矩阵

整个解码器架构的代码可以如下编写『有一点值得注意的是,如下文代码中所述

  • 在对输入x执行自注意力计算并进行第一个子层的处理(带mask),最后一个参数是tgt_mask,即x = self.sublayer[0](x, lambda x: self.self_attn(x, x, x, tgt_mask))
  • 但对输入x执行源注意力计算并进行第二个子层的处理时(不带mask),最后一个参数是src_mask,即x = self.sublayer[1](x, lambda x: self.src_attn(x, m, m, src_mask))?

且Decoder也是由N=6个相同层组成

最终,整个transformer完整模型的整体封装代码为

当我们把编码器和解码器组合到一起后,看下它两是如何一块协作的

需要注意的是

  1. Encoder中的Q、K、V全部来自于上一层单元的输出 而Decoder只有Q来自于上一个Decoder单元的输出,K与V都来自于Encoder最后一层的输出。也就是说,Decoder是要通过当前状态与Encoder的输出算出权重后(计算query与各个key的相似度),最后将Encoder的编码加权得到下一层的状态 比如当我们要把“Hello Word”翻译为“你好,世界”时 Decoder会计算“你好”这个query分别与“Hello”、“Word”这两个key的相似度 很明显,“你好”与“Hello”更相似,从而给“Hello”更大的权重,从而把“你好”对应到“Hello”,达到的效果就是“Hello”翻译为“你好”
  2. 且在解码器中因为加了【【微信】】机制,自注意力层只允许关注已输出位置的信息,实现方法是在自注意力层的softmax之前进行mask,将未输出位置的权重设置为一个非常大的负数(进一步softmax之后基本变为0,相当于直接屏蔽了未输出位置的信息)

具体实现时,先创建批次和掩码

接下来,我们创建一个通用的训练和得分函数来跟踪损失。我们传入一个通用的损失计算函数,它也处理参数更新

下面这段代码定义了一个名为 SimpleLossCompute 的类,实现了简单的损失计算和训练函数

  • 在调用该类的实例时,输入预测输出、目标输出和规范化因子,计算损失值并进行梯度更新
  • 如果提供了优化器,还会更新模型参数和清空梯度缓存

优化器(optimizer)经常用于在训练过程中更新模型参数以最小化损失函数,而Adam(Adapti【【微信】】)是一种常用的优化器,它结合了两种传统优化算法的优点:Momentum和RMSprop

为了通俗易懂地理解Adam,可以将其比作一个赛车手。训练模型就像是找到一辆赛车在赛道上的最佳行驶速度和路径,以达到最快的速度并取得优异的成绩。在这个过程中,速度的调整(即学习率)非常重要

  1. 首先,Adam像Momentum一样,具有动量效应。这意味着赛车手(模型)会积累动量,使其在下坡时更快,而在上坡时减速。这有助于模型更快地穿越平坦区域,并避免在最低点附近摆动

  2. 其次,Adam像RMSprop一样,会自适应地调整每个参数的学习率。在我们的赛车比喻中&#

    必应chatgpt怎么用


    3.1ChatGPT厚积薄发

    最近,工智能公司OpenAI推出的ChatGPT风靡全球,其上线仅两个月,注册用户破亿。ChatGPT包含丰富的知识,不仅能更好地理解人类的问题和指令,流畅进行多轮对话,还在越来越多领域显示出解决各种通用问题和推理生成能力。许多人相信,ChatGPT不仅是新一代聊天机器人的突破,也将为信息产业带来巨大变革,也预示着AI技术应用将迎来大规模普及。

    ChatGPT表现不俗?其背后的技术有哪些?

    3.2 从GPT到GPT-3

    3.3 从GPT-3到ChatGPT的进化路线图

    下图为从最初的GPT-3到GPT-3.5的进化路线图。

    图1 GPT-3初版到ChatGPT的进化路线图

    其中text―davinci―002是在code―davinci―002的基础上使用InstructGPT训练方法改进的。GPT-3.5在GPT-3的基础上加入了代码的能力,ChatGPT的代码训练中,很多数据来自于类似Stack O【【微信】】这样一些代码问答的网站,所以我们会发现它做简单的任务其实做得还蛮好的。

    从图1可知,GPT-3为ChatGPT打下了扎实的基础,但codex、RLHF等技术新增很多新功能,挖掘了GPT-3的潜力。

    3.4 使GPT-3初版升级到ChatGPT的多项关键技术

    从图1可知,这两项关键技术是代码训练(Codex)、RLHF及TAMER等

    1、Codex

    Codex 模型系列是 GPT-3 系列的后代,它经过了自然语言和数十亿行代码的训练。该模型系列精通十几种语言,包括 C# Ja【【微信】】、Go、Perl、PHP、Ruby、Swift、TypeScript、SQL甚至Shell,但最擅长 Python。

    你可以使用Codex完成各种任务,包括:

    • 将注释转换为代码

    • 在上下文中补全下一行代码或函数

    • 为你提供一些知识,例如为应用程序查找有用的库或 API 调用

    • 添加注释

    • 重写代码以提高效率

    Codex如何训练的呢?

    首先,在GITHub数据上预训练模型。这个模型可以合理地表征人类编码空间,可以极大地减少搜索量级。使用带【【淘密令】】的GOLD目标函数,结合编程竞赛数据集,微调模型。可有进一步降低搜索空间,给每个编程题目生成一个较大的样本集;过滤这个样本集,得到一个较小的候选结果集。

    然后,进行代码补全,代码补全这个任务的特殊性:具体来说,传统的NLP任务,生成的结果越接正确答案,那么模型得分越高,但是代码不是这样的,代码但凡有一点点小Bug,都可能造成毁灭性的结果。所以对于代码补全任务,判断生成代码的正确与否就是使用的单元测试(unittest)。

    针对代码补全这样一个特殊问题,作者提出了一个pass@k的一个指标,生成k个结果,只要有一个通过就算通过(k如果比较大,就会对模型的能力过度乐观,当k比较大的时候,虽然模型分数比较高,但是在使用时,会给用户返回一大堆代码,让用户去选,这个也是很难的,所以说需要排算法,但这个分数并没有反映排序)。

    在预训练过程中引入程序代码,和文本一起参与预训练,以此进一步增强大型语言模型(Large Language Model,LLM)的推理能力。这个结论从不少论文的实验部分都可以得出。如图3所示。

    图3 有关codex的试验数据

    从图3给出的实验数据,来自于论文“On the Ad【【微信】】e Models Better Reasoners”,其中GPT-3 davinci就是标准的GPT-3模型,基于纯文本训练;code-da【【微信】】(OpenAI内部称为Codex)是同时在Code和NLP数据上训练的模型。如果比较两者效果,可以看出,不论采用具体哪种推理方法,仅仅是从纯文本预训练模型切换到文本和Code混合预训练模型,在几乎所有测试数据集合上,模型推理能力都得到了巨大的效果提升。

    2、RLHF

    人类反馈强化学习(ReinforcementLearning from Human Feedback,RHFL)模型将预训练语言模型按照人类反馈进一步微调以符合人类偏好,利用人类反馈信息直接优化模型。Open AI 采用了人类反馈强化学习作为ChatGPT和核心训练方式,并称其是“能有效提升通用人工智能系统与人类意图对齐的技术”。RLHF 的训练包括三个核心步骤:

    (1)预训练语言模型(也可以使用额外文本进行微调,监督微调新模型可以让模型更加遵循指令提示,但不一定符合人类偏好)。

    (2)对模型根据提示(prompt)生成的文本进行质量标注,由人工标注者按偏好从最 佳到最差进行排名,利用标注文本训练奖励模型,从而学习到了人类对于模型根据给定提示生成的文本序列的偏好性。

    (3)使用强化学习进行微调,确保模型输出合理连贯的文本片段,并且基于奖励模型对模型输出的评估分数提升文本的生成质量。

    详细过程如图4所示。

    图4 RHFL的训练过程,

    原图来自:Learning to summarize from human feedback

    3、TAMER

    TAMER(Training an Agent Manually 【【微信】】cement,评估式强化人工训练代理)框架。该框架将人类标记引入到智能体(即强化学习中的Agents)的学习循环中,可以通过人类向Agents提供奖励反馈(即指导Agents进行训练),从而快速达到训练任务目标。其架构图如下所示。

    3.5 ChatGPT训练过程

    3.6ChatGPT不断迭代的路线图

    3.7ChatGPT的不足

    尽管ChatGPT在上下文对话能力甚至编程能力上表现出色,完成了大众对人机对话机器人由“人工智障”到“人工智能”的突破,我们也要看到,ChatGPT仍然有一些局限性,还需不断迭代进步。

    (1)ChatGPT在其未经大量语料训练的领域缺乏“人类常识”和引申能力,甚至会一本正经的“胡说八道”。

    (2)ChatGPT无法处理复杂冗长或者特别专业的语言结构。对于来自金融、自然科学或医学等专业领域的问题,如果没有进行足够的语料“喂食”,ChatGPT可能无法生成适当的回答。

    (3)ChatGPT还没法在线的把新知识纳入其中,而出现一些新知识就去重新预训练GPT模型也是不现实的。

    (4)训练ChatGPT需要耗费非常大量的算力,成本还是很大的。

    3.8ChatGPT应用场景

    ChatGPT能够提供高效的信息获取方式,有望成为重要的生产工具,潜在应用领域广泛。业界普遍认为,ChatGPT将在智能办公、智慧科研、智慧教育、智慧医疗及游戏、新闻等领域迅速落地。在金融、传媒、文娱、电商等领域,ChatGPT可以为各类消费群体提供个性化、高质量的服务,解锁多领域智慧应用。