乐趣区

关于人工智能:深度学习进阶篇预训练模型1预训练分词SubwordELMoTransformer模型原理结构技巧以及应用详解

深度学习进阶篇 - 预训练模型[1]:预训练分词 Subword、ELMo、Transformer 模型原理; 构造; 技巧以及利用详解

从字面上看,预训练模型(pre-training model)是先通过一批语料进行训练模型,而后在这个初步训练好的模型根底上,再持续训练或者另作他用。这样的了解基本上是对的,预训练模型的训练和应用别离对应两个阶段:预训练阶段(pre-training)和 微调(fune-tuning)阶段。

预训练阶段个别会在超大规模的语料上,采纳无监督(unsupervised)或者弱监督(weak-supervised)的形式训练模型,冀望模型可能取得语言相干的常识,比方句法,语法常识等等。通过超大规模语料的”洗礼”,预训练模型往往会是一个 Super 模型,一方面体现在它具备足够多的语言常识,一方面是因为它的参数规模很大。

微调阶段是利用预训练好的模型,去定制化地训练某些工作,使得预训练模型”更懂”这个工作。例如,利用预训练好的模型持续训练文本分类工作,将会取得比拟好的一个分类后果,直观地想,预训练模型曾经懂得了语言的常识,在这些常识根底下来学习文本分类工作将会事倍功半。利用预训练模型去微调的一些工作 (例如前述文本分类) 被称为上游工作(down-stream)。

以 BERT 为例,BERT 是在海量数据中进行训练的,预训练阶段蕴含两个工作:MLM(Masked Language Model)和 NSP (Next Sentence Prediction)。前者相似”完形填空”,在一句中扣出一个单词,而后利用这句话的其余单词去预测被扣出的这个单词;后者是给定两句话,判断这两句话在原文中是否是相邻的关系。

BERT 预训练实现之后,后边能够接入多种类型的上游工作,例如文本分类,序列标注,浏览了解等等,通过在这些工作上进行微调,能够取得比拟好的试验后果。

1. 预训练分词 Subword

1.1Subword 介绍

1.1.1 分词器是做什么的?

机器无奈了解文本。当咱们将句子序列送入模型时,模型仅仅能看到一串字节,它无奈晓得一个词从哪里开始,到哪里完结,所以也不晓得一个词是怎么组成的。所以,为了帮忙机器了解文本,咱们须要

  1. 将文本分成一个个小片段
  2. 而后将这些片段示意为一个向量作为模型的输出
  3. 同时,咱们须要将一个个小片段(token) 示意为向量,作为词嵌入矩阵,通过在语料库上训练来优化 token 的示意,使其蕴含更多有用的信息,用于之后的工作。

1.1.2 为什么须要分词?

在 NLP 工作中,神经网络模型的训练和预测都须要借助词表来对句子进行示意。传统结构词表的办法,是先对各个句子进行分词,而后再统计并选出频数最高的前 N 个词组成词表。通常训练集中蕴含了大量的词汇,以英语为例,总的单词数量在 17 万到 100 万左右。出于计算效率的思考,通常 N 的选取无奈蕴含训练集中的所有词。因此,这种办法结构的词表存在着如下的问题:

  • 理论利用中,模型预测的词汇是凋谢的,对于未在词表中呈现的词(Out Of Vocabulary, OOV),模型将无奈解决及生成;
  • 词表中的低频词 / 稠密词在模型训练过程中无奈失去充沛训练,进而模型不能充沛了解这些词的语义;
  • 一个单词因为不同的状态会产生不同的词,如由”look”衍生出的”looks”,“looking”,“looked”,显然这些词具备相近的意思,然而在词表中这些词会被当作不同的词解决,一方面减少了训练冗余,另一方面也造成了大词汇量问题。

一种解决思路是应用字符粒度来示意词表,尽管可能解决 OOV 问题,但单词被拆分成字符后,一方面失落了词的语义信息,另一方面,模型输出会变得很长,这使得模型的训练更加简单难以收敛。

1.1.3 分词办法

分词的办法有很多,次要包含基于空格的分词办法,基于字母的分词办法和基于子词的分词办法,也能够本人设定一些分隔符号或者规定进行分词等等。基于子词的分词办法包含 Byte Pair Encoding (BPE), WordPiece 和 Unigram Language Model。上面的章节会具体介绍这几种办法。

  • 基于空格的分词办法

一个句子,应用不同的规定,将有许多种不同的分词后果。咱们之前罕用的分词办法将空格作为分词的边界。也就是图中的第三种办法。然而,这种办法存在问题,即只有在训练语料中呈现的 token 能力被训练器学习到,而那些没有呈现的 token 将会被 $<UNK>$ 等非凡标记代替,这样将影响模型的体现。如果咱们将词典做得足够大,使其能包容所有的单词。那么词典将十分宏大,产生很大的开销。同时对于呈现次数很少的词,学习其 token 的向量示意也十分艰难。除去这些起因,有很多语言不必空格进行分词,也就无奈应用基于空格分词的办法。综上,咱们须要新的分词办法来解决这些问题。

  • 基于字母的分词办法

将每个字符看作一个词。

  • 长处

不必放心未知词汇,能够为每一个单词生成词嵌入向量示意。

  • 毛病

    • 字母自身就没有任何的外在含意,失去的词嵌入向量不足含意。
    • 计算复杂度晋升(字母的数目远大于 token 的数目)
    • 输入序列的长度将变大,对于 Bert、CNN 等限度最大长度的模型将很容易达到最大值。
  • 基于子词的分词办法

