Bert调用
2018年的10月11日,Google发布的论文《Pre-training of Deep Bidirectional Transformers for Language Understanding》,成功在 11 项 NLP 任务中取得 state of the art 的结果,赢得自然语言处理学界的一片赞誉之声。
目前大多数NLP任务研究中,会调用bert预训练模型,大量实验证明,bert的实验对下游任务会起到一定的提升作用。
那么这里将介绍一下如何调用bert预训练模型,以及相关的用法。
安装transformers
pip install transformers==4.3.0
我安装的是4.3.0的版本,以下的演示也是基于此。
BertTokenizer
Bert的切词器,附带Bert的字典,因为对词向量化需要先找到字典中对应的序号,才能找到它的词向量。
from transformers import BertTokenizer
tokenizer = BertTokenizer.from_pretrained('bert-base-uncased') # 加载base模型的对应的切词器
print(tokenizer) # 打印出对应的信息,如base模型的字典大小,截断长度等等
token = tokenizer.tokenize("Don't Make sUch a fuss,get StUFf!") # 切词
print(token) # 切词结果
indexes = tokenizer.convert_tokens_to_ids(token) # 将词转换为对应字典的id
print(indexes) # 输出id
tokens = tokenizer.convert_ids_to_tokens(indexes)# 将id转换为对应字典的词
print(tokens) # 输出词
# 使用这种方法对句子编码会自动添加[CLS] 和[SEP]
input_ids = torch.tensor(tokenizer.encode("Don't Make sUch a fuss,get StUFf!")).squeeze(0)
print(input_ids)
cls_id = tokenizer._convert_token_to_id('[CLS]')
sep_id = tokenizer._convert_token_to_id('[SEP]')
print(cls_id, sep_id)
输出如下:
BertModel
输入bertmodel的句子的开头和结尾需要自己添加上[CLS]和[SEP],才能够正确的使用bert,或者直接调用BertTokenizer.encode,则会自己自动的添加。
转换成id即可输入bert获得对应的句子编码和词向量了。
import torch
from transformers import BertTokenizer, BertModel
tokenizer = BertTokenizer.from_pretrained('bert-base-uncased')
model = BertModel.from_pretrained("bert-base-uncased")
input_ids = torch.tensor(tokenizer.encode("Don't Make sUch a fuss,get StUFf!")).unsqueeze(0) # Batch size 1
input_ids2 = torch.tensor(tokenizer.encode("how old you")).unsqueeze(0) # Batch size 1
outputs = model(input_ids)
outputs2 = model(input_ids2)
print(outputs[0].shape) # 词的向量表示
print(outputs[1].shape) # 句子的向量表示
print(outputs2[0].shape)
print(outputs2[1].shape)
输出:
可见[CLS]和[SEP]也会被转换为向量输出
我们可以看一个例子:
import torch
from transformers import BertTokenizer, BertModel
tokenizer = BertTokenizer.from_pretrained('bert-base-uncased')
model = BertModel.from_pretrained("bert-base-uncased")
input_ids = torch.tensor(tokenizer.encode("good night")).unsqueeze(0) # Batch size 1
input_ids2 = torch.tensor(tokenizer.encode("good food")).unsqueeze(0) # Batch size 1
outputs = model(input_ids)
outputs2 = model(input_ids2)
print(outputs[0][0][1]) # 取出good night 中的 good
print(outputs2[0][0][1]) # 取出good food 中的 good
输出结果:
看的出来,同一个词,在不同的句子中词向量是不同的。
因此bert能够很好的解决一次多义的现象,这便是它的魅力所在