Chatgpt论文笔记——GPT1详细解读与可运行的代码

前言

论文:https://cdn.openai.com/research-covers/language-unsupervised/language_understanding_paper.pdf
时间:2018年6月
贡献:

提出了大规模数据上无监督预训练然后在目标任务上有监督finetune的范式。

具体实现

当时由于NLP领域不存在像图像领域中ImageNet那样百万级别标注的数据(并且图像的像素包含了比句子更丰富的信息,百万级别的图像标注数据相当于千万级别的句子标注数据),所以当时NLP的发展比较缓慢。本文相当于开疆拓土采用了在大规模数据上进行无监督预训练然后再目标任务上进行有监督finetune的尝试。
最后实验的效果是在12个NLP任务上,9个取得了超过SOTA的效果:
在这里插入图片描述

模型结构

GPT的模型结构核心组建是transformer的decoder模块,为什么用transformer而不用经典的RNN或者LSTM,GRU之类呢?因为作者在论文中说到,相比于RNN,transformer学到的特征更加的稳健一些,这个可能还是跟transformer里面的self attention有关,它更加的结构化并且可以学习了token和token之间的关系,对句子的理解更加的深刻。
完整的GPT1模型结构也比较简单:
在这里插入图片描述
整体采用了12个transformer的decoder模块构成,其实这里说的decoder给我造成了很多误解,我记得transformer的decoder部分长这样:
在这里插入图片描述
但是看GPT论文的结构又是transformer的encoder的样子:
在这里插入图片描述
所以一直没明白为啥说用的是decoder,仔细看了下别人实现的代码才发现了,主要是GPT仅仅用了单向的transformer,也就是mask multi head self attention,也就是transformer的decoder模块的这部分:
在这里插入图片描述
但是整个结构还是还是encoder一样的,只是MHA这个地方用了mask所以说成了用了decoder部分。
至于为什么用带Mask的MHA呢?

GPT中因为要完成语言模型的训练,也就要求Pre-Training预测下一个词的时候只能够看见当前以及之前的词,这也是GPT放弃原本Transformer的双向结构转而采用单向结构的原因。

代码

没有代码是不完整的,直接上模型结构的代码