为了改良分词办法,在 $<UNK>$ 数目和词向量含意丰富性之间达到均衡,提出了 Subword Tokenization 办法。这种办法的目标是通过一个无限的单词列表来解决所有单词的分词问题,同时将后果中 token 的数目降到最低。例如,能够用更小的词片段来组成更大的词:

“unfortunately”=“un”+“for”+“tun”+“ate”+“ly”

它的划分粒度介于词与字符之间,比方能够将”looking”划分为”look”和”ing”两个子词,而划分进去的”look”,”ing”又可能用来结构其它词,如”look”和”ed”子词可组成单词”looked”,因此 Subword 办法可能大大降低词典的大小,同时对相近词能更好地解决。

1.2 Byte Pair Encoding (BPE)

BPE 最早是一种数据压缩算法,由 Sennrich 等人于 2015 年引入到 NLP 畛域并很快失去推广。该算法简略无效,因此目前它是最风行的办法。GPT- 2 和 RoBERTa 应用的 Subword 算法都是 BPE。在信号压缩畛域中 BPE 过程可视化如下:

BPE 取得 Subword 的步骤如下:

  1. 筹备足够大的训练语料,并确定冀望的 Subword 词表大小;
  2. 将单词拆分为成最小单元。比方英文中 26 个字母加上各种符号,这些作为初始词表;
  3. 在语料上统计单词内相邻单元对的频数,选取频数最高的单元对合并成新的 Subword 单元;
  4. 反复第 3 步直到达到第 1 步设定的 Subword 词表大小或下一个最高频数为 1。

上面以一个例子来阐明。假如有语料集通过统计后示意为:{‘low’:5,’lower’:2,’newest’:6,’widest’:3},其中数字代表的是对应单词在语料中的频数。

1)拆分单词成最小单元,并初始化词表。这里,最小单元为字符,因此,可失去

<p> 语料 </p> <p> 词表 </p>
<p>‘low</w>’:5‘lower</w>’:2‘newest</w>’:6‘widest</w>’:3</p> <p>l,o,w,e,r,n,s,t,i,d,</w></p>

须要留神的是,在将单词拆分成最小单元时,要在单词序列后加上”</w>”(具体实现上能够应用其它符号)来示意停止符。在子词解码时,停止符能够辨别单词边界。

2)在语料上统计相邻单元的频数。这里,最高频间断子词对”e”和”s”呈现了 6 +3= 9 次,将其合并成”es”,有

<p> 语料 </p> <p> 词表 </p>
<p>‘low</w>’:5‘lower</w>’:2‘newest</w>’:6‘widest</w>’:3</p> <p>l,o,w,e,r,n,t,i,d,</w>,’es’</p>

因为语料中不存在’s’子词了,因而将其从词表中删除,然而预料中还存在‘e’的子词,所以 e 还不能删除。同时退出新的子词’es’。一增一减,词表大小放弃不变。

3)持续统计相邻子词的频数。此时,最高频间断子词对”es”和”t”呈现了 6 +3= 9 次, 将其合并成”est”,有

<p> 语料 </p> <p> 词表 </p>
<p>‘low</w>’:5‘lower</w>’:2‘newest</w>’:6‘widest</w>’:3</p> <p>l,o,w,e,r,n,i,d,</w>,est</p>

接着,最高频间断子词对为”est”和”</w>”,有

<p> 语料 </p> <p> 词表 </p>
<p>‘low</w>’:5‘lower</w>’:2‘newest</w>’:6‘widest</w>’:3</p> <p>l,o,w,e,r,n,i,d,est</w></p>
<p> 持续上述迭代直到达到预设的 Subword 词表大小或下一个最高频的字节对呈现频率为 1。</p> <p></p>

从下面的示例能够晓得,每次合并后词表大小可能呈现 3 种变动:

* +1,表明退出合并后的新子词,同时原来的 2 个子词还保留(2 个子词离开呈现在语料中)。

* +0,表明退出合并后的新子词,同时原来的 2 个子词中一个保留,一个被消解(一个子词齐全随着另一个子词的呈现而紧跟着呈现)。

* -1,表明退出合并后的新子词,同时原来的 2 个子词都被消解(2 个子词同时间断呈现)。

实际上,随着合并的次数减少,词表大小通常先减少后减小。

在失去 Subword 词表后,针对每一个单词,咱们能够采纳如下的形式来进行编码:

1. 将词典中的所有子词依照长度由大到小进行排序;

2. 对于单词 w,顺次遍历排好序的词典。查看以后子词是否是该单词的子字符串,如果是,则输入以后子词,并对残余单词字符串持续匹配。

3. 如果遍历完字典后,依然有子字符串没有匹配,则将残余字符串替换为特殊符号输入,如””。

4. 单词的示意即为上述所有输入子词。

解码过程比较简单,如果相邻子词间没有停止符,则将两子词间接拼接,否则两子词之间增加分隔符。

* 长处

能够很无效地均衡词典尺寸和编码步骤数(将句子编码所须要的 token 数量)

* 毛病

* 对于同一个句子, 例如 Hello world,如图所示,可能会有不同的 Subword 序列。不同的 Subword 序列会产生齐全不同的 id 序列示意,这种歧义可能在解码阶段无奈解决。在翻译工作中,不同的 id 序列可能翻译出不同的句子,这显然是谬误的。

