[预训练语言模型专题] 结合HuggingFace代码浅析Transformer

栏目: IT技术 · 发布时间: 5年前

[预训练语言模型专题] 结合HuggingFace代码浅析Transformer

本文为预训练语言模型专题系列第九篇

快速传送门     

1-4:[萌芽时代]、 [风起云涌][文本分类通用技巧] [GPT家族]

5-8:[BERT来临]、 [浅析BERT代码][ERNIE合集] 、[ MT-DNN(KD) ]

感谢清华大学自然语言处理实验室对 预训练语言模型架构 的梳理,我们将沿此脉络前行,探索预训练语言模型的前沿技术,红框中为已介绍的文章,本期将结合HuggingFace代码浅析Transformer代码,欢迎大家留言讨论交流。

[预训练语言模型专题] 结合HuggingFace代码浅析Transformer

1

前言

前面几期一起分享了这么多基于 Transformer 的预训练语言模型,本期想和大家一起来结合代码复习一下Transformer。它是目前state-of art 语言模型中最核心的模块,替代RNN成为NLP的柱石。

我在分享中会引用HuggingFace Transformers包中的代码,主要是BertAttention的相关代码,希望大家也能有所收获。

2

Attention Is All You Need(2017)

以前,处理NLP时序序列的关键模块是循环神经网络RNN(LSTM)或者卷积神经网络CNN。但是它们都有各自的问题。比如RNN无法进行并行计算,训练速度较慢,而且梯度传递有困难,容易梯度爆炸或消失。而卷积神经网络难以捕捉长距离的语义。所以,这篇文章提出了一种新的简单网络结构,称为Transformer,单纯基于attention的机制,既能并行计算提高训练速度,还能够捕捉句中的长序文本内部的联系。

直接上结构图:

[预训练语言模型专题] 结合HuggingFace代码浅析Transformer

Encoder-decoder

首先它是一个encoder-decoder的结构。从设计上看,左边的inputs会被encode成向量表示z,输入给右边decoder(encoder上方流出)。在解码的时候,decoder会结合z和outputs中某token之前的token来生成当前的token,是比较典型的自回归模型。我们分别说说它的encoder以及decoder。

  • Encoder:

    首先在Transformer的encoder里有六层,每一层都是图中这样的两个sublayer。第一个sublayer是一个Multi-Head Attention,第二个sublayer是feed forward layer。在这两个sublayer之间都有 残差连接和层归一化

  • Decoder:

    decoder也是六层,比起encoder有两个变化,一是第一个sublayer的multi-head attention需要进行mask,因为作为一个自回归模型在decode的时候,每个词的生成时,后面的词还没有生成出来,所以attention只能看到前面的词,后面的需要被mask掉。二是中间插了一个新层来 计算encoder传来的向量与output向量的attention

Attention

Transformers的精华就是Attention,接下来会结合论文和代码来介绍 attention 的基本概念和用法。

[预训练语言模型专题] 结合HuggingFace代码浅析Transformer

上图左侧的叫做 Scaled Dot-Product Attention 计算的公式可以表示为下图,Q和K两矩阵相乘后进行scale,scale的因子dk为单个头的维度,也即是上述代码中的attention_head_size,矩阵乘V得到Attention的向量表达。

[预训练语言模型专题] 结合HuggingFace代码浅析Transformer

这里我们结合Transformers这个包BertSelfAttention类的代码来具体讨论 。首先定义三个矩阵 query, key, value。参数量和hidden_size和 head的数量有关,关于head我们后面再提。L为文本长度。

# 头的数量,以及每个头的size

self.num_attention_heads = config.num_attention_heads

self.attention_head_size = int(config.hidden_size / config.num_attention_heads)

self.all_head_size = self.num_attention_heads * self.attention_head_size

# 三个变换矩阵

self.query = nn.Linear(config.hidden_size, self.all_head_size)

self.key = nn.Linear(config.hidden_size, self.all_head_size)

self.value = nn.Linear(config.hidden_size, self.all_head_size)

这里定义的三个矩阵,实际上是要将某句文本的hidden_states变换成Q, K, V的表示,下面的代码中是具体的变换和计算。

# 将x从(batch_size, L, all_head_size)变为(batch_size, num_heads, L, attention_size)

def transpose_for_scores(self.x):

new_x_shape = x.size()[:-1] + (self.num_attention_heads, self.attention_head_size)

x = x.view(*new_x_shape)

return x.permute(0, 2, 1, 3)

# 对hidden_states进行三种变换,形成Q, K, V

mixed_query_layer = self.query(hidden_states)

mixed_key_layer = self.key(hidden_states)

mixed_value_layer = self.value(hidden_states)


query_layer = self.transpose_for_scores(mixed_query_layer)

key_layer = self.transpose_for_scores(mixed_key_layer)

value_layer = self.transpose_for_scores(mixed_value_layer)

# Q和K相乘得到本文自注意力的评分

attention_scores = torch.matmul(query_layer, key_layer.transpose(-1, -2))

attention_scores = attention_scores / math.sqrt(self.attention_head_size)

if attention_mask is not None:

attention_scores = attention_scores + attention_mask


# Normalize the attention scores to probabilities.

attention_probs = nn.Softmax(dim=-1)(attention_scores)


# This is actually dropping out entire tokens to attend to, which might

# seem a bit unusual, but is taken from the original Transformer paper.

attention_probs = self.dropout(attention_probs)


# Mask heads if we want to

if head_mask is not None:

attention_probs = attention_probs * head_mask

# softmax过的attention_prob乘V得到Attention的表示向量

context_layer = torch.matmul(attention_probs, value_layer)