import torch
import torch.nn as nnclass ScaledDotProductAttention(nn.Module):def __init__(self, d_k, attn_pdrop):super(ScaledDotProductAttention, self).__init__()self.d_k = d_kself.dropout = nn.Dropout(attn_pdrop)def forward(self, q, k, v, attn_mask):# |q| : (batch_size, n_heads, q_len, d_k)# |k| : (batch_size, n_heads, k_len, d_k)# |v| : (batch_size, n_heads, v_len, d_v)# |attn_mask| : (batch_size, n_heads, q_len, k_len)attn_score = torch.matmul(q, k.transpose(-1, -2)) / (self.d_k ** 0.5)attn_score.masked_fill_(attn_mask, -1e9)# |attn_scroe| : (batch_size, n_heads, q_len, k_len)attn_weights = nn.Softmax(dim=-1)(attn_score)attn_weights = self.dropout(attn_weights)# |attn_weights| : (batch_size, n_heads, q_len, k_len)output = torch.matmul(attn_weights, v)# |output| : (batch_size, n_heads, q_len, d_v)return output, attn_weightsclass MultiHeadAttention(nn.Module):def __init__(self, d_model, n_heads, attn_pdrop):super(MultiHeadAttention, self).__init__()self.n_heads = n_headsself.d_k = self.d_v = d_model // n_headsself.WQ = nn.Linear(d_model, d_model)self.WK = nn.Linear(d_model, d_model)self.WV = nn.Linear(d_model, d_model)self.scaled_dot_product_attn = ScaledDotProductAttention(self.d_k, attn_pdrop)self.linear = nn.Linear(n_heads * self.d_v, d_model)def forward(self, Q, K, V, attn_mask):# |Q| : (batch_size, q_len(=seq_len), d_model)# |K| : (batch_size, k_len(=seq_len), d_model)# |V| : (batch_size, v_len(=seq_len), d_model)# |attn_mask| : (batch_size, q_len, k_len)batch_size = Q.size(0)q_heads = self.WQ(Q).view(batch_size, -1, self.n_heads, self.d_k).transpose(1, 2)k_heads = self.WK(K).view(batch_size, -1, self.n_heads, self.d_k).transpose(1, 2)v_heads = self.WV(V).view(batch_size, -1, self.n_heads, self.d_v).transpose(1, 2)# |q_heads| : (batch_size, n_heads, q_len, d_k), |k_heads| : (batch_size, n_heads, k_len, d_k), |v_heads| : (batch_size, n_heads, v_len, d_v)attn_mask = attn_mask.unsqueeze(1).repeat(1, self.n_heads, 1, 1)# |attn_mask| : (batch_size, n_heads, q_len, k_len)attn, attn_weights = self.scaled_dot_product_attn(q_heads, k_heads, v_heads, attn_mask)# |attn| : (batch_size, n_heads, q_len, d_v)# |attn_weights| : (batch_size, n_heads, q_len, k_len)attn = attn.transpose(1, 2).contiguous().view(batch_size, -1, self.n_heads * self.d_v)# |attn| : (batch_size, q_len, n_heads * d_v)outputs = self.linear(attn)# |outputs| : (batch_size, q_len, d_model)return outputs, attn_weightsclass PositionWiseFeedForwardNetwork(nn.Module):def __init__(self, d_model, d_ff):super(PositionWiseFeedForwardNetwork, self).__init__()self.linear1 = nn.Linear(d_model, d_ff)self.linear2 = nn.Linear(d_ff, d_model)self.gelu = nn.GELU()nn.init.normal_(self.linear1.weight, std=0.02)nn.init.normal_(self.linear2.weight, std=0.02)def forward(self, inputs):# |inputs| : (batch_size, seq_len, d_model)outputs = self.gelu(self.linear1(inputs))# |outputs| : (batch_size, seq_len, d_ff)outputs = self.linear2(outputs)# |outputs| : (batch_size, seq_len, d_model)return outputsclass DecoderLayer(nn.Module):def __init__(self, d_model, n_heads, d_ff, attn_pdrop, resid_pdrop):super(DecoderLayer, self).__init__()self.mha = MultiHeadAttention(d_model, n_heads, attn_pdrop)self.dropout1 = nn.Dropout(resid_pdrop)self.layernorm1 = nn.LayerNorm(d_model, eps=1e-5)self.ffn = PositionWiseFeedForwardNetwork(d_model, d_ff)self.dropout2 = nn.Dropout(resid_pdrop)self.layernorm2 = nn.LayerNorm(d_model, eps=1e-5)def forward(self, inputs, attn_mask):# |inputs| : (batch_size, seq_len, d_model)# |attn_mask| : (batch_size, seq_len, seq_len)attn_outputs, attn_weights = self.mha(inputs, inputs, inputs, attn_mask)attn_outputs = self.dropout1(attn_outputs)attn_outputs = self.layernorm1(inputs + attn_outputs)# |attn_outputs| : (batch_size, seq_len, d_model)# |attn_weights| : (batch_size, n_heads, q_len(=seq_len), k_len(=seq_len))ffn_outputs = self.ffn(attn_outputs)ffn_outputs = self.dropout2(ffn_outputs)ffn_outputs = self.layernorm2(attn_outputs + ffn_outputs)# |ffn_outputs| : (batch_size, seq_len, d_model)return ffn_outputs, attn_weightsclass TransformerDecoder(nn.Module):def __init__(self, vocab_size, seq_len, d_model, n_layers, n_heads, d_ff, embd_pdrop, attn_pdrop, resid_pdrop,pad_id):super(TransformerDecoder, self).__init__()self.pad_id = pad_id# layersself.embedding = nn.Embedding(vocab_size, d_model)self.dropout = nn.Dropout(embd_pdrop)self.pos_embedding = nn.Embedding(seq_len + 1, d_model)self.layers = nn.ModuleList([DecoderLayer(d_model, n_heads, d_ff, attn_pdrop, resid_pdrop) for _ in range(n_layers)])nn.init.normal_(self.embedding.weight, std=0.02)def forward(self, inputs):# |inputs| : (batch_size, seq_len)positions = torch.arange(inputs.size(1), device=inputs.device, dtype=inputs.dtype).repeat(inputs.size(0), 1) + 1position_pad_mask = inputs.eq(self.pad_id)positions.masked_fill_(position_pad_mask, 0)# |positions| : (batch_size, seq_len)outputs = self.dropout(self.embedding(inputs)) + self.pos_embedding(positions)# |outputs| : (batch_size, seq_len, d_model)attn_pad_mask = self.get_attention_padding_mask(inputs, inputs, self.pad_id)# |attn_pad_mask| : (batch_size, seq_len, seq_len)subsequent_mask = self.get_attention_subsequent_mask(inputs).to(device=attn_pad_mask.device)# |subsequent_mask| : (batch_size, seq_len, seq_len)attn_mask = torch.gt((attn_pad_mask.to(dtype=subsequent_mask.dtype) + subsequent_mask), 0)# |attn_mask| : (batch_size, seq_len, seq_len)attention_weights = []for layer in self.layers:outputs, attn_weights = layer(outputs, attn_mask)# |outputs| : (batch_size, seq_len, d_model)# |attn_weights| : (batch_size, n_heads, seq_len, seq_len)attention_weights.append(attn_weights)return outputs, attention_weightsdef get_attention_padding_mask(self, q, k, pad_id):attn_pad_mask = k.eq(pad_id).unsqueeze(1).repeat(1, q.size(1), 1)# |attn_pad_mask| : (batch_size, q_len, k_len)return attn_pad_maskdef get_attention_subsequent_mask(self, q):bs, q_len = q.size()subsequent_mask = torch.ones(bs, q_len, q_len).triu(diagonal=1)# |subsequent_mask| : (batch_size, q_len, q_len)return subsequent_maskclass GPT(nn.Module):def __init__(self,vocab_size,seq_len=512,d_model=768,n_layers=12,n_heads=12,d_ff=3072,embd_pdrop=0.1,attn_pdrop=0.1,resid_pdrop=0.1,pad_id=0):super(GPT, self).__init__()self.decoder = TransformerDecoder(vocab_size, seq_len, d_model, n_layers, n_heads, d_ff,embd_pdrop, attn_pdrop, resid_pdrop, pad_id)def forward(self, inputs):# |inputs| : (batch_size, seq_len)outputs, attention_weights = self.decoder(inputs)# |outputs| : (batch_size, seq_len, d_model)# |attention_weights| : [(batch_size, n_heads, seq_len, seq_len)] * n_layersreturn outputs, attention_weightsif __name__ == '__main__':model = GPT(vocab_size=10000)print(model)input = torch.ones(16, 128).long()out = model(input)print(out[0].shape)