* 在训练任务中,如果能对不同的 Subword 进行训练的话,将减少模型的健壮性,可能容忍更多的噪声,而 BPE 的贪婪算法无奈对随机散布进行学习。

## 1.3 WordPiece

Google 的 Bert 模型在分词的时候应用的是 WordPiece 算法。与 BPE 算法相似,WordPiece 算法也是每次从词表中选出两个子词合并成新的子词。与 BPE 的最大区别在于,如何抉择两个子词进行合并:BPE 抉择频数最高的相邻子词合并,而 WordPiece 抉择可能晋升语言模型概率最大的相邻子词退出词表。

假如句子 $S=(t_{1},t_{2},…,t_{n})$ 由 n 个子词组成,$t_{i}$ 示意子词,且假如各个子词之间是独立存在的,则句子 S 的语言模型似然值等价于所有子词概率的乘积:

$$log P(S)=\sum_{i=1}^n logP(t_{i})$$

假如把相邻地位的 x 和 y 两个子词进行合并,合并后产生的子词记为 z,此时句子似然值的变动可示意为:

$$logP(t_{z})-(logP(t_{x})+logP(t_{y}))=log(\frac{P(t_{z})}{P(t_{x})P(t_{y})})$$

从下面的公式,很容易发现,似然值的变动就是两个子词之间的互信息。简而言之,WordPiece 每次抉择合并的两个子词,他们具备最大的互信息值,也就是两子词在语言模型上具备较强的关联性,它们常常在语料中以相邻形式同时呈现。

## 1.4 Unigram Language Model (ULM)

Unigram 模型是 Kudo. 在论文“Subword Regularization: Improving Neural Network Translation Models with Multiple Subword Candidates”中提出的。过后次要是为了解决机器翻译中分词的问题。作者应用一种叫做 marginalized likelihood 的办法来建模翻译问题,思考到不同分词后果对最终翻译后果的影响,引入了分词概率。

与 WordPiece 一样,Unigram Language Model(ULM)同样应用语言模型来筛选子词。不同之处在于,BPE 和 WordPiece 算法的词表大小都是从小到大变动,属于增量法。而 Unigram Language Model 则是减量法, 即先初始化一个大词表,依据评估准则一直抛弃词表,直到满足限定条件。ULM 算法思考了句子的不同分词可能,因此可能输入带概率的多个子词分段。

对于句子 S,$\vec x=(x_{1},x_{2},…,x_{m})$ 为句子的一个分词后果,由 m 个子词组成。所以,以后分词下句子 S 的似然值能够示意为:

$$P(\vec x)=\prod_{i=1}^m{P(x_{i})}$$

对于句子 S,筛选似然值最大的作为分词后果,则能够示意为

$$x^{*}=arg max_{x \in U(x)} P(\vec x)$$

其中 $U(x)$ 蕴含了句子的所有分词后果。在理论利用中,词表大小有上万个,间接列举所有可能的分词组合不具备操作性。针对这个问题,可通过维特比算法失去 $x^*$ 来解决。

那怎么求解每个子词的概率 $P(x_{i})$ 呢?ULM 通过 EM 算法来预计。假如以后词表 V, 则 M 步最大化的对象是如下似然函数:

$$L=\sum_{s=1}^{|D|}log(P(X^{(s)}))=\sum_{s=1}^{|D|}log(\sum_{x \in U(X^{(s)})}P(x))$$

其中,$|D|$ 是语料库中语料数量。上述公式的一个直观了解是,将语料库中所有句子的所有分词组合造成的概率相加。

然而,初始时,词表 V 并不存在。因此,ULM 算法采纳一直迭代的办法来结构词表以及求解分词概率:

1. 初始时,建设一个足够大的词表。个别,可用语料中的所有字符加上常见的子字符串初始化词表,也能够通过 BPE 算法初始化。

2. 针对以后词表,用 EM 算法求解每个子词在语料上的概率。

3. 对于每个子词,计算当该子词被从词表中移除时,总的 loss 升高了多少,记为该子词的 loss。

4. 将子词依照 loss 大小进行排序,抛弃肯定比例 loss 最小的子词(比方 20%),保留下来的子词生成新的词表。这里须要留神的是,单字符不能被抛弃,这是为了防止 OOV 状况。

5. 反复步骤 2 到 4,直到词表大小缩小到设定范畴。

能够看出,ULM 会保留那些以较高频率呈现在很多句子的分词后果中的子词,因为这些子词如果被抛弃,其损失会很大。

* 长处

* 应用的训练算法能够利用所有可能的分词后果,这是通过 data sampling 算法实现的。

* 提出一种基于语言模型的分词算法,这种语言模型能够给多种分词后果赋予概率,从而能够学到其中的噪声。

## 1.5 三种子词分词器的关系

# 2. ELMo

## 2.1. ELMo 简绍

Deep contextualized word representations 取得了 NAACL 2018 的 outstanding paper award,其办法有很大的启发意义。近几年来,预训练的 word representation 在 NLP 工作中体现出了很好的性能,曾经是很多 NLP 工作不可或缺的一部分,论文作者认为一个好的 word representation 须要能建模以下两局部信息:单词的特色,如语义,语法;单词在不同语境下的变动,即一词多义。基于这样的动机,作者提出了 ELMo 模型。ELMo 可能训练进去每个词的 embedding,能够作为上下文相干的词的向量。其余几个奉献:

* 应用字符级别的 CNN 示意。因为单词级别思考数据可能稠密,呈现 OOV 问题,拆成字符后稠密性没有那么强了,刻画的会更好。