结合上面代码中,我们可以观察到

  1. hidden_states的shape是(batch_size, L, hidden_size) 。为文本产生的向量表示如Embedding。

  2. 我们通过query矩阵乘hidden_state得到mixed_query_layer (batch_size, L, all_head_size)

  3. 经过 transpose变化成为query_layer(batch_size, num_heads, L, attention_head_size) 得到上图中的 Q

  4. 同样的 key_layer(上图中K)的shape为(batch_size, num_heads, L, attention_head_size), 最后两维包括文本长度的维度进行了矩阵相乘,所以attention_scores维度变为(batch_size, num_heads, L, L)

  5. attention_score 经过softmax ,长度方向归一化了,乘于value变为context_layer(batch_size, num_heads, L, attention_head_size)

所以Q(query) ,K(key),V(value) 都是由原来文本向量乘于对应矩阵得到。这三种变换的矩阵参数都是我们需要通过训练学习。Q矩阵乘K以后,得到(batch_size, num_heads, L, L)的矩阵,我理解为文本的每个位置和其他位置都相乘得出一个数值,这个数值我们可以看作文本的每个token和其他token的相关度,即为self attention的 score ,越大一般这两个token关系就越密切,softmax以后变成一个0-1的数,这时候score再矩阵乘value我们就可以得到一个上下文相关向量的attention表示了。

前面还提到了 Multi-Head Attention ,多头注意力。相比于进行一次attention function,进行h次效果会更好。也就是说,我们会初始化h个不同的query, key, value矩阵,每个大小为(hidden_state, attention_head_size), 在上面代码中,我们实际上初始了一个(hidden_state, attention_head_size * num_heads) 大小的矩阵,与num_heads(h)个单头的attention矩阵是一致的,矩阵中其实参数是单头的num_heads份。然后每份参数去进行上面的attention运算,最后把多份的attention 拼接起来成为了最终的multi-head attention。

Positional Encoding

Attention机制让Transformer 得以能够建立长距离的语义关联,但是我们可以注意到,在encoder和decoder中,我们用的都是fully connected layer,所以每个位置的token都是独立的,你会失去语序的信息。所以有必要告诉网络,token之间的相对或绝对信息,所以文章引入了 Positional Encoding

[预训练语言模型专题] 结合HuggingFace代码浅析Transformer

pos是位置,i是Embedding的某个维度, 2i指的偶数维度的Embedding, 2i+1指的是奇数维度的Embedding。i 是从 0到 dmodel / 2 ,所以对不同层的Embedding,sin和cos函数的波长是从 2pi 到 20000 pi。对于固定的i,  pos变化就会引起Embedding以正弦或余弦变化。这样encode了以后,模型就能去对相对的位置进行建模。

Visualizations

Attention的另外一个好处是, 可视化和可解释性 加强了。我们从下图可以看到masking这个词,它主要和周围的词产生比较强的联系,尤其是和more difficult关系较大,这个是比较合理。我们还可以看到的是不同颜色代表不同的是不同的头,不同头的结果其实差别挺大的,这也是为什么多头注意力能带来收益的原因。

[预训练语言模型专题] 结合HuggingFace代码浅析Transformer

从下面这张图,我们可以看到attention基本可以捕捉句子的结构。

[预训练语言模型专题] 结合HuggingFace代码浅析Transformer

最后,作者比较了不同任务上Transformer的效果,我就贴出在机器翻译上的结果,显示Transformer确实在效果和效率上都有所提升。

[预训练语言模型专题] 结合HuggingFace代码浅析Transformer

未完待续

本期的论文就给大家分享到这里,感谢大家的阅读和支持,下期我们会给大家带来其他预训练语言模型的介绍,敬请大家期待!

推荐阅读

AINLP年度阅读收藏清单

百度PaddleHub NLP模型全面升级,推理性能提升50%以上

斯坦福大学NLP组 Python 深度学习自然语言处理工具Stanza试用

数学之美中盛赞的 Michael Collins 教授,他的NLP课程要不要收藏?

自动作诗机&藏头诗生成器:五言、七言、绝句、律诗全了

From Word Embeddings To Document Distances 阅读笔记

模型压缩实践系列之——bert-of-theseus,一个非常亲民的bert压缩方法

这门斯坦福大学自然语言处理经典入门课,我放到B站了

可解释性论文阅读笔记1-Tree Regularization

征稿启示 | 稿费+GPU算力+星球嘉宾一个都不少

关于AINLP

AINLP 是一个有趣有AI的自然语言处理社区,专注于 AI、NLP、机器学习、深度学习、推荐算法等相关技术的分享,主题包括文本摘要、智能问答、聊天机器人、机器翻译、自动生成、知识图谱、预训练模型、推荐系统、计算广告、招聘信息、求职经验分享等,欢迎关注!加技术交流群请添加AINLPer(id:ainlper),备注工作/研究方向+加群目的。

[预训练语言模型专题] 结合HuggingFace代码浅析Transformer


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Java程序员修炼之道

Java程序员修炼之道

[英] Benjamin J. Evans、[荷兰] Martijn Verburg / 吴海星 / 人民邮电出版社 / 2013-7 / 89.00元

本书分为四部分,第一部分全面介绍Java 7 的新特性,第二部分探讨Java 关键编程知识和技术,第三部分讨论JVM 上的新语言和多语言编程,第四部分将平台和多语言编程知识付诸实践。从介绍Java 7 的新特性入手,本书涵盖了Java 开发中最重要的技术,比如依赖注入、测试驱动的开发和持续集成,探索了JVM 上的非Java 语言,并详细讲解了多语言项目, 特别是涉及Groovy、Scala 和Cl......一起来看看 《Java程序员修炼之道》 这本书的介绍吧!

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具