看着很长,其实代码很简单,就是翻译这张图:
在这里插入图片描述
首先GPT这个类就是定义了12层transformer的decoder构成的:
在这里插入图片描述
vocab_size是词典的大小,就比如说英文一共有10w个单词,那么vocab_size就是10w。用来配合nn.embedding
模块把单词抽成embedding。
然后每个decoder里面就是对着图写代码了,其中比较核心的就是两个mask:
在这里插入图片描述

  • 第一个mask很好理解,因为句子的长度不一样,比如【good morning】和【nice to meet you】,一个长度是2一个是4,这样两个句子没办法组成训练数据,所以一般会把短的padding一下成【good morning pad pad】这样就长度一样可以组成训练数据了,图上第一个pad mask就是用于【good morning pad pad】这个里面那些是pad的部分,然后不参与self attention的计算。
  • 第二个mask就是之前我困惑的地方为啥叫decoder,decoder用的是带mask的MHA,这个mask就是图上的第二个框,他把某个单词后的单词都进行的mask。举个例子,还是【nice to meet you】,对于nice单词它的mask就是【0,1,1,1】,对于meet单词,它的mask就是【0,0,0,1】,这样从左往右相当于去了全1矩阵的上三角的1,所以这里的mask用pytorch的triu实现的:
    subsequent_mask = torch.ones(bs, q_len, q_len).triu(diagonal=1)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/21596.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