* 训练了从左到右或从右到左的语言模型。用这个语言模型输入的后果,间接作为词的向量。

* contextualized:这是一个语言模型,其双向 LSTM 产生的词向量会蕴含左侧上文信息和右侧下文信息,所以称之为 contextualized

* deep:句子中每个单词都能失去对应的三个 Embedding: 最底层是单词的 Word Embedding,往上走是第一层双向 LSTM 中对应单词地位的 Embedding,这层编码单词的句法信息更多一些;再往上走是第二层 LSTM 中对应单词地位的 Embedding,这层编码单词的语义信息更多一些。

上面的章节会具体介绍 ELMo。

### 2.1.1 从 Word Embedding 到 ELMo

Word Embedding:词嵌入。最简略的了解就是:将词进行向量化示意,实体的形象成了数学形容,就能够进行建模,利用到很多工作中。之前用语言模型做 Word Embedding 比拟火的是 word2vec 和 glove。应用 Word2Vec 或者 Glove,通过做语言模型工作,就能够取得每个单词的 Word Embedding,然而 Word Embedding 无奈解决多义词的问题,同一个词在不同的上下文中示意不同的意思,然而在 Word Embedding 中一个词只有一个示意,这导致两种不同的上下文信息都会编码到雷同的 word embedding 空间里去。如何依据句子上下文来进行单词的 Word Embedding 示意。ELMO 提供了解决方案。

咱们有以下两个句子:

* I read the book yesterday.

* Can you read the letter now?

花些工夫思考下这两个句子的区别,第一个句子中的动词“read”是过来式,而第二个句子中的“read”却是当初式,这是一种一词多义景象。

传统的词嵌入会对两个句子中的词“read”生成同样的向量,所以这些架构无奈区别多义词,它们无奈辨认词的上下文。

与之相同,ELMo 的词向量可能很好地解决这种问题。ELMo 模型将整个句子输出方程式中来计算词嵌入。因而,上例中两个句子的“read”会有不同的 ELMo 向量。

## 2.2.ELMo 原理

在此之前的 Word Embedding 实质上是个动态的形式,所谓动态指的是训练好之后每个单词的表白就固定住了,当前应用的时候,不管新句子上下文单词是什么,这个单词的 Word Embedding 不会跟着上下文场景的变动而扭转,所以对于比方 Bank 这个词,它当时学好的 Word Embedding 中混合了几种语义,在利用中来了个新句子,即便从上下文中(比方句子蕴含 money 等词)显著能够看出它代表的是“银行”的含意,然而对应的 Word Embedding 内容也不会变,它还是混合了多种语义。这是为何说它是动态的,这也是问题所在。

ELMO 的实质思维是:我当时用语言模型学好一个单词的 Word Embedding,此时多义词无奈辨别,不过这没关系。在我理论应用 Word Embedding 的时候,单词曾经具备了特定的上下文了,这个时候我能够依据上下文单词的语义去调整单词的 Word Embedding 示意,这样通过调整后的 Word Embedding 更能表白在这个上下文中的具体含意,天然也就解决了多义词的问题了。所以 ELMO 自身是个依据以后上下文对 Word Embedding 动静调整的思路。

ELMo 表征是“深”的,就是说它们是 BiLM 的所有层的内部表征的函数。这样做的益处是可能产生丰盛的词语表征。高层的 LSTM 的状态能够捕获词语以一种和语境相干的特色(比方能够利用在语义消歧),而低层的 LSTM 能够找到语法方面的特色(比方能够做词性标注)。如果把它们联合在一起,会在上游的 NLP 工作中显出劣势。

### 2.2.1 模型构造

ELMO 基于语言模型的,确切的来说是一个 Bidirectional language models,也是一个 Bidirectional LSTM 构造。咱们要做的是给定一个含有 N 个 tokens 的序列。分为以下三步:

1. 第一步:失去 word embedding,即上图的 E。所谓 word embedding 就是一个 n*1 维的列向量,其中 n 示意 embedding 向量的大小;

2. 第二步:送入双向 LSTM 模型中,即上图中的 Lstm;

3. 第三步:将 LSTM 的输入 $h_{k}$,与上下文矩阵 $W’$ 相乘,再将该列向量通过 Softmax 归一化。其中,假设数据集有 V 个单词,$W’$ 是 $|V|*m$ 的矩阵,$h_{k}$ 是 $m*1$ 的列向量,于是最终后果是 $|V|*1$ 的归一化后向量,即从输出单词失去的针对每个单词的概率。

### 2.2.2 双向语言模型

假设一个序列有 N 个 token,即 $(t_{1},t_{2},…,t_{N})$,对于前向语言模型(forward LM),咱们基于 $(t_{1},..,t_{k-1})$ 来预测 $t_{k}$,前向公式示意为:

$$p(t_{1},t_{2},…,t_{N})=\prod_{k=1}^{N}p(t_{k}|t_{1},t_{2},…,t_{k-1})$$

向后语言模型(backword LM)与向前语言模型相似,除了计算的时候倒置输出序列,用前面的上下文预测后面的词:

$$p(t_{1},t_{2},…,t_{N})=\prod_{k=1}^{N}p(t_{k}|t_{k+1},t_{k+2},…,t_{N})$$

一个双向语言模型蕴含前向和后向语言模型,训练的指标就是联结前向和后向的最大似然:

