SpringMVC——核心技术:拦截器

String,StringBuilder和StringBuffer

  返回  

datawhale 8月学习——NLP之Transformers:BERT和GPT(更新中)

2021/8/20 19:29:55 浏览:

前情回顾

1.attention和transformers

结论速递

由于没有很多的NLP知识背景,跳开NLP框架来学习BERT和GPT的时候,有许多不解和迷惑的地方。在本次学习中,我参考了一些相关的NLP博客文章,试图为自己构建一个NLP的知识体系。对于本次学习,其实核心的需要理解NLP中的预训练+微调模式,以及一类重要的任务——语言建模。
对于BERT模型,教程里面的逻辑并非层层展开的,这边简单小结一下BERT的主要关注点:

  1. 首先BERT应用是预训练+微调模式,这也是NLP常用的模式;
  2. BERT模型本质上是一个语言建模模型;
  3. BERT用了Transformer的Encoder,并且使用了mask来改进Encoder,从而实现语言建模的目的;
  4. BERT的用途还算广泛,可以用于文本分类,QA任务等,使用方法是下载预训练好的BERT,然后根据任务类型在合适输出位置后加FFNN。

本文索引

    • 前情回顾
    • 结论速递
  • 1 BERT
    • 1.1 BERT的诞生
      • 1.1.1 NLP的发展与BERT的诞生
      • 1.1.2 BERT的使用简介
      • 1.1.3 BERT的使用案例:句子分类
    • 1.2 BERT模型
      • 1.2.1 概述
      • 1.2.2 简单理解BERT模型
      • 1.2.3 BERT预训练的本质:语言建模(词嵌入)
        • 1.2.3.1 词嵌入的回顾
        • 1.2.3.2 ELMo:考虑上下文的词嵌入
        • 1.2.3.3 OpenAI Transformer:Transformer Decoder获取上文信息
        • 1.2.3.4 BERT:Transformer Encoder获取上下文信息
      • 1.2.4 BERT的使用
        • 1.2.4.1 BERT的输入嵌入
        • 1.2.4.2 BERT在不同任务上的应用
        • 1.2.4.3 将 BERT 用于特征提取
        • 1.2.4.4 如何使用BERT
  • 2 GPT-2
    • 2.1 什么是GPT-2
    • 2.2 Transformer Block的进化
      • 2.2.1 进一步理解Self-Attention
  • 参考阅读

1 BERT

1.1 BERT的诞生

1.1.1 NLP的发展与BERT的诞生

2018年是NLP的ImageNet时刻,就是说多年前类似的发展也加速了机器学习在计算机视觉任务中的应用。在这一年的里程碑式BERT的发布,标志这一个新的时代的开始。
BERT 是一个模型,它打破了模型处理基于语言的任务的能力的多项记录。
这是一个重大的发展,因为它使得任何一个构建构建机器学习模型来处理语言的人,都可以将这个强大的功能作为一个现成的组件来使用,从而节省了从零开始训练语言处理模型所需要的时间、精力、知识和资源。

NLP当前面临的任务是如何最好地表示单词和句子,从而最好地捕捉基本语义和关系。

在这样的背景下,BERT诞生了。BERT诞生于NLP的一些聪明想法上(包括但不限于半监督序列学习、ELMo、ULMFiT、OpenAI transformer和Transformer)。

这些聪明想法为:

  1. ELMo:考虑上下文的词嵌入技术(后面1.2.3.2节会进行介绍)
  2. ULM-FiT:NLP 领域的迁移学习
    受 ImageNet 预训练在计算机视觉任务上启发,生成式预训练 LM + 任务微调的思路最先在 ULMFiT上得到了尝试。
    它所使用的模型是AWD-LSTM,通过LM预训练,目标任务LM微调,还有目标任务分类器微调三步完成。
    在这里插入图片描述
  3. Transformer:比LSTM更好地处理长期依赖
    其Encoder+Decoder结构使得其非常适合机器翻译,但是在文本分类问题上还需要改变。
  4. OpenAI Transformer:预训练一个 Transformer Decoder 来进行语言建模(后面1.2.3.3节也会详细介绍)