生成式AI管理规则落地 大模型后时代到来

国家网信办等七部门联合颁布的《生成式人工智能服务管理暂行办法》,给中国生成式AI产业树立了发展规范。 这份监管文件的用意并不止于管控,还用大量的笔墨传递出推动产业发展的原则,尤其强调“鼓励生成式人工智能技术在各行业、各领域的创新…

摄影师没了?!生成式人工智能即将降维打击摄影行业

本文是Mixlab无界社区成员的投稿: 滚石 deepfacelab和deepfacelive项目组成员 摄影师失业了??怎么说? # # 你还以为AI绘画影响的只是插画师行业吗?错了,摄影行业也即将面临技术洗牌。话不多说,先…

AIGC绘就无限可能的元宇宙

随着科技的飞速发展,我们正逐渐步入一个由虚拟和现实交织构成的全新时代。元宇宙(Metaverse)作为这个新时代的象征,正在成为一个重要的热点。而人工智能生成内容(AIGC)技术的结合,将无疑会推动元…

开发者出海合规手册;@levelsio独立开发月入20万解析;MJ+AR设计珠宝;SD算法原理-通俗版 | ShowMeAI日报

👀日报&周刊合集 | 🎡生产力工具与行业应用大全 | 🧡 点赞关注评论拜托啦! 🤖 独立开发者必看,出海应用开发者合规手册 这是 JourneymanChina 多年出海经验教训的总结,适用于Google Play 以…

ChatGPT唤醒AI游戏?

配图来自Canva可画 “七天制作新游戏”、“AI全自动完成所有游戏!”......继各种AI绘画、AI合成照片、视频之后,AI在游戏领域开启了新一场狂欢。 长久以来,游戏和AI一直有着“相互扶持”的亲密关系——一边是游戏充当AI科研基地&#xff0c…

网易的“草长莺飞二月天”:增长稳健,加码研发,逐浪AI

2月23日,网易发布了2022年第四季度财报。 这是网易与暴雪分道扬镳后的首份财报,加上近期AIGC热度扩散至游戏、教育等各个领域,网易第四季度业绩及其对于GPT等热门技术的探索受到市场关注。 根据财报,第四季度,网易营…

「经济理财」32堂你能听懂的理财课

之前学了一下基金投资课程,作为以后财富管理的积累,可以出门右转看「银行螺丝钉的基金投资课」。但还是觉得应该系统了解一下理财,从小白到理财达人,我需要半年来学习和实践,比较好的是接触到简七理财,结合…

[AI医学] 医学领域几个微调预训练大模型的项目

关键词:AI医学,医学大模型,指令微调,PubMed 文章目录 医学微调大模型1. MedicalGPT-zh2. DoctorGLM3. Huatuo-Llama-Med-Chinese & ChatGLM-Med 医学预训练语言模型1. BioMedLM (2.7B)2. PMC-LLaMA (7B)3. BioMedGPT (1.6B) 总…

程序员专属对联

请欣赏“程序猿春节对联集锦”: 对联一 上联:上拜图灵只佑服务可用 下联: 下跪关公但求永不宕机 横批:风调码顺 风调雨顺 上拜图灵只佑服务可用 下跪关公但求永不宕机 对联二 上联:屏中创造繁华世 下联:指尖…