$$\sum_{k=1}^N (log p(t_{k}|t_{1},…,t_{k-1};\Theta_{x},\overrightarrow\Theta_{LSTM},\Theta_{s})+log p(t_{k}|t_{k+1},…,t_{N};\overleftarrow\Theta_{LSTM},\Theta_{s}))$$

两个网络里都呈现了 $\Theta_{x}$ 和 $\Theta_{s}$,两个网络共享的参数。

其中 $\Theta_{x}$ 示意映射层的共享,示意第一步中,将单词映射为 word embedding 的共享,就是说同一个单词,映射为同一个 word embedding。

$\Theta_{s}$ 示意第三步中的上下文矩阵的参数,这个参数在前向和后向 LSTM 中是雷同的。

### 2.2.3 ELMo

ELMo 对于每个 token $t_{k}$, 通过一个 L 层的 biLM 计算 2L+1 个表征(representations),这是输出第二阶段的初始值:

$$R_{k}=\{x_{k}^{LM},\overrightarrow h^{LM}_{k,j},\overleftarrow h^{LM}_{k,j}|j=1,…,L\}$$

$$=\{h_{k,j}^{LM}|j=0,…,L\}$$

其中 k 示意单词地位,j 示意所在层,j=0 示意输出层。故整体可用右侧的 h 示意。$h_{k,0}^{LM}$ 是对 token 进行间接编码的后果 (这里是字符通过 CNN 编码),$h_{k,j}^{LM}=[\overrightarrow h^{LM}_{k,j};\overleftarrow h^{LM}_{k,j}]$ 是每个 biLSTM 层输入的后果。在试验中还发现不同层的 biLM 的输入的 token 示意对于不同的工作成果不同. 最下面一层的输入是用 softmax 来预测上面一个单词

利用中将 ELMo 中所有层的输入 R 压缩为单个向量, $ELMo_{k}=E(R_{k};\Theta_{\epsilon})$,最简略的压缩办法是取最上层的后果做为 token 的示意:$E(R_{k})=h_{k,L}^{LM}$, 更通用的做法是通过一些参数来联结所有层的信息:

$$ELMo_{k}^{task}=E(R_{k};\Theta^{task})$$

$$=\gamma^{task}\sum_{j=0}^{L}s_{j}^{task}h_{k,j}^{LM}$$

其中 $s_{j}$ 是 softmax 标准化权重,$\gamma$ 是缩放系数,容许任务模型去缩放整个 ELMO 向量。文中提到 γ 在不同工作中取不同的值成果会有较大的差别,须要留神,在 SQuAD 中设置为 0.01 获得的成果要好于设置为 1 时。

文章中提到的 Pre-trained 的 language model 是用了两层的 biLM, 对 token 进行上下文无关的编码是通过 CNN 对字符进行编码, 而后将三层的输入 scale 到 1024 维, 最初对每个 token 输入 3 个 1024 维的向量示意.

## 2.3.ELMo 训练

### 2.3.1 第一阶段 语言模型进行预训练

ELMo 采纳了典型的两阶段过程,第一个阶段是利用语言模型进行预训练;第二个阶段是在做上游工作时,从预训练网络中提取对应单词的网络各层的 Word Embedding 作为新特色补充到上游工作中。图展现的是其预训练过程:

它的网络结构采纳了双层双向 LSTM,目前语言模型训练的工作指标是依据单词 $W_{i}$ 的上下文去正确预测单词 $W_{i}$,$W_{i}$ 之前的单词序列 Context-before 称为上文,之后的单词序列 Context-after 称为下文。图中左端的前向双层 LSTM 代表正方向编码器,输出的是从左到右程序的除了预测单词外 $W_{i}$ 的上文 Context-before;右端的逆向双层 LSTM 代表反方向编码器,输出的是从右到左的逆序的句子下文 Context-after;每个编码器的深度都是两层 LSTM 叠加。这个网络结构其实在 NLP 中是很罕用的。

应用这个网络结构利用大量语料做语言模型工作就能事后训练好这个网络,如果训练好这个网络后,输出一个新句子 $S_{new}$,句子中每个单词都能失去对应的三个 Embedding: 最底层是单词的 Word Embedding,往上走是第一层双向 LSTM 中对应单词地位的 Embedding,这层编码单词的句法信息更多一些;再往上走是第二层 LSTM 中对应单词地位的 Embedding,这层编码单词的语义信息更多一些。也就是说,ELMO 的预训练过程不仅仅学会单词的 Word Embedding,还学会了一个双层双向的 LSTM 网络结构,而这两者前面都有用。

### 2.3.2 第二阶段 接入上游 NLP 工作

下图展现了上游工作的应用过程,比方咱们的上游工作依然是 QA 问题,此时对于问句 X,咱们能够先将句子 X 作为预训练好的 ELMo 网络的输出,这样句子 X 中每个单词在 ELMO 网络中都能取得对应的三个 Embedding,之后给予这三个 Embedding 中的每一个 Embedding 一个权重 a,这个权重能够学习得来,依据各自权重累加求和,将三个 Embedding 整合成一个。而后将整合后的这个 Embedding 作为 X 句在本人工作的那个网络结构中对应单词的输出,以此作为补充的新特色给上游工作应用。

对于上图所示上游工作 QA 中的答复句子 Y 来说也是如此解决。因为 ELMO 给上游提供的是每个单词的特色模式,所以这一类预训练的办法被称为“Feature-based Pre-Training”。

最初,作者发现给 ELMo 模型减少肯定数量的 Dropout,在某些状况下给损失函数退出正则项 $\lambda ||w||^2_{2}$,这等于给 ELMo 模型加了一个演绎偏置,使得权重靠近 BiLM 所有层的均匀权重。

