专栏名称: 机器学习算法与自然语言处理
一个有情怀的公众号。机器学习、自然语言处理、算法等知识集中营、期待与你相遇~
目录
相关文章推荐
阑夕  ·  好了看春晚了 -20250128200459 ·  2 天前  
t0mbkeeper  ·  1、root cause 应该是 A 和 ... ·  3 天前  
连岳  ·  多尺寸淡水珍珠素钉,不止优雅 ·  1 周前  
51好读  ›  专栏  ›  机器学习算法与自然语言处理

【BERT】如何训练并使用Bert【持续更新】

机器学习算法与自然语言处理  · 公众号  ·  · 2020-03-17 15:00

正文

公众号关注 “ML_NLP
设为 “星标”,重磅干货,第一时间送达!

来自 | 知乎

地址 | https://zhuanlan.zhihu.com/p/113326366

作者 | 小李杜ljyduke

编辑 | 机器学习算法与自然语言处理公众号

本文仅作学术分享,若侵权,请联系后台删文处理


写作时间:2020.3.15【知乎的pm能听到我的诉求么,我看文章要先看是啥时候发的...】

看到一个大佬的git头像 把人家的头偷来了 ,感兴趣的可以研究一下。我还没写完咋就让我发表了。。。

好的今天我要分享一下怎么预训练自己的Bert,并将其应用到下游任务中。因为不是写论文我就不严格意义上标注哪里是抄的,哪里是自己写的了,看我顺不顺手。所有的参考文献都在最后,表示感谢,如果有遗漏,请联系我补上,我真的很尊重版权并感谢各位大佬的分享。