Node接入ChatGPT 的最强对手Claude

由于个人的chatGPT免费版本即将到期, Claude 很火,在网上被说成是 ChatGPT 的最强对手,是 ChatGPT 的替代品。本文我将介绍下 Claude 是什么,以及如何免费使用 Claude. 什么是Claude 看一下它是如何自我介绍的 Slack Slack 是一款流行的团…

读《EMOQ-TTS: EMOTION INTENSITY QUANTIZATION FOR FINE-GRAINED CONTROLLABLE EMOTIONAL TEXT-TO-SPEECH》

0 Abstract 虽然近年来文本到语音(TTS)的研究取得了显著进展,但仍局限于情感语音合成。为了产生情感话语,大多数作品都利用了从情感标签或参考音频中提取的情感信息。然而,由于话语层面的情绪条件,它们导致了单调的情绪表达。在本…

专家担心 ChatGPT 很快会被用于毁灭性的网络攻击

听到这个新闻,我是挺震惊的,​ChatGPT 近几个月来风靡全球,但就在它以其技术能力让人们惊叹的同时,也有人对其潜在的滥用提出了担忧。 现在,似乎一些 IT 领导者担心它将很快被用于重大网络攻击,并有可能在未…

英文润色网站-英文质量改写改进软件

英文改写软件 英文改写软件是一种全新的工具,它可以方便快捷地对不同语种的图文内容进行批量改写和转换,包括但不限于英语、法语、德语、中文等。无论用户需要将哪种语言的文章进行改写和转换,都可以轻松实现。该软件支持任何文档格式和文本…

OpenAI Translator Bob Plugin Bob上一款翻译、润色、语法修改插件

OpenAI Translator Bob Plugin 一款可以在Bob进行即时翻译的插件。它基于 OpenAI 的 GPT 系列模型,能够提供高质量、准确的翻译服务。该插件支持多种语言的翻译,包括中文、英文、法语、德语、日语等。用户只需在页面中选中需要翻译的文本,然…

pg数据库数据导出

首先得在postgresql的安装包下找到bin目录,找到路径。其次在cmd下面,输入导出路径: 导出数据库的命令: > pg_dump -U postgres -h ip地址 数据库名> f:\data\数据库名.dump >口令:密码

如何进行数据的导出?

如何进行数据的导出? 以前有进行过填写资料并且把资料导出Excel表格,当时就觉得好神奇,又想知道这样的功能是怎么实现的,可是那时的头脑简单,没有知道答案,可是现在我终于知道为什么可以直接导出数据了&am…

图像搜索:以图搜图

以图搜图 随着数字时代的到来,单单的文字搜素已经无法满足人们的搜索了,图像搜索,甚至是视频搜索都已经比较成熟。本文大致讲解下图像搜索: 发展历程 原理 搜索项目:主要分为三个部分——图像特征抽取,构…

图片搜索引擎网站大全,以图搜图网站

当我们需要搜索一些图片的时候使用图片搜索引擎网站可以帮我们更快地找到自己需要的图片,那么有哪些图片搜索引擎网站可以搜索图片呢?下面小编就来和大家分享几个以图搜图的网站。 1.百度图片搜索引擎网站 百度是最大的中文搜索引擎,百度的图…

查找照片的来源

想要知道照片的来源,可以使用百度识图或其他识图工具,但得到的信息可能不多,不过还可以通过多种手段获取更多信息。 以以下照片为例,查找是哪家麦当劳。 (1).进入电脑pc端,右键单击照片&#xf…

如何使用谷歌“以图找图”图片搜索功能

谷歌不愧为搜索界的大佬,谷歌在前几个月开放了一个新功能,叫做“图像搜索”,也就是说,可以用图片搜索到图片,图片可以是网络链接的,也可以是上传的。有了这个功能后,人肉搜索 又上了一个新的层次…