## 2.4. ELMo 应用步骤

ELMO 的应用次要有三步:

1. 在大的语料库上预训练 biLM 模型。模型由两层 biLSTM 组成,模型之间用残差连接起来。而且作者认为低层的 biLSTM 层能提取语料中的句法信息,高层的 biLSTM 能提取语料中的语义信息。

2. 在咱们的训练语料(去除标签),fine-tuning 预训练好的 biLM 模型。这一步能够看作是 biLM 的 domain transfer。

3. 利用 ELMo 产生的 word embedding 来作为工作的输出,有时也能够即在输出时退出,也在输入时退出。

### 2.4.1 优缺点

* 长处

* 思考上下文,针对不同的上下文生成不同的词向量。表白不同的语法或语义信息。如“流动”一词,既能够是名词,也能够是动词,既能够做主语,也能够做谓语等。针对这种状况,ELMo 可能依据不同的语法或语义信息生成不同的词向量。

* 6 个 NLP 工作中性能都有幅度不同的晋升,最高的晋升达到 25% 左右,而且这 6 个工作的覆盖范围比拟广,蕴含句子语义关系判断,分类工作,浏览了解等多个畛域,这阐明其适用范围是十分广的,普适性强,这是一个十分好的长处。

* 毛病

* 应用 LSTM 提取特色,而 LSTM 提取特色的能力弱于 Transformer

* 应用向量拼接形式交融上下文特色,这种形式获取的上下文信息成果不如设想中好

* 训练工夫长,这也是 RNN 的实质导致的,和下面特征提取毛病差不多;

参考文献:

Deep contextualized word representations

# 3.Transformer

## 3.1.Transformer 介绍

Transformer 网络架构架构由 Ashish Vaswani 等人在 Attention Is All You Need 一文中提出,并用于机器翻译工作,和以往网络架构有所区别的是,该网络架构中,编码器和解码器没有采纳 RNN 或 CNN 等网络架构,而是采纳齐全依赖于注意力机制的架构。网络架构如下所示:

Transformer 改良了 RNN 被人诟病的训练慢的特点,利用 self-attention 能够实现疾速并行。上面的章节会具体介绍 Transformer 的各个组成部分。

Transformer 次要由 encoder 和 decoder 两局部组成。在 Transformer 的论文中,encoder 和 decoder 均由 6 个 encoder layer 和 decoder layer 组成,通常咱们称之为 encoder block。

transformer 构造

每一个 encoder 和 decoder 的外部简版构造如下图

transformer 的 encoder 或者 decoder 的内部结构

对于 encoder,蕴含两层,一个 self-attention 层和一个前馈神经网络,self-attention 能帮忙以后节点不仅仅只关注以后的词,从而能获取到上下文的语义。

decoder 也蕴含 encoder 提到的两层网络,然而在这两层两头还有一层 attention 层,帮忙以后节点获取到以后须要关注的重点内容。

首先,模型须要对输出的数据进行一个 embedding 操作,enmbedding 完结之后,输出到 encoder 层,self-attention 解决完数据后把数据送给前馈神经网络,前馈神经网络的计算能够并行,失去的输入会输出到下一个 encoder。

embedding 和 self-attention

## 3.2 Transformer 的构造

Transformer 的构造解析进去如下图示意,包含 Input Embedding, Position Embedding, Encoder, Decoder。

### 3.2.1 Embedding

字向量与地位编码的公式示意如下:

$$X=Embedding Lookup(X)+Position Encoding$$

* Input Embedding

能够将 Input Embedding 看作是一个 lookup table,对于每个 word,进行 word embedding 就相当于一个 lookup 操作,查出一个对应后果。

* Position Encoding

Transformer 模型中还短少一种解释输出序列中单词程序的办法。为了解决这个问题,transformer 给 encoder 层和 decoder 层的输出增加了一个额定的向量 Positional Encoding,维度和 embedding 的维度一样,这个向量采纳了一种很独特的办法来让模型学习到这个值,这个向量能决定以后词的地位,或者说在一个句子中不同的词之间的间隔。这个地位向量的具体计算方法有很多种,论文中的计算方法如下

$$PE(pos,2i)=sin(pos/10000^{2i}/d_{model})$$

$$PE(pos,2i+1)=cos(pos/10000^{2i}/d_{model})$$

其中 pos 是指以后词在句子中的地位,i 是指向量中每个值的 index,能够看出,在偶数地位,应用正弦编码,在奇数地位,应用余弦编码.

### 3.2.2 Encoder

用公式把一个 Transformer Encoder block 的计算过程整顿一下

* 自注意力机制

$$Q=XW_{Q}$$

$$K=XW_{K}$$

$$V=XW_{V}$$

$$X_{attention}=selfAttention(Q,K,V)$$

* self-attention 残差连贯与 Layer Normalization

$$X_{attention}=LayerNorm(X_{attention})$$

* FeedForward,其实就是两层线性映射并用激活函数激活,比如说 RELU

$$X_{hidden}=Linear(RELU(Linear(X_{attention})))$$

* FeedForward 残差连贯与 Layer Normalization

$$X_{hidden}=X_{attention}+X_{hidden}$$

$$X_{hidden}=LayerNorm(X_{hidden})$$

其中:$X_{hidden} \in R^{batch_size*seq_len*embed_dim}$

### 3.2.3 自注意力机制