提出BERT的Open Sourcing BERT: State-of-the-Art Pre-training for Natural Language Processing,其代码开源在GitHub上google-research/bert

1.1.2 BERT的使用简介

使用BERT分为两大主要的步骤

  1. 下载预训练好的模型
    一般来讲,这个模型是在无标注的数据上训练的
  2. 针对自己的数据进行模型微调

下面这张图来源于The Illustrated BERT, ELMo, and co. (How NLP Cracked Transfer Learning),它比较简单清晰的解释了使用BERT的两大主要步骤。
在这里插入图片描述

1.1.3 BERT的使用案例:句子分类

可以通过句子分类任务更直观地理解BERT模型的使用,任务描述如下:

垃圾邮件检测:
通过分析邮件中的信息,判断邮件为“垃圾邮件”或者“非垃圾邮件”。
这个任务属于一个监督学习任务,需要一个带有标签的数据集,即一个邮件内容列表,和对应的一系列标签。

为了比较好地完成这一个任务,我们可能需要一个很大的有标签数据集,但是通过BERT,我们可以减少这个数据集的大小要求。
在这里插入图片描述
如上图所示,只需要下载一个BERT,然后训练上述的Classifier就可以,几乎不需要改动BERT模型。

这个训练过程称为微调,它起源于Semi-supervised Sequence Learning 和 ULMFiT。

1.2 BERT模型

1.2.1 概述

文章发布时提到了两种大小的BERT,一种是BASE版本,比较小一些(与OpenAI Transformer大小接近),方便和其他模型比较性能;另外一种是LARGE版本,这是一个非常巨大的模型,可以取得最先进的成果。

这两种BERT模型都有大量的Encoder层,BASELARGE分别有12层和24层,同时也有更大的前馈神经网络(768, 1024 hidden units)和更多的Attention heads(12, 16)。
在这里插入图片描述
在这里插入图片描述
如今已经增加了多个模型,这个在BERT的Github上面可以下载得到,其中中文是唯一的一个非英语模型。
在这里插入图片描述
需要注意的是,BERT模型的预训练需要的计算要求非常高,所以其可复现性很差,我们在使用的时候只能够直接用,然后微调。

Reddit对跑一次BERT的价格讨论展示,确实是相当昂贵:
For TPU pods:
4 TPUs * ~$2/h (preemptible) * 24 h/day * 4 days = $768 (base model)
16 TPUs = ~$3k (large model)
For TPU:
16 tpus * $8/hr * 24 h/day * 4 days = 12k
64 tpus * $8/hr * 24 h/day * 4 days = 50k
For GPU:
"BERT-Large is 24-layer, 1024-hidden and was trained for 40 epochs over a 3.3 billion word corpus. So maybe 1 year to train on 8 P100s? "
实在是贵得离谱。

1.2.2 简单理解BERT模型

BERT模型有很多个位置输出,每个位置输出一个大小为hidden_size的向量,如下图所示
在这里插入图片描述
对于前面所述的文本分类的例子,我们关注的是第一个位置输出的向量,也就是[CLS]那个位置。该向量现在可以用作我们选择的分类器的输入。

就像下面这样,叠加一个单层的Classifier
在这里插入图片描述
这个感觉有点像计算机视觉问题中VGGNet等网络中完成特征提取的卷积部分,和网络最后完成分类问题的全连接分类部分。
在这里插入图片描述
有点像下面这样的类比

模型/功能特征提取分类
计算机视觉分类任务卷积层全连接分类层
文本分类任务BERT全连接分类层

1.2.3 BERT预训练的本质:语言建模(词嵌入)

1.2.3.1 词嵌入的回顾

所谓的词嵌入,是指

单词不能直接输入机器学习模型,而需要某种数值表示形式,以便模型能够在计算中使用。通过 Word2Vec,我们可以使用一个向量(一组数字)来恰当地表示单词,并捕捉单词的语义以及单词和单词之间的关系(例如,判断单词是否相似或者相反,或者像 “Stockholm” 和 “Sweden” 这样的一对词,与 “Cairo” 和 "Egypt"这一对词,是否有同样的关系)以及句法、语法关系(例如,“had” 和 “has” 之间的关系与 “was” 和 “is” 之间的关系相同)。

词嵌入对自然语言处理来说相当重要,为了达到好的效果,最好是在大规模的文本数据上预训练好词嵌入,然后直接拿来使用。

现在已经有很多中词嵌入的方法,最常用的是Word2Vec和GloVe,我们可以下载器预训练好的单词列表,并完成词嵌入。

教程里给了一个直观的词嵌入的例子:

在GloVe中单词stick的词嵌入向量,其长度是200.
在这里插入图片描述

1.2.3.2 ELMo:考虑上下文的词嵌入

尽管GloVe已经在很多地方很有用处,但是它并没有考虑到一个单词出现在文章中的不同位置会有什么不同的含义。

语言模型嵌入(Embeddings from Language Model,ELMo)试图通过无监督的方式预训练一个语言模型来获取情景化字词表示,它是一种语境化的词嵌入技术。

ELMo没有对单词使用固定的词嵌入,而是在为每个词分配词嵌入之前,查看整个句子,融合上下文信息。

「双向语言模型(bidirectional Language Model,biLM)」 是 ELMo 的基础,当输入为 n n n个标识组成的序列时, ( x 1 , . . . , x n ) (x_1,...,x_n) (x1,...,xn),语言模型会学着根据历史预测下个标识的概率。

下图展示了ELMo 的 biLSTM 基础模型。把很多很多地语料输入到这个模型中,就可以得到上下文词嵌入。
在这里插入图片描述
ELMo的秘密通俗地讲,就是通过训练,预测单词序列中的下一个词,从而获得了语言理解能力,这项任务被称为语言建模。

举个例子,以 “Let’s stick to” 作为输入,预测下一个最有可能的单词。分为前向和后向两部分,都会进行预测,每个unit都可以输出当前方向下最大概率出现的下一个单词。
在这里插入图片描述
ELMo 通过将隐藏层状态(以及初始化的词嵌入)以某种方式(向量拼接之后加权求和)结合在一起,实现了带有语境化的词嵌入。(为什么每个隐层和初始的词嵌入都要结合起来?)
在这里插入图片描述

1.2.3.3 OpenAI Transformer:Transformer Decoder获取上文信息

OpenAI Transformer使用Transformer的Decoder 来进行语言建模,选择Decoder是因为它有mask,可以除去下文的影响,适合进行语言建模。

这个模型包括 12 个 Decoder 层。因为在这种设计中没有 Encoder,这些 Decoder 层不会像普通的 Transformer 中的 Decoder 层那样有 Encoder-Decoder Attention 子层。不过,它仍然会有 Self Attention 层(这些层使用了 mask,因此不会看到句子后来的 token)。
在这里插入图片描述
当OpenAI Transformer 经过了预训练,它的网络层经过调整,可以很好地处理文本语言,就可以开始使用它来处理下游任务。

例如句子分类任务(把电子邮件分类为 ”垃圾邮件“ 或者 ”非垃圾邮件“),直接在后面街上一个全连接神经网络。
在这里插入图片描述
论文中列举了一些常见的下游任务所需要对应的输入和输出,包括分类任务,推理任务,文本相似性检查,多种选择等。
在这里插入图片描述
GPT 的一个局限之处在于单向性——模型只会自左向右的预测上下文。

1.2.3.4 BERT:Transformer Encoder获取上下文信息

前面提到,ELMo可以实现双向语言建模,但OpenAI Transformer 只训练了一个前向的语言模型。我们希望可以获得一个双向语言建模的基于Transformer 的模型。

事实上BERT的全称就是Transformer 双向编码器表示(Bidirectional Encoder Representations from Transformers,BERT)

为了能够获取上下文信息,BERT完成了两个任务:

第一个任务,遮罩语言模型(Mask language model,MLM)

BERT尝试使用Transformer的Encoder来实现上下文信息的获取,但是Encoder的self-attention会把更多的注意力集中到自己身上,就学不到有用的上下文信息了。于是,BERT 提出使用 mask,把需要预测的词屏蔽掉

这个模型也叫MLM,即遮罩语言模型(Mask language model,MLM),它像完形填空一样有趣。

“完形填空(填充缺失测验)是一项练习,测试或评估,由一部分语句构成,其中特定项、字词或符号会被删除(填空文本),与试者的任务是替换缺失语言项……该练习首先由 W.L. Taylor 在 1953 年提出”

  1. 每个句子随机挡住 15% 的内容。因为如果我们只用特殊占位符 [MASK] 换掉被遮标识,微调的时候特定标识就再也看不到了。所以 BERT 用了几个启发式技巧:
    a. 80% 的概率用 [MASK] 替换选定词
    b. 10% 的概率用随机词替换
    c. 10% 的概率保持不变
  2. 模型只预测缺失词,但它不知道哪个词被替换了,或者要预测哪个词。输出大小只有输入的 15%

下面这个图可以直观地展示MLM:
在这里插入图片描述

BERT 在语言建模任务中,巧妙地屏蔽了输入中 15% 的单词,并让模型预测这些屏蔽位置的单词。
除了屏蔽输入中 15% 的单词外, BERT 还混合使用了其他的一些技巧,来改进模型的微调方式。例如,有时它会随机地用一个词替换另一个词,然后让模型预测这个位置原来的实际单词。

第二个任务,下一句预测

由于许多下游任务涉及到对句子间关系的理解(QA,NLI),BERT 额外加了一个辅助任务,训练一个二分类器(binary classifier)判断一句话是不是另一句的下文:

  1. 对语句对(A,B)采样:
    a. 50% 的情况 B 是 A 的下文
    b. 50% 的情况不是
  2. 模型对两句话进行处理并输出一个二值标签,指明 B 是否就是 A 后的下一句话

上述两个辅助任务的训练数据可以轻易从任意单语语料中获取,所以训练规模不受限制。训练损失是累计平均遮罩 LM 概率,和累计平均下文预测概率。

在这里插入图片描述

BERT 预训练的第 2 个任务是两个句子的分类任务。在上图中,tokenization 这一步被简化了,因为 BERT 实际上使用了 WordPieces 作为 token,而不是使用单词本身。在 WordPiece 中,有些词会被拆分成更小的部分。

下面这个图片展示了上面提到的三个语言建模模型的不同,还挺直观的。
在这里插入图片描述

1.2.4 BERT的使用

1.2.4.1 BERT的输入嵌入

为了在任务中使用BERT模型,需要了解BERT模型的不同位置输出的含义,这个其实涉及到了BERT的输入嵌入

BERT的输入嵌入是三部分的和:

  1. 「字段标识嵌入(WordPiece tokenization embeddings)」
    字段模型原本是针对日语或德语的分词问题提出的。相较于使用自然分隔的英文单词,它们可以进一步分成更小的子词单元便于处理罕见词或未知词。(分词优化也是一个常见的问题)
  2. 「片段嵌入(segment embedding)」
    如果输入有两句话,分别有句子 A 和句子 B 的嵌入向量,并用特殊标识 [SEP] 隔开;如果输入只有一句话就只用句子 A 的嵌入向量。
  3. 「位置嵌入(position embeddings)」
    位置 embedding 需要学习而非硬编码。

如下图所示:
在这里插入图片描述
需要注意的是,注意第一个标识必须是 [CLS],它是之后下游任务预测中会用到的占位符。

1.2.4.2 BERT在不同任务上的应用

其实也就是微调,论文中给了下图:
在这里插入图片描述
对于分类任务,取首个标识 [CLS] 的最终隐态 h L [ C L S ] h_L^{[CLS]} hL[CLS],然后再加上一个权重矩阵(可以通过全连接神经网络训练得到),再 s o f t m a x softmax softmax就可以,也就是 s o f t m a x ( h L [ C L S ] W c l s ) softmax(h_L^{[CLS]}W_{cls}) softmax(hL[CLS]Wcls)

而QA任务,要针对问题预测给定段落的文本跨度。BERT 对每个标识要预测两个概率分布,分别对应描述作为文本范围的开端和末尾的几率。微调时新训练的只有两个小矩阵 W s W_s Ws W e W_e We ,而 s o f t m a x ( h L ( i ) W s ) softmax(h_L^{(i)}W_{s}) softmax(hL(i)Ws) s o f t m a x ( h L ( i ) W e ) softmax(h_L^{(i)}W_{e}) softmax(hL(i)We)对应两个概率分布。

总体来讲微调下游任务时加上的内容很少——一两个权重矩阵,负责将 Transformer的 隐态转换成可解释形式。

1.2.4.3 将 BERT 用于特征提取

使用 BERT 并不是只有微调这一种方法。就像 ELMo 一样,你可以使用预训练的 BERT 来创建语境化的词嵌入。然后你可以把这些词嵌入用到你现有的模型中。论文里也提到,这种方法在命名实体识别任务中的效果,接近于微调 BERT 模型的效果。

在这里插入图片描述

1.2.4.4 如何使用BERT

尝试 BERT 的最佳方式是通过托管在 Google Colab 上的 BERT FineTuning with Cloud TPUs。如果你之前从来没有使用过 Cloud TPU,那这也是一个很好的尝试开端,因为 BERT 代码可以运行在 TPU、CPU 和 GPU。

2 GPT-2

2.1 什么是GPT-2

事实上,我们在前面的1.2.3.3节已经接触到了GPT,OpenAI Transformer,也叫生成式预训练 Transformer(Generative Pre-training Transformer,GPT)。

GPT2是OpenAI开发的GPT 2.0,它的核心思想就是认为可以用无监督的预训练模型去做有监督任务。GPT2模型的结构还是和GPT一样,由Transformer的Decoder构成。和前文所述一致,它是通过从大量语料上训练一个机器学习模型,来进行语言建模。

GPT-2发布了四个大小版本,层数都很多,如下图
在这里插入图片描述
与使用Encoder的BERT模型不同,采用了Decoder的GPT2在每次生成一个结果后,都会把结果添加到输入序列当中,这个新的序列就会变成模型下一步的输入,这是一种叫“自回归(auto-regression)”的思想。这种做法可以使得 RNN 非常有效。

这个其实很好理解,因为decoder就是这么运作的。

GPT2,和后来的一些模型如 TransformerXL 和 XLNet,本质上都是自回归的模型。但 BERT 不是自回归模型。这是一种权衡。去掉了自回归后,BERT 能够整合左右两边的上下文,从而获得更好的结果。XLNet 重新使用了 自回归,同时也找到一种方法能够结合两边的上下文。

2.2 Transformer Block的进化

2.2.1 进一步理解Self-Attention

经过上一个任务attention和transformers的学习,我们现在已经很熟悉Transformer是由Encoder和Decoder构成的。

Encoder长这样
在这里插入图片描述
而Decoder长这样
在这里插入图片描述

参考阅读

  1. The Illustrated BERT, ELMo, and co. (How NLP Cracked Transfer Learning)
  2. NLP语言模型发展史
  3. 一文读懂BERT
  4. The Illustrated GPT-2 (Visualizing Transformer Language Models)

联系我们

如果您对我们的服务有兴趣,请及时和我们联系!

服务热线:18288888888
座机:18288888888
传真:
邮箱:888888@qq.com
地址:郑州市文化路红专路93号