BERT初学者九问

0.前言

  • 本文总结了初学者对BERT的一些常见疑惑
  • BERT 的五个关键词: Pre-training、Deep、Bidirectional、Transformer、Language Understanding

1. Bert是什么?

首先要明白什么是预训练模型【这个我后面再更~】。在这个基础上,我们来看 Bert 模型。

1.1 定义

  • 标志BERT出身的那篇论文的标题是BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding
  • BERT( Bidirectional Encoder Representation from Transformers,其中文译名应该就是“基于transformers 的双向(深度)编码表示”)

Bert is a method of pretraining language representations

  • BERT是首个无监督的、深度双向预训练NLP模型,仅使用纯文本语料库进行训练。BERT可以进行多任务学习,也就是说,它可以同时执行不同的NLP任务。

1.2 特点

  • Bert最关键两点,一点是特征抽取器采用Transformer;第二点是预训练的时候采用双向语言模型。
  • BERT 是从大量的文本中经过半监督训练得来

2.可以用BERT干什么?

You can either use these models to extract high quality language features from your text data, or you can fine-tune these models on a specific task (classification, entity recognition, question answering, etc.) with your own data to produce state of the art predictions.

主要可以用于两种用途,也就是:

  • extract feature
  • fine-tuning model
    其实这两种不同方式带来的最后效果相差不远。

3.Embedding 有什么用?

First, these embeddings are useful for keyword/search expansion, semantic search and information retrieval.
【即使没有关键字重叠,还是可以找出比较相似的句子】

Second, and perhaps more importantly, these vectors are used as high-quality feature inputs to downstream models.

4.BERT 和 word2vector

这两者都是nlp发展上的一个缩影,只不过word2vec已经逐渐被遗忘了,而bert尚活于世。

4.1 二者的关系

个人理解是:BERTword2vec的高级进化版,进化的后果【用进废退】就是:BERT广泛成长,word2vec逐渐废弃。

4.2 二者的区别

Bertword2vec 的区别是:word2vec中每个单词都有一个固定的表示,而与单词出现的上下文无关【为什么啊???】;bert生成的单词表示是由单词周围的单词动态形成的。

4.3 Bert 也做 word embedding吗?

Bert 有自己的word to vector方法,你可以将其看做是embedding生成机制中的一种。但是Bert做的embedding是动态的,即使同一个单词在不同的句子中得到的embedding可能都不是一样的。Bert 可以得到word的embedding,句子的embedding。但有个问题是:BERT 生成的 embedding 不是固定的,它没有固定的层用于生成embedding,所以就需要你自己考虑由哪些层的输出得到embedding就OK了。

4.4 BERT 相比 word2vec 的优势是什么?

BERT produces word representations that are dynamically informed by the words around them.【最主要的就是利用了上下文信息,每个单词都不是一座孤岛】

5. BERT、Transformer、Attention之间的关系

Attention 是一种算法,可以将其看成是平级于 RNN,LSTM 的一种方法。这种方法的特别之处在于它对一个句子不同的词赋以不同的优先级。
transformer 是一种架构,它基于Attention 机制实现。所谓的transformer也就是数个ecoder layer叠加得到的块。【同时需要注意,我们平常也会使用一个包叫做Transformer,这个包实现了诸如BERT,GPT这种常用且著名的算法,这个包由著名的hugging face团队开发】
BERT是一种集合transfomer+双向检索思想得到的算法,它可以很好的提取出文本中的信息。

6. BERT tokenize 的过程

6.1 常见术语

  • sentence

a “sentence” can be an arbitrary span of contiguous text, rather than an actual linguistic sentence.A “sequence” refers to the input token sequence to BERT, which may be a single sentence or two sentences packed together.

  • Tokens:标记
    BERT初学者九问_第1张图片常用的[CLS],[SEP]都是token,只不过他们是special tokens;tokens 也可以是常见的汉字,也可以是常见的英语单词。但是也有可能把常见的单词拆分成几个字母的组合。

Here are some examples of the tokens contained in our vocabulary.
说明单词表中存在的词就可以称之为 tokens 。

  • Tokenize: 将文本处理成token 的过程就是tokenize。这个过程常常使用Transformer中的Tokenizer类
  • Tokenizer:这个是代码中的类,用于实现tokenize的具体操作。例如BERT 有一个tokenzier 就叫做 BertTokenizer

6.2 tokenize的过程

预训练好的模型是在一个固定大小的单词表上搞出来的,这个单词表包含四种词汇:

  1. 整个单词
  2. 单词的开头部分
  3. 单词的子成分
  4. 独立的字符
    当然,任何单词表也不一定能涵盖text中所有的单词。其中OOV:out of vocabulary;UNK:unknown vocabulary就是常出现的两种情况。对于单词表无法涵盖所有的单词,BERT并没有用OOV,UNK来表示这些不认识的单词,而是将不认识的单词拆分成多个部分。基于这个模型【指的是WordPiece模型】,tokenize的过程是:
    01.先查找单词表中有没有这样的完整单词
    02.如果没有,则拆分成概率最大的几个零散单词
    03.如果还不行,则拆分成字符

讲完4,5两大部分,我们再来看看part 6,即怎么用BERT 提取出 embedding

7. 如何用Bert提取出embedding?【如何用NLP预训练模型做word embedding?】

7.1 先看别人怎么实现

下面这两个答案都是出自知乎问题 我觉得写得还行,就贴过来了。