* 首先,自注意力机制(self-attention)会计算出三个新的向量,在论文中,向量的维度是 512 维,咱们把这三个向量别离称为 Query、Key、Value,这三个向量是用 embedding 向量与一个矩阵相乘失去的后果,这个矩阵是随机初始化的,维度为(64,512)留神第二个维度须要和 embedding 的维度一样,其值在反向流传的过程中会始终进行更新,失去的这三个向量的维度是 64 低于 embedding 维度的。

Query Key Value

2、计算 self-attention 的分数值,该分数值决定了当咱们在某个地位 encode 一个词时,对输出句子的其余局部的关注水平。这个分数值的计算方法是 Query 与 Key 做点乘,以下图为例,首先咱们须要针对 Thinking 这个词,计算出其余词对于该词的一个分数值,首先是针对于本人自身即 q1·k1,而后是针对于第二个词即 q1·k2

Query Key Value

3、接下来,把点乘的后果除以一个常数,这里咱们除以 8,这个值个别是采纳上文提到的矩阵的第一个维度的开方即 64 的开方 8,当然也能够抉择其余的值,而后把失去的后果做一个 softmax 的计算。失去的后果即是每个词对于以后地位的词的相关性大小,当然,以后地位的词相关性必定会会很大

softmax

4、下一步就是把 Value 和 softmax 失去的值进行相乘,并相加,失去的后果即是 self-attetion 在以后节点的值。

dot product

在理论的利用场景,为了进步计算速度,咱们采纳的是矩阵的形式,间接计算出 Query, Key, Value 的矩阵,而后把 embedding 的值与三个矩阵间接相乘,把失去的新矩阵 Q 与 K 相乘,乘以一个常数,做 softmax 操作,最初乘上 V 矩阵

scaled dot product attention

这种通过 query 和 key 的相似性水平来确定 value 的权重散布的办法被称为 scaled dot-product attention。

用公式表白如下:

$$Q=XW_{Q}$$

$$K=XW_{K}$$

$$V=XW_{V}$$

$$X_{attention}=selfAttention(Q,K,V)$$

### 3.2.4 Self-Attention 复杂度

Self-Attention 工夫复杂度:$O(n^2 \cdot d)$,这里,n 是序列的长度,d 是 embedding 的维度。

Self-Attention 包含三个步骤:类似度计算,softmax 和加权均匀,它们别离的工夫复杂度是:

类似度计算能够看作大小为 (n,d) 和 (d,n) 的两个矩阵相乘:$(n,d) *(d,n) =(n^2 \cdot d)$,失去一个 (n,n) 的矩阵

softmax 就是间接计算了,工夫复杂度为: $O(n^2)$

加权均匀能够看作大小为 (n,n) 和 (n,d) 的两个矩阵相乘:$(n,d) *(d,n) =(n^2 \cdot d)$,失去一个 (n,d) 的矩阵

因而,Self-Attention 的工夫复杂度是: $O(n^2 \cdot d)$

### 3.2.5 Multi-head Attention

不仅仅只初始化一组 Q、K、V 的矩阵,而是初始化多组,tranformer 是应用了 8 组,所以最初失去的后果是 8 个矩阵。

multi-head attention

multi-head 注意力的全过程如下,首先输出句子,“Thinking Machines”, 在 embedding 模块把句子中的每个单词变成向量 X,在 encoder 层中,除了第 0 层有 embedding 操作外,其余的层没有 embedding 操作;接着把 X 分成 8 个 head,

multi-head attention 总体构造

### 3.2.6 Multi-Head Attention 复杂度

多头的实现不是循环的计算每个头,而是通过 transposes and reshapes,用矩阵乘法来实现的。

Transformer/BERT 中把 d,也就是 hidden_size/embedding_size 这个维度做了 reshape 拆分。并将 num_attention_heads 维度 transpose 到后面,使得 Q 和 K 的维度都是 (m,n,a),这里不思考 batch 维度。

这样点积能够看作大小为 (m,n,a) 和 (m,a,n) 的两个张量相乘,失去一个 (m,n,n) 的矩阵,其实就相当于 (n,a) 和 (a,n) 的两个矩阵相乘,做了 m 次,工夫复杂度是:

$$O(n^2 \cdot m \cdot a)=O(n^2 \cdot d)$$

因而 Multi-Head Attention 工夫复杂度也是 $O(n^2 \cdot d)$,复杂度相较单头并没有变动,次要还是 transposes and reshapes 的操作,相当于把一个大矩阵相乘变成了多个小矩阵的相乘。

### 3.2.7 残差连贯

通过 self-attention 加权之后输入,也就是 Attention(Q,K,V),而后把他们加起来做残差连贯

$$X_{hidden}=X_{embedding}+self Attention(Q,K,V)$$

除了 self-attention 这里做残差连贯外,feed forward 那个中央也须要残差连贯,公式相似:

$$X_{hidden}=X_{feed_forward}+X_{hidden}$$

### 3.2.8 Layer Normalization

Layer Normalization 的作用是把神经网络中暗藏层归一为规范正态分布,也就是独立同散布,以起到放慢训练速度,减速收敛的作用 $$X_{hidden}=LayerNorm(X_{hidden})$$

其中:$X_{hidden} \in R^{batch_size*seq_len*embed_dim}$

LayerNorm 的具体操作如下:

$$\mu_{L}=\dfrac{1}{m}\sum_{i=1}^{m}x_{i}$$

上式以矩阵为单位求均值;

