作者博客:@Jay Alammar
原文链接:The Illustrated GPT-2 (Visualizing Transformer Language Models) – Jay Alammar – Visualizing machine learning one concept at a time. (jalammar.github.io)
这是我补充的内容。
it单词的时候。
接下来我们详细介绍一下这一过程是如何实现的。
注意,接下来的图解过程会用到很多 “向量” 来图解算法机制,而实际实现中是使用 矩阵 进行计算的。这个分析过程是想让读者了解在处理过程中每个单词发生了什么,因此本文的重点是单词级(word-level)处理逻辑进行解析。
1. 创建Query、Key、Value
现在我们只关注第一个路径,我们需要用它的Query和所有的Key比较,这一步骤会为每个路径都生成一个注意力分数。
先不管什么是多头注意力,先看一个head 的情况。自注意力计算的第一步就是要计算出每个路径的Query、Key、Value三个向量。
- 看一下下图是一次处理四个tokens,每个token都有它单独的路径,第一路径指的是$X_1$这个token。
- 对于每个词来说对应的QKV是一个向量,而在实际计算中是使用整个输入序列的矩阵。
- 获得Query、Key、Value三个向量的方法是$每个单词的表示向量×对应的权重矩阵(W^Q、W^K、W^V)$。
2. 计算注意力分数
现在我们已经有了那三个向量,在第二步我们只需要用到query和key向量。因为我们关注的是第一个token,所以我们将其第一个token的query乘以其他token的key向量,这样计算会得到每一个token的注意力分数。
这里是两个向量做点乘积,不是按位乘。
3. 求和
我们现在可以将上一步得到的注意力分数乘以Value向量。将相乘之后的结果加起来,那些注意力分数大的占比会更大。
看下图,注意力分数乘以每个Value向量,原作者用不同深浅的蓝色的框框表示计算之后的结果。可以看到$V_3$比较显眼,$V_2$几乎看不到了,然后将计算结果加起来得到$Z_1$。这个$Z_1$就是$X_1$新的表示向量,这个向量除了单词本身,还涵盖了上下文其他token的信息。 这一过程可以认为注意力分数就是求不同单词重要性权重的过程,这一步的计算就是求所有token的加权和。
对于Value向量,注意力分数越低,颜色越透明。这是为了说明乘以一个小数如何稀释不同token的Value向量。
如果我们对每个路径进行相同的操作,最终会得到每个token新的表示向量,其中包含该token的上下文信息。之后会将这些数据传给encoder组件的下一个子层(前馈神经网络):
这种屏蔽通常以矩阵的形式实现,称为注意力屏蔽(attention mask)。
还是假设输入序列由四个单词组成,例如robot must obey orders。在语言建模场景中,这个序列包含四个处理步骤,每个单词一个步骤(假设现在每个单词都是一个token)。由于模型是按照批量(batch)进行处理的,我们可以假设这个模型的批量大小为4(batch_size = 4),然后模型将把整个序列作为一个batch处理进行四步处理。
假设现在每个单词都是一个token,这个假设是因为单词word ≠ token,在不同的分词方式中同一个单词可能会划分为不同的token。
在矩阵形式中,我们通过将Query矩阵乘以Key矩阵来计算注意力分数。让我们像下面这样进行可视化,注意,单词无法直接进行矩阵运算,所以要把他们的Query和Key丢到矩阵中。
完成乘法运算后,我们要加上上三角形式的mask矩阵。它会将我们想要屏蔽的单元格设置为$-∞$或一个非常大的负数(GPT-2中的为负一亿):
然后,对每一行进行softmax就会转化成我们需要的注意力分数:
这个分数表的含义如下:
robot,它的注意力将100%集中在这个单词上。
robot must,当它处理单词“must”时,48%的注意力会放在robot上,52%的注意力会放在must上。
作者意思是比如假设我们处理输入序列的第一个tokena robot must obey the rule,如果第一次迭代时候只有a,仅需要计算它的QKV,第二次迭代时候是a robot,如果直接算二者的QKV,那就是重复计算了a的,这样会造成巨大的计算开销。 GPT-2的高效处理方法如下:
a时(暂时忽略<s>)。
GPT-2会保留atoken的Key和Value向量。每个自注意力层都有各自的Key和Value向量,不同的decoder组件中Key和Value向量不共享:
在下一次迭代中,当模型处理单词robot时,它不需要为a重新生成Query、Key、Value,而是直接用第一次迭代中保存的那些:
it。如果我们讨论的是最底层的decoder组件,那么它接收的token的输入是token的嵌入+ 第九个位置的位置编码:
Transformer中的每个组件之权重不共享,都有自己的权重。我们首先要和权重矩阵进行计算,我们使用权重矩阵创建Query、Key、Value。
自注意力子层会将输入乘以权值矩阵(还会加上bias,图中没表示出来),乘法会产生一个向量,这个向量是单词it的Query、Key、Value的拼接向量。
将输入向量乘以注意力权重向量(然后添加一个偏差向量),就会得到这个token的Query、Key、Value向量。
前边的例子中我们已经了解了一个注意力头怎么计算,现在我们考虑一下多头注意力,如下图考虑有三个head。
现在,该token可以针对其他token的所有Value进行评分:
但是这个拼接结果向量还不能传给下一个子层。
我们首先需要把这个拼接向量转换成对齐表示。
作者原文写的“We need to first turn this Frankenstein’s-monster of hidden states into a homogenous representation.” 直译是“我们需要首先把这个隐藏状态的弗兰肯斯坦怪物变成对齐的表示。” 弗兰肯斯坦是一个人造人,是个怪物,作者是玛丽·雪莱,这本书可以看作是科幻小说开山之作。感兴趣的可以看一下。
之后我们就产生了可以发送到下一层的向量:
GPT-2 全连接神经网络第一层
全连接神经网络的输入是自注意力层的输出,用于处理自注意力子层得到的token的新的表示,这个表示包含了原始token及其上下文的信息。
它由两层组成。第一层是模型大小的4倍(因为GPT-2 small是768,所以GPT-2中的全连接神经网络第一层会将其投影到768*4 = 3072个单位的向量中)。为什么是四倍?因为原始Transformer的也是四倍,这里就没改。
上图没画出bias。
GPT-2 全连接神经网络第二层:投影到模型维度
第二层将第一层的结果再投射回模型的维度(GPT-2 small为768)。这个计算结果就是整个decoder组件对token的处理结果。
上图没画出bias。
每个Transformer组件都有自己的权重。另外,该模型只有一个token的嵌入矩阵和一个位置编码矩阵:
如果你想看到模型的所有参数,我在这里对它们进行了统计:
由于某种原因,它们加起来有124M的参数,而不是117M。我不知道为什么,但这就是在发布的代码中它们的数量(如果我错了欢迎指正)。
上图中博客作者对GPT-2 small的参数进行了统计,计算结果和OpenAI开源的GPT-2模型的参数量不一样。 作者算的是124M,实际代码中只有117M, 原因如下: OpenAI团队说:“我们论文里参数计算方法写错了。所以你现在可以看到GPT-2 small模型参数只有117M……”截图来源https://github.com/openai/gpt-2
我正在使用i18n从头开始构建一个多语言网络应用程序,虽然我自己可以处理一大堆yml文件,但我说的语言(非常)有限,最终我想寻求外部帮助帮助。我想知道这里是否有人在使用UI插件/gem(与django上的django-rosetta不同)来处理多个翻译器,其中一些翻译器不愿意或无法处理存储库中的100多个文件,处理语言数据。谢谢&问候,安德拉斯(如果您已经在rubyonrails-talk上遇到了这个问题,我们深表歉意) 最佳答案 有一个rails3branchofthetolkgem在github上。您可以通过在Gemfi
作为新的阿里云用户,您可以50免费试用多种优惠,价值高达1,700美元(或8,500美元)。这将让您了解和体验阿里云平台上提供的一系列产品和服务。如果您以个人身份注册免费试用,您将获得价值1,700美元的优惠。但是,如果您是注册公司,您可以选择企业免费试用,提交基本信息通过企业实名注册验证,即可开始价值$8,500的免费试用!本教程介绍了如何设置您的帐户并使用您的免费试用版。关于免费试用在我们开始此试用之前,您还必须遵守以下条款和条件才能访问您的免费试用:只有在一年内创建的账户才有资格获得阿里云免费试用。通过此免费试用优惠,用户可以免费试用免费试用活动页面上列出的每种产品一次。如果您有多个帐
很高兴看到google代码:google-api-ruby-client项目,因为这对我来说意味着Ruby人员可以使用GoogleAPI-s来完善代码。虽然我现在很困惑,因为给出的唯一示例使用Buzz,并且根据我的实验,Google翻译(v2)api的行为必须与google-api-ruby-client中的Buzz完全不同。.我对“Explorer”演示示例很感兴趣——但据我所知,它并不是一个探索器。它所做的只是调用一个Buzz服务,然后浏览它已经知道的关于Buzz服务的事情。对我来说,Explorer应该让您“发现”所公开的服务和方法/功能,而不一定已经知道它们。我很想听听使用这个
如果特定语言环境中缺少翻译,如何配置i18n以使用en语言环境翻译?当前已插入翻译缺失消息。我正在使用RoR3.1。 最佳答案 找到相似的question这里是答案:#application.rb#railswillfallbacktoconfig.i18n.default_localetranslationconfig.i18n.fallbacks=true#railswillfallbacktoen,nomatterwhatissetasconfig.i18n.default_localeconfig.i18n.fallback
在使用rails4和https://github.com/globalize/globalize的情况下,我应该如何为我的模型编写表单?用于翻译。我想以一种形式显示所有翻译,如下例所示。我在这里找到了解决方案https://github.com/rilla/batch_translations但我不知道如何实现它。这个“批量翻译”是一个gem还是什么?以及如何安装它。EditingpostEnglish(defaultlocale)SpanishtranslationFrenchtranslation 最佳答案 批处理翻译gem很旧
我有以下python函数来递归查找集合的所有分区:defpartitions(set_):ifnotset_:yield[]returnforiinxrange(2**len(set_)/2):parts=[set(),set()]foriteminset_:parts[i&1].add(item)i>>=1forbinpartitions(parts[1]):yield[parts[0]]+bforpinpartitions(["a","b","c","d"]):print(p)有人可以帮我把它翻译成ruby吗?这是我目前所拥有的:defpartitions(set)ifnots
所以我知道如果我在读取yaml文件时遇到“翻译缺失:”如何返回默认值。some=I18n.t("something.something_else",default:"value")但是如果我希望默认值为nil,我该如何以Ruby的方式做到这一点呢?我知道我可以正则表达式并匹配变量some中的“translationmissing:”,如果它匹配,我会将它分配给nil。但我想做的是拥有some=I18n.t("something.something_else",default:nil)但它只是返回了我缺少的翻译。有谁知道好的方法吗? 最佳答案
我正在使用Ruby-Tk为OSX开发一个桌面应用程序,我想为该应用程序提供一个AppleEvents接口(interface)。这意味着应用程序将定义它将响应的AppleScript命令的字典(对应于发送到应用程序的Apple事件),并且用户/其他应用程序可以使用AppleScript命令编写Ruby-Tk应用程序的脚本。其他脚本语言支持此类功能——Python通过位于http://appscript.svn.sourceforge.net/viewvc/appscript/py-aemreceive/的py-aemreceive库和Tcl通过位于http://tclae.source
有人知道如何在Rails中翻译模型关联吗?例如:我有一个Person模型,它可以有很多Phone。但是,一个人需要至少有一部电话。我无法翻译该验证。我能做的最好的是:validates_presence_of:phones,:message=>"Atleastonephoneisrequired."在我的YAML上,我替换了这一行以省略%{attribute}:format:!'%{message}'这样只显示我的消息,我避免显示未翻译的字段名称。这让我很头疼,因为有些gems根本不允许我传递:message=>"somethingdescribingtheerror",所以我想配置所
我创建了一个gem(TranslationsGem),我在多个项目(一个引擎和一个Rails应用程序)中使用它。这个gem设置了几个哈希值,这些哈希值被加载到I18n后端。#store_dynamic_translations方法设置了几个哈希,这些哈希被加载到I18n后端。它基本上是这样工作的:I18n.backend.store_translations(:en,{test:{property:'value'}})我的测试确认方法和翻译加载工作正常。但是我无法让它在主机引擎和Rails应用程序中工作。在我的测试环境中,我必须在我的test_helper中执行该方法,以确保正确加载翻