答:以huggingface为例,你可以直接拿一个预训练bert模型,然后tokenize text 放到模型里跑,输出结果是一个向量,这个向量就是embedding,之后可以用这个向量进行进一步训练,无论是分类也好,还是别的应用。

把最后的classifier扔掉,feed-forwarding 以后的结果就是embedding。需要句子的embedding的话最简单的方法是做mean pooling。

根据 sentence 得出 embedding的过程可以参考文章 来实现,这文章写的真的超级好。【英语不好读起来真是超要命

7.2 自己实现

光说不练假把式,这些东西还是需要自己动手,使用bert生成embedding是个非常简单的过程。

"""
实现bert做embedding
"""
import torch
from transformers import BertTokenizer, BertModel # 导入transformer 的包
#torch.set_printoptions(profile="full") # 输出tensor的整个部分
"""from_pretrained()方法是类PreTrainedModel的一个方法"""
model = BertModel.from_pretrained("bert-base-uncased")
tokenizer = BertTokenizer.from_pretrained('bert-base-uncased')

inputs = tokenizer("hello,my dog",return_tensors='pt')
# 执行model[BertModel实例]的forward()方法,但是在执行之前,仍然做了很多其他的事情
# 比如因为传入的inputs是一个字典,在使用命令关键字做参数的时候,就涉及到了解包操作等等
outputs = model(**inputs)

# The last hidden-state is the first element of the output tuple
# outputs 是一个多维的tensor, 其中第一维就是最后一个隐层的输出,这里我们直接取最后一个隐层的输出作为sentence 的 embedding
last_hidden_states = outputs[0]

print(last_hidden_states)
print(last_hidden_states.size()) 

"""
1. inputs 是个字典,的内容如下:
{'input_ids': tensor([[  101,  7592,  1010,  2026,  3899,  2003, 10140,   102]]), 
'token_type_ids': tensor([[0, 0, 0, 0, 0, 0, 0, 0]]), 
'attention_mask': tensor([[1, 1, 1, 1, 1, 1, 1, 1]])
}


2.如果我的句子是 "hello,my dog is cute",那么得到last_hidden_state 的size 就是torch.Size([1, 8, 768]),

如果我的句子是"hello,my dog",那么得到的last_hidden_state 的 就是 torch.size([1,6,768]) 
"""

得到的每个单词的 embedding 如下所示,因为这里共有4+2个token,所以其各个embedding显示如下:
BERT初学者九问_第2张图片上面这段代码我放到了github中。库里面还有更好的内容哦,也在不断整理中~

7.3 关键点

我觉得关键点主要就如下几个:

  • 熟悉BERT的输入、输出长什么样子
  • 熟悉BERT的模型结构,只有这样才能理解BERT的工作流程,才能清楚数据在BERT中的流动过程
    上面这两点是比较关键的,
  • 再次者,我觉得熟悉源码操作的过程是比较重要的

8.BERT实战相关?

8.1 如何使用BERT?

可以使用 Hugging Face组织提供的 Transformers包,里面提供了Bert的实现。其中transformers提供了将BERT应用到不同下游任务【token classification,text classification....】的许多类。

transformers provides a number of classes for applying BERT to different tasks (token classification, text classification, …).

  • 安装包
    可以采用普通命令进行安装pip install transformers
    这里我建议可以尝试源码安装,毕竟后面会常用到bert,阅读其源码也是一个基本学习方法。

  • 使用包
    import transformers

  • 导入包中指定的模型
    from transformers import BertModel, BertTokenizer
    这句话的含义是从模块transformers中导入BertTokenizerBertModel。这里请记住BertModel 这个类,可以说这是源码中较为重要的一个类了。以后肯定会更加经常的碰到~

  • 指定格式的输入
    因为Bert是一个预训练好的模型,所以有很严格的数据输入格式。格式主要如下:
    每个sentence都用SEP, CLS 分割;分割得到的tokens必须与代码中预训练的BERT模型使用相一致的的词表【也就是我们在下载的文件中常见到的vocab.txt文件】;Tokens的Token IDs,来自于BERT 的tokenzier;Mask IDs:表明句中的元素谁是tokens,谁是被 padding 的元素; Segment IDs :用于区分不同的句子;Positional Embeddings: 用于展示剧中的token位置
    这部分不再赘述,可以在参考博客中查看。
    上面这些东西都可由 BertTokenizer的实例 的tokenize()方法得到。

8.2 BERT tokenizer 是基于什么模型构建的?

BERT tokenizer was created with a WordPiece model.

这个部分尚未深入,待更新吧~

9.BERT结构

其实觉得这部分应该拿到前面去写,但是缘分在这儿,就放这儿了~

9.1 体系结构

提纲挈领的一句话就是:

BERT is basically a trained Transformer Encoder stack.

我们常用的BERT分成bert-basebert-large 版,但是无论哪一种结构都是由一些encoder layers构成的,这些encoder layers又被叫做Transformer blocks。如下图所示:
BERT初学者九问_第3张图片但实际代码中使用 BERT 的架构同论文中BERT的架构是稍有不同的【大致相似】。

参考资料

  • http://jalammar.github.io/illustrated-bert/
  • https://mccormickml.com/2019/05/14/BERT-word-embeddings-tutorial
    应该是这篇文章是国内大多数BERT相关博文的材料来源了吧,那么这篇文章主要讲什么?

we will use BERT to extract features, namely word and sentence embedding vectors, from text data.

  • https://www.zhihu.com/question/404312195
    上面这个问题提到了如何使用BERT构建 word embedding

你可能感兴趣的:(#,pytorch,nlp,深度学习,nlp,python)