$$\delta^{2}=\dfrac{1}{m}\sum_{i=1}^{m}(x_{i}-\mu)^2$$

上式以矩阵为单位求方差

$$LN(x_{i})=\alpha \dfrac{x_{i}-\mu_{L}}{\sqrt{\delta^{2}+\epsilon}}+\beta$$

而后用每一列的每一个元素减去这列的均值,再除以这列的标准差,从而失去归一化后的数值,加 $\epsilon$ 是为了避免分母为 0. 此处个别初始化 $\alpha$ 为全 1,而 $\beta$ 为全 0.

### 3.2.9 Feed Forward

将 Multi-Head Attention 失去的向量再投影到一个更大的空间(论文里将空间放大了 4 倍)在那个大空间里能够更不便地提取须要的信息(应用 Relu 激活函数),最初再投影回 token 向量原来的空间

$$FFN(x)=ReLU(W_{1}x+b_{1})W_{2}+b_{2}$$

借鉴 SVM 来了解:SVM 对于比较复杂的问题通过将特色其投影到更高维的空间使得问题简略到一个超平面就能解决。这里 token 向量里的信息通过 Feed Forward Layer 被投影到更高维的空间,在高维空间里向量的各类信息彼此之间更容易区别。

3.3 Decoder

和 Encoder 一样,下面三个局部的每一个局部,都有一个残差连贯,后接一个 Layer Normalization。Decoder 的两头部件并不简单,大部分在后面 Encoder 里咱们曾经介绍过了,然而 Decoder 因为其非凡的性能,因而在训练时会波及到一些细节,上面会介绍 Decoder 的 Masked Self-Attention 和 Encoder-Decoder Attention 两局部,其结构图如下图所示

decoder self attention

### 3.2.10 Masked Self-Attention

传统 Seq2Seq 中 Decoder 应用的是 RNN 模型,因而在训练过程中输出因而在训练过程中输出 t 时刻的词,模型无论如何也看不到将来时刻的词,因为循环神经网络是工夫驱动的,只有当 t 时刻运算完结了,能力看到 t+1 时刻的词。而 Transformer Decoder 摈弃了 RNN,改为 Self-Attention,由此就产生了一个问题,在训练过程中,整个 ground truth 都裸露在 Decoder 中,这显然是不对的,咱们须要对 Decoder 的输出进行一些解决,该解决被称为 Mask。

Mask 非常简单,首先生成一个下三角全 0,上三角全为负无穷的矩阵,而后将其与 Scaled Scores 相加即可,之后再做 softmax,就能将 -inf 变为 0,失去的这个矩阵即为每个字之间的权重。

### 3.3.2 Masked Encoder-Decoder Attention¶

其实这一部分的计算流程和后面 Masked Self-Attention 很类似,构造也一摸一样,惟一不同的是这里的 K,V 为 Encoder 的输入,Q 为 Decoder 中 Masked Self-Attention 的输入

Masked Encoder-Decoder Attention

### 3.2.11 Decoder 的解码

下图展现了 Decoder 的解码过程,Decoder 中的字符预测完之后,会当成输出预测下一个字符,晓得遇见终止符号为止。

## 3.3 Transformer 的最初一层和 Softmax

线性层是一个简略的全连贯的神经网络,它将解码器堆栈生成的向量投影到一个更大的向量,称为 logits 向量。如图 linear 的输入

softmax 层将这些分数转换为概率(全副为正值,总和为 1.0)。抉择概率最高的单元,并生成与其关联的单词作为此工夫步的输入。如图 softmax 的输入。

## 3.4 Transformer 的权重共享

Transformer 在两个中央进行了权重共享:

*(1)Encoder 和 Decoder 间的 Embedding 层权重共享;

《Attention is all you need》中 Transformer 被利用在机器翻译工作中,源语言和目标语言是不一样的,但它们能够共用一张大词表,对于两种语言中独特呈现的词(比方:数字,标点等等)能够失去更好的示意,而且对于 Encoder 和 Decoder,嵌入时都只有对应语言的 embedding 会被激活,因而是能够共用一张词表做权重共享的。

论文中,Transformer 词表用了 bpe 来解决,所以最小的单元是 subword。英语和德语同属日耳曼语族,有很多雷同的 subword,能够共享相似的语义。而像中英这样相差较大的语系,语义共享作用可能不会很大。

然而,共用词表会使得词表数量增大,减少 softmax 的计算工夫,因而理论应用中是否共享可能要依据状况衡量。

*(2)Decoder 中 Embedding 层和 FC 层权重共享;

Embedding 层能够说是通过 onehot 去取到对应的 embedding 向量,FC 层能够说是相同的,通过向量(定义为 x)去失去它可能是某个词的 softmax 概率,取概率最大(贪心状况下)的作为预测值。

那哪一个会是概率最大的呢?在 FC 层的每一行量级雷同的前提下,实践上和 x 雷同的那一行对应的点积和 softmax 概率会是最大的(可类比本文问题 1)。

因而,Embedding 层和 FC 层权重共享,Embedding 层中和向量 x 最靠近的那一行对应的词,会取得更大的预测概率。实际上,Decoder 中的 Embedding 层和 FC 层有点像互为逆过程。

通过这样的权重共享能够缩小参数的数量,放慢收敛。

## 3.4 小结

本文具体介绍了 Transformer 的细节,包含 Encoder,Decoder 局部,输入解码的局部,Transformer 的共享机制等等。

5. 参考文献

Attention Is All You Need

退出移动版