涉及到的知识点包括但不限于,可以直接去相应章节阅读:

  1. 数据预处理

  2. Transformer 结构复习(todo)

  3. Bert的结构解读

  4. 具体的预训练方式

  5. 如何应用到下游NLP任务中(to complete

  6. 如何对Bert做修改-前处理、后处理与正则(todo

  7. Bert的轻量化改进,后续衍生品(todo

  8. Bert在非文本领域的应用前景(todo

  9. 胡说一下对过去的总结和对未来的看法(todo

一、数据预处理

数据预处理,文中给我们了一个很重要的case,那就是尽量从长文本中搜集数据,这个很重要。因为我们其实是想要获取到长文本的。

二、Transformer 结构复习

三、Bert的论文解读

这个的主要参考文献是论文,说的清楚又不清楚,需要有一些transformer的知识作为背景。

什么叫做finetuning,什么叫做feature-based。jianshu.com/p/689e92250

BERT论文详解

Abstract

  1. BERT Bidirectional Encoder Representations from Transformers 双向,所以对左右两边的context都考虑到了,这样不会丢失单向的另一边的信息

  2. 结论:
    As a result, the pre-trained BERT model can be fintuned with just one additional output layer to create SOTA models for a wide range of tasks
    can: [QA, MRC, NER]
    can't: MT NLG tasks etc. [why? caz it doesn't build on language model]

Introduction

强调了语言模型pre训练的重要性,列出了几种任务:

  1. sentence-level tasks NLI and paraphrasing,.
    目的是通过整体分析预测sentence之间的关系

  2. token-level。NER
    细粒度的分析

2.1 运用预训练模型到下游任务的策略

Feature-based: ELMO, 使用task-specific 结构,其中包含了pretrained的表示作为additioal features

Fine-tuning:GPT (Generative Pre-trained Transformer),介绍了最小的task-specific参数,并且在下游任务上做fine-tuning来微调参数,就可以得到不错的效果。

以上的两个pretraining都用了同样的objective function【语言模型】,且都用了unidirectional language models来学习general的语言表示。

重点来了:

  1. 提出了当前的瓶颈一是单向的语言模型作为学习。这个一个是限制了网络结构,另一个就是在sentencelevel是sub-optimal的,对于句子级别的人物来说。那么对于token级别(QA)的来说就更差劲了,因为双向上下文的信息对这些任务很重要。

  2. 提出了BERT作为解决方案,改进了fine-tuning的预训练方法。和GPT的结构很像,但是应用了双向,并且想出了怎么用,这个是关键。双向的transformer。本身transformer是一个很有力的特征提取器。(三层,语义信息,位置信息,句子信息)。

    1. 应用方法:使用MLM “Masked language model” 作为与训练的objevtive, 说是被Cloze task任务inspired的【BOW也是类似的方法】。
      The masked language model randomly masks some of the tokens from the input, and the objective is to predict the original vocabulary id of the masked word based only on its context. 
      这样的方法就可以把左右的context都放进去

    2. 第二个任务叫做NSP。Next sentence prediction。a “next sentence prediction” task that jointly pre- trains text-pair representations. 文本对的表示。这个怎么理解呢?Specifically, when choosing the sentences A and B for each pretraining example, 50% of the time B is the actual next sentence that follows A (labeled as IsNext), and 50% of the time it is a random sentence from the corpus (labeled as NotNext). 这个在后面有介绍原因,这里先提一下。【cls】 0 1 分别代表了是后面的句子,或者不是

The contributions of our paper are as follows:

  1. MLM来训练,做到了双向transformer

  2. NSP,做到句子级别的训练,特征捕捉

  3. fine-tuning的模型,sota结果。

模型结构

除了output layer,两个过程都是一样的。对于使用者来说,关键是理解,选择什么样的outputlayer,另一个是如何构造自己的数据,送入模型。

使用方法:

[CLS] is a special symbol added in front of every input example, and [SEP] is a special separator token (e.g. separating questions/answers).

We primarily report results on two model sizes:BERTBASE (L=12, H=768, A=12, Total Parameters=110M) and BERTLARGE (L=24, H=1024,A=16, Total Parameters=340M).

如何计算这个参数呢?来自链接 以及 链接2

输入层

词向量包括三个部分的编码:

词向量参数,位置向量参数,句子类型参数

(bert用了2个句子,为0和1)并且,Bert采用的vocab_size=32000,hidden_size=768,max_position_embeddings=512,token_type_embeddings=2。

V x (V x E ) = E

所以:embedding参数 = (32000+512 + 2)* 768 = 24970752

encoder层:Multi-heads



左边的图是一个self attention。即一个head,右边是多个head。

从结构中可以看到,Q,K,V就是我们输入的三个(句子词向量),从之前的词向量分析可知,输出向量大小从len -> len x hidden_size,即len x 768。

如果是self-attention,Q=K=V,如果是普通的attention,Q !=(K=V)。

上次说过了Q和K就是两个要比较的东西。在NLP中的attention中K和V一般是一样的【或许可以修改V得到一种新的attention,应该有了类似的研究了吧】

但是,不管用的是self-attention还是普通的attention,参数计算并不影响。因为在输入单头head时,对QKV的向量均进行了不同的线性变换,引入了三个参数,W1,W2,W3。其维度均为:768 x 64。为什么是64呢,

768/12 . 选择了12个头。所谓的12个头就是有12个scaled dot-product attention. 所以每个头的输入都是64维的。得出:W1,W2,W3的维度都是768 x 64。为什么W123是一样的维度,因为他们的输入是一样的,本身就是同一个东西在做self-attention。所以参数计算结果为:

一个head:768 * 768/12 * 3 输入768,本身维度的输入是768,输出是64,有三个

有12个head。所以有768 * 768/12 * 3 * 12

有一个线性变化的W,768 * 768

所以在multi-heads的参数量为768 * 768/12 * 3 * 12 + 768 * 768=1769472+589824=2359296

对应的每个W都会有一个相应维度的bias 12个 64 以及一个 768.合起来就是两个768



我们看这个网络结构。transformer的,上次我们看过的

encoder层:FeedForward层:全联接

看到参数有W1,W2。其中用到了两个参数W1和W2,Bert沿用了惯用的全连接层大小设置,即4 * dmodle(768,上一层的输出),为3072,因此,W1,W2大小都是为768 * 3072,2个为 2 * 768 * 3072=4718592。

有两个bisa,那么大小为3072*2

encoder层的总共的参数量:

而Base Bert的encoder用了12层,因此,最后的参数大小为:词向量参数 + 12 * (Multi-Heads参数 + 全连接层参数)=

(32000+512 + 2)* 768 + 12 * (768 * 768/12 * 3 * 12 + 768 * 768 + 768 * 3072 * 2+3072*2 + 2 * 768) =

24970752+12*(2359296+4718592 + 6144 + 1536)= 109978896

= 109997328

layer norm 没有添加进去。每个是1536,合起来是36864,打头也有1536的参数。合进去也是差不多的。

最后约等于110M (million)。具体的算法我没有找到官方的计算。

回到论文

Input for BERT

To make BERT handle a variety of down-stream tasks, our input representation is able to unambiguously represent both a single sentence and a pair of sentences (e.g., h Question, Answer i) in one token sequence.

所以bert的输入,可以是一句single的sentence,也可以是两句sentence,用sep分割开。

[cls] sentence A [sep a] sentence B [sep b].

输入的构成:

  1. wordpicec embeddings,30,000token的词表。打头的永远都是[CLS]],这个token在最后的状态中用来表示类别。
    \1. 文本向量:该向量的取值在模型训练过程中自动学习,用于刻画文本的全局语义信息,并与单字/词的语义信息相融合
    \2. 位置向量:由于出现在文本不同位置的字/词所携带的语义信息存在差异(比如:“我爱你”和“你爱我”),因此,BERT模型对不同位置的字/词分别附加一个不同的向量以作区分
    最后,BERT模型将字向量、文本向量和位置向量的加和作为模型输入。特别地,在目前的BERT模型中,文章作者还将英文词汇作进一步切割,划分为更细粒度的语义单位(WordPiece),例如:将playing分割为play和##ing;此外,对于中文,目前作者尚未对输入文本进行分词,而是直接将单字作为构成文本的基本单位。
    'i', 'want', 'em', '##bed', '##ding', '##s', 'for', '.', '[SEP]']
    Notice how the word “embeddings” is represented:
    ['em', '##bed', '##ding', '##s']
    The original word has been split into smaller subwords and characters. The two hash signs preceding some of these subwords are just our tokenizer’s way to denote that this subword or character is part of a larger word and preceded by another subword. So, for example, the ‘##bed’ token is separate from the ‘bed’ token; the first is used whenever the subword ‘bed’ occurs within a larger word and the second is used explicitly for when the standalone token ‘thing you sleep on’ occurs.

  2. 如果是sentence pair。就被pack到一个single的seq中,我们区分两种情况

  • 首先,我们用[SEP]作为区分。

  • 其次,我们添加一个learned embedding,到每个token中,用来表明它属于句子A还是句子B。这个叫做segment embedding,在后面的图2中可以看到。

看一下输入是什么样子,from link:

Because BERT is a pretrained model that expects input data in a specific format, we will need:

  • special tokens to mark the beginning ([CLS]) and separation/end of sentences ([SEP])

  • tokens that conforms with the fixed vocabulary used in BERT

  • token IDs from BERT’s tokenizer

  • mask IDs to indicate which elements in the sequence are tokens and which are padding elements [工程化的一个工作]

  • segment IDs used to distinguish different sentences 【0,1】

  • positional embeddings used to show token position within the sequence 【表征位置】

Luckily, this interface takes care of some of these input specifications for us so we will only have to manually create a few of them (we’ll revisit the other inputs in another tutorial).

special tokens

BERT can take as input either one or two sentences, and expects special tokens to mark the beginning and end of each one:

2 Sentence Input:

[CLS] The man went to the store. [SEP] He bought a gallon of milk. [SEP]

1 Sentence Input:

[CLS] The man went to the store. [SEP]

Task 1 MLM 【masked language model】

  1. 我们mask掉15%的word,然后预测这些word

  2. 但是存在一个问题,就是[mask]这个在finetuning中其实并不会出现的。为了减弱这个影响,对于每个要被mask的word,我们80%的概率使用[Mask]替换,10%随机选择一个在词表中的token,10%就保持原样。

  3. BERT需要对该被修改的单词进行预测,预测其原来的单词是什么。

Task2 NSP

这里主要是在考虑QA,NLI这样的任务是基于对两个句子的关系的理解做出来的。那么为了做这样的模型来理解句子之间的关系。

所以我们这样生成任务训练数据。[sep] token两侧的句子有50%的概率是前后句,有50%的概率不是前后句。[cls]这个token就用来做这个二分类的判断。

预测的方法如下,在输入句子时第一个token是[cls] token,其对应的输出的token上会连接一个二分类层,同样通过损失函数对其进行训练。上述两个任务在预训练中会同时进行。

The NSP task is closely related to representation- learning objectives used in Jernite et al. (2017) and Logeswaran and Lee (2018). However, in prior work, only sentence embeddings are transferred to down-stream tasks, where BERT transfers all pa- rameters to initialize end-task model parameters.

区别于之前的任务。

Pretraining-data

It is critical to use a document-level corpus rather than a shuffled sentence-level corpus such as the Billion Word Benchmark (Chelba et al., 2013) in order to extract long contiguous sequences.

Fine-tuning

这个主要是偏工程化以及task相关的任务。推荐去看看他的git。另一个是中文的相关工作。

英文请直接看google.

中文的相关工作

github.com/CLUEbenchmar

简单说一下:

BERT应用于阅读理解

在SQuAD,给出了问题和包含答案的段落,任务是预测答案文本的起始和结束位置(答案的跨度,span)。

BERT首先在问题前面添加special classification token[CLS]标记,然后问题和段落连在一起,中间使用special tokens[SEP]分开。序列通过token Embedding、segment embedding 和 positional embedding输入到BERT。最后,通过全连接层和softmax函数将BERT的最终隐藏状态转换为答案跨度的概率。

flashgene.com/archives/ 讲了bert用于阅读理解任务

相应的ner也是在最后用softmax来计算各个标签的概率

For each task, we simply plug in the task- specific inputs and outputs into BERT and fine- tune all the parameters end-to-end. At the in- put, sentence A and sentence B from pre-training are analogous to (1) sentence pairs in paraphras- ing, (2) hypothesis-premise pairs in entailment, (3) question-passage pairs in question answering, and (4) a degenerate text-? pair in text classification or sequence tagging. At the output, the token rep- resentations are fed into an output layer for token- level tasks, such as sequence tagging or question answering, and the [CLS] representation is fed into an output layer for classification, such as en- tailment or sentiment analysis.

这里就明确的告诉我们,两个大类的下游任务。

要么把token的表示送入到output layer做token-level的任务,例如ner或者qa任务;

要么就把cls的表示送入到output来做分类,例如en-tailment或者情感分析。

note:其中提到的(4)的表示是退化的text-pair任务,就是一个single的句子。

GPT可以做生成任务,但是BERT不可以。因为BERT就不是一个正常的语言模型(从左往右或者反过来)

mp.weixin.qq.com/s/CUVW

这里有给出比较简单但是很好理解的介绍。

因为 bi-rnn、bi-lstm 的『双向』,并不是像 bert 一样,将上下文用同一套模型参数进行编码,而是用两个分开的单向rnn去处理,只不过共享了输入,以及输出时进行拼接。

参考:

zhuanlan.zhihu.com/p/89

四、具体的预训练方式

如何从0开始训练一个完整的bert

1. 将网络上的demo跑通

下载网络上的预训练模型,然后使用里面附带的vocab.txt进行。

BERT_BASE_DIR=uncased_L-12_H-768_A-12
python create_pretraining_data.py \
--input_file=./sample_text.txt \
--output_file=/tmp/tf_examples.tfrecord \
--vocab_file=$BERT_BASE_DIR/vocab.txt \
--do_lower_case=True \
--max_seq_length=128 \
--max_predictions_per_seq=20 \
--masked_lm_prob=0.15 \
--random_seed=12345 \
--dupe_factor=5

python run_pretraining.py \
--input_file=/tmp/tf_examples.tfrecord \
--output_dir=/tmp/pretraining_output \
--do_train=True \
--do_eval=True \
--bert_config_file=$BERT_BASE_DIR/bert_config.json \
--init_checkpoint=$BERT_BASE_DIR/bert_model.ckpt \
--train_batch_size=32 \
--max_seq_length=128 \
--max_predictions_per_seq=20 \
--num_train_steps=20 \
--num_warmup_steps=10 \
--learning_rate=2e-5

2. 等到这个demo通了之后,我们就需要利用自己的数据,来重新训练。

如何生成数据。根据一篇新发布的工作。里面讲了如何生成数据。

换句话说,如果我们有现成的数据,是可以直接跑的。当然,我们需要注意的是参数到底应该如何设定会比较合适。

这方面我们需要对整个模型的内容比较熟悉和了解。

首先我们来看一下数据长什么样子

下面是训练语料。一行一句话,用空行来区分不同的doc。

这个数据的生成,不是很费事,自己用电脑多开几台,100个G的数据处理一下。时间还是很久的。

注意在生成训练语句的时候,我们是从corpus里面找句子凑起来,生成一个句子对,合起来这个句子对的长度不能超过我们设定的max_seq_length.

OPPO手机此前下方无背光的三大金刚键被不少人吐槽已久,如今OPPOR9在Home键两侧分别放置了一枚隐藏式触控按键,而背光不点亮的情况下基本看不到,点亮后的背光亮度也比较柔和,在晚上不会感到刺眼。

七十年代的日本曾经出现过比较明显的产能过剩,美国欧洲国家也都出现过产能过剩。
中国特别是在九十年代末以来,中国经济告别了短缺经济之后,产能过剩问题一直是一个挥之不去的,对中国经济影响非常大的一个隐患。
历数这十几年近二十年的时间,大致有三次比较严重的产能过剩。
一架战机系统复杂、设备众多,对应的维护保障仪器繁多。
马登武常说,搞飞机维护保障不是搬家过日子,一切要做到高效、快捷。
为此,他把心思都放到设备集成,提高保障能力上。
座谈会上,中越双方表示,新的一年,双方要继续加强各个领域的合作,共同推进跨境经济合作区建设,特别是中越北仑河二桥等重大项目的建设,继续加强在边境贸易、跨境旅游、跨境金融、劳务合作、警务合作、边境管控、打击走私等领域的交流合作,推动两市的合作发展取得更大的成绩。

作为具有影响力的高科技中心,德国在促进隐私、数据安全等领域的企业的发展尤有突出表现。
思科称,它计划帮助德国加速其“数字化”进程,具体措施包括投资该国的创业公司和风投基金,以及与公共部门合作展开技术项目。
微软强制要求用户升级到新版IE(又或者转用Windows10及其默认浏览器Edge)之举,迫使用户换用别的浏览器。

下面是vocab.txt。

构建词汇的脚本

kwonmha/bert-vocab-builder



使




注意其中英文 会使用wordpiece。

wordpiece意义在于,比如"loved","loving","loves"这三个单词。其实本身的语义都是“爱”的意思,但是如果我们以单词为单位,那它们就算不一样的词,在英语中不同后缀的词非常的多,就会使得词表变的很大,训练速度变慢,训练的效果也不是太好。BPE算法通过训练,能够把上面的3个单词拆分成"lov","ed","ing","es"几部分,这样可以把词的本身的意思和时态分开,有效的减少了词表的数量。并且一定程度上可以避免oov的情况。【没有见过loved,但是见过lov,有见过ed,那不就结了】

接着我们要使用这些语料生成tensorflow输入的数据格式,我们需要用到词表。

创造tfrecord的脚本语句我已经提供了,大家可以参照使用。这个过程也是比较久的。

我用72核的机器,最低配置的内存。6台机器要跑五六个小时吧。我没有仔细计算也。似乎粗略估算:

3min/cpu核 可以处理5MB左右的数据

新建的VM虚拟机,因为无法实现对bucket的写入权限,所以可以执行:

gcloud auth application-default login

下面是 training tips from google

Therefore, one good recipe is to pre-train for, say, 90,000 steps with a sequence length of 128 and then for 10,000 additional steps with a sequence length of 512. The very long sequences are mostly needed to learn positional embeddings, which can be learned fairly quickly. Note that this does require generating the data twice with different values of max_seq_length.

我们需要阅读一下各个参数分别代表什么意思

【注意在训练的时候,训练的代码和创建tfrecord的代码中的句子长度设置要一致,或许训练的小于tfrecord的应该也可以。我没测试,每次跑一下都是钱,有点心疼。但是大于一定会报错】

  python3 create_pretraining_data.py  \
--input_file=gs://clue_storage/clue_pretrain_corpus/raw_txt_corpus/train/clue_pretrain_$l.txt \
--output_file=gs://clue_storage/clue_pretrain_corpus/tfrecords/bert_base_128_c5_vocab8k/clue_pretrain128_$i.tfrecord \
--vocab_file=./bert_base/vocab_clue.txt \ # 我们使用的词表
--t2s=True \ # 我们是否要进行简体和繁体的转化
--do_lower_case=True \ # 是否要做大写转小写
--max_seq_length=128 \ # 句子的最大输入长度
--max_predictions_per_seq=20 \ # 下一句话的预测
--masked_lm_prob=0.15 \ # mask单词的概率
--random_seed=12345 \

预训练。在warmup 阶段学习率会比之后低,之后学习率恢复正常。学习率的改变一般有以下几种方式,当然这个 我没有去查,,,dfs太多了。

"warmup_cosine": WarmupCosineSchedule,

"warmup_constant": WarmupConstantSchedule,

"warmup_linear": WarmupLinearSchedule

python3 run_pretraining.py \
--input_file=$INPUT_DIR \
--output_dir=$OUT_PUT_DIR \
--do_train=True \
--do_eval=True \
--bert_config_file=./bert_base/bert_config.json \ # 输入的config参数配置
--train_batch_size=4096 \ batch。batch理论上是越大越好的。但是放不下,所以就用mini-batch。
--max_seq_length=512 \
--max_predictions_per_seq=51 \
--num_train_steps=500,500 \ # 这里意思是 一共训练多少步。具体的steps和epochs之间的计算,和数据量有关系。
--num_warmup_steps=10,000 \ # 预热的步骤
--learning_rate=0.00176 \ # 学习率
--save_checkpoints_steps=2000 \

paper的建议

We train with batch size of 256 sequences (256 sequences * 512 tokens = 128,000 tokens/batch) for 1,000,000 steps, which is approximately 40 epochs over the 3.3 billion word corpus. We use Adam with learning rate of 1e-4, β1 = 0.9, β2 = 0.999, L2 weight decay of 0.01, learning rate warm-up over the first 10,000 steps, and linear decay of the learning rate

至于超参数怎么选择,这个是强任务,数据相关的,可以参考一些已经训练好的模型的参数。

接下来我稍微介绍和解释一下,max_predictions_per_seq 以及 masked_lm_prob。我们就看到了,两者之间到底是怎么计算的。并且,这个max_seq 和 maxprediction 在createdata以及做pretrain的时候必须要保持一致。

The max_predictions_per_seq is the maximum number of masked LM predictions per sequence. You should set this to around max_seq_length * masked_lm_prob (the script doesn't do that automatically because the exact value needs to be passed to both scripts).

from: What is suitable max_predictions_per_seq size when max_seq_length set to 512? · Issue #516 · google-research/bert

至于优化器和对应的激活函数,论文选择了Adam和gelu (我记得上学的时候我试过gelu确实比relu效果好)

结果一般为:

mlm最好要达到0.70以上, nsp基本接近满分。可以不用,参加robert。
具体训练要具体看,问题出在哪里了,得仔细查看才可以

五、如何应用到下游NLP任务中

我们如果去网上看很多资料,会发现一个神奇的现象,教程和复现大多以Pytorch为主,很少有人纠结TF怎么实现的。我也不是大神,所以我们完全可以将TF作为一个工具包来使用。除非你要对模型结构做修改。这个会在第六章中做描述。

首先介绍一个工作:CLUEbenchmark/CLUE

ok接下来,我来仔细和大家分享四个大类型的下游任务,分别是pairwise的文本分类,single sentence的文本分类,Squad为代表的span阅读理解,NER为代表的token-level的细粒度任务。

在glue中有相应的任务对应,我这里选择其中的任务做介绍,对于各个任务bert都给出了自己推荐的hyper-params

For fine-tuning, most model hyperparameters are the same as in pre-training, with the exception of the batch size, learning rate, and number of train- ing epochs. The dropout probability was always kept at 0.1. The optimal hyperparameter values

我们看到了,超参数中,我们主要修改的是batchsize,learning rate 以及 training epochs,dropout率也要保持。

tips,可以修改max的sentence length,但是不能大于pretrainingmodel的length,可以小于等于。

官方给出了推荐的参数,我们也可以使用试试看:

Batch size: 16, 32
Learning rate (Adam): 5e-5, 3e-5, 2e-5 
Number of epochs: 2, 3, 4
We also observed that large data sets (e.g., 100k+ labeled training examples) were far less sensitive to hyperparameter choice than small data sets. Fine-tuning is typically very fast, so it is rea- sonable to simply run an exhaustive search over the above parameters and choose the model that performs best on the development set.

如果我有钱,我把所有的参数都试一试给你看。。。

上面论文中的图片已经说明了具体的各个任务的finetune指南,我们要做的就是在最后添加一个output layer,所以只需要学习少量的参数就可以用来学习了。图中,a和b是seq-level的任务,c和d是token-level的任务。E表示input embedding(word,seg,position)Ti表示token_i的上下文表示,cls是分类用的富豪,sep是表示一个句子结束的富豪。

我突发奇想的把GLUE的任务在这里用中文描述一下,当然把SuperGLUE放在最后也描述一下,大家来感受一下这个东西。最后我把CLUE的任务也会一一对应起来。大家感受一下为什么要这样构造数据集,同时这也是经典的NLP的研究方向。

MNLI 句子对的二分类。任务是一个entailment classification task。任务是给定一个句子对,来判断第二个句子对第一个句子来说到底是一个entailment,contradiction还是neural。意思就是,一个意思或者加成了,还是矛盾还是中立(无关)
QQP 句子对的二分类任务。是quora的问题对而分类任务,目的是判断在Quora上面问的这两个问题是不是等效的。这个是社区问答相关的工作。Community Question Answering,知乎也是这个类型的,这里推荐一下杨敏老师的工作,太强了
QNLI,句子对的二分类任务。问题NLI。是StanfordQA数据集的一个版本,这个版本被转化为了二分类任务。正类是Q和包含答案的sentence,负类是Q和不包含答案的并且来自同一个paragraph的sentence
SST-2 单一句子的二分类问题。从电影评论中抽取的,并且是人类标注的极性。
CoLA 单一句子的二分类问题。目的是判断一个英语句子是否从语法上是可以接受的
STS-B 句子对的分类。是从新闻标题和别的地方找来的。标记了这两句话的相似度,用1-5。
MRPC是微软研究院做的段落Corpus,包含了句子对,这是自动从在线新闻中抽取出来的,人工标注了句子对是否从语义上一致。
RTE 句子对的二分类。和MNLI类似的任务。但是训练数据更少。
Note that we only report single-task fine-tuning results in this paper. A multitask fine-tuning approach could poten- tially push the performance even further. For example, we did observe substantial improvements on RTE from multi- task training with MNLI. 
【google 论文原话,我觉得像是白说把】
WNLI 没有选择
NER

对应的在构造数据的时候,abcd分别如下构造:

a
输入[CLS]sentence A [sep] sentence B [sep]
输出[CLS]进入softmax
b
输入[CLS]sentence A [sep]
输出[CLS]进入softmax
c
输入[CLS]sentence A(Question) [sep] sentence B (paragraph)[sep]
输出[sentence B 的 token representation]进入softmax
d
输入[CLS]sentence A [sep]
输出sentence A的token representation进入softmax

ok具体的代码,我明天再放出来给大家看:


六、如何对Bert做修改-前处理、后处理与正则

前处理与后处理是简单而又好实现的一种方法。即在送入网络之前对数据做一定的处理变换,等到网络将数据输出之后做一定的处理变化。正则,可以在开始添加,也可以在后面添加,下面我会分别举例子。

6.0 预处理

不管是预处理还是后处理,都是task-specific的工作。我也只能举脑海中第一时间蹦出来的例子,大家一起交流一下。

我这里举出的例子,主要是一个问题抽象化的例子。比如说,我们要如何才能将bert运用到文本去重这个任务重,一般来说我们会对文本进行粗排,然后将这些文本形成文本对,然后直接当作一个文本分类的任务来做。

另一个,对GLUE的COPA任务,要怎么做?

最直接的办法,就直接把任务数据输入进去就好了,我们也不用管别的,让模型自己学去吧。

另一种办法是什么呢?

我们可以把文本的前后顺序调换一下,这样是不是就隐含了所谓的“推理”这样的逻辑呢?当然,可以更进一步的添加,so,why之类的词语来表达类似的意思。(这些词不能被当作stopwords给去掉。

我说的这是比较直觉的方法,一般来说,考察的是对问题的理解和建模,对后续的算法理解要求并没有那么高,当然如果有理解会更好。例如bert在做短文本相似度判断的时候,效果如何?超长文本呢?

6.1 分词后处理:

输入:我今天很高兴,看了小李杜发的文章很开心

网络当作黑盒子,最后输出了一个结果:我 今天 很 高兴 看 了 小李 杜 发的 文章 很 开心。

但是我们认为小李杜应该是一个词,怎么办呢?在最后添加一个字典对整个输出结果做扫描,如果发现应该粘连在一起的单词,我们将其粘连起来。

是不是很蠢啊,但是这个似乎是很有效的方法哎。

6.2 添加正则

这个我要推荐的是这个同学的工作。我看到很不错的问答系统中语义匹配的『杀手锏』。里面有讲到它是怎么对模型结构做修改的。

我就介绍一下他的工作吧。

七、Bert的对比,轻量化改进,后续衍生品

Comparison of BERT, ELMo ,and OpenAI GPT。

fine- tuning approaches:BERT and OpenAI GPT

feature-based:ELMo

论文主要是将bert和GPT做了比较,最大的不同在于双向,以及两个预训练任务(MLM和NSP)这些内容文中都有,我来翻译一下~:

• GPT is trained on the BooksCorpus (800M words); BERT is trained on the BooksCor- pus (800M words) and Wikipedia (2,500M words). 数据集
• GPT uses a sentence separator ([SEP]) and classifier token ([CLS]) which are only in- troduced at fine-tuning time; BERT learns [SEP], [CLS] and sentence A/B embed- dings during pre-training. sep和cls的使用方法不同,由于NSP的存在所以有了A/B编码
• GPT was trained for 1M steps with a batch size of 32,000 words; BERT was trained for 1M steps with a batch size of 128,000 words. 都是100wstep,但是batchsize更大(这是炫富的意思么
• GPT used the same learning rate of 5e-5 for all fine-tuning experiments; BERT chooses a task-specific fine-tuning learning rate which performs the best on the development set. fine-tuning的时候learning rate在修改

八、Bert在非文本领域的应用前景

就不胡说了吧。主要还是transformer的应用作为特征提取。爱奇艺做过相关的技术,可以搜索一下,就当帮朋友推荐他们的工作嘿嘿。

九、胡说一下对过去的总结和对未来的看法


参考文献:

除了文中我直接列出来的,我还看了:

张俊林老师对bert的解读:zhuanlan.zhihu.com/p/65


重磅!忆臻自然语言处理-学术微信交流群已成立

可以扫描下方二维码,小助手将会邀请您入群交流,

注意:请大家添加时修改备注为 [学校/公司 + 姓名 + 方向]

例如 —— 哈工大+张三+对话系统。

号主,微商请自觉绕道。谢谢!


推荐阅读:

全连接的图卷积网络(GCN)和self-attention这些机制的区别与联系

图卷积网络(GCN)新手村完全指南

论文赏析[ACL18]基于Self-Attentive的成分句法分析