了解Transformers
transformers是最新的BERT开源github项目,他的前身是pytorch-transformers 和 pytorch-pretrained-bert,现在已经改名了,并支持最新的很多流行的用BERT实现的模型,博主应最近的自然语言课程处理要求也在广泛查找csdn,发现之前的很多讲解关于最新的transformers较少,也不够细致,只讲到了做一句话embedding的代码,实际上BERT是支持两句话的。在本文我们就将讲解在pytorch框架下如何使用最新的transformers做Bert以及Roberta的embedding。
安装Transformers
如果你已经安装好了transformers并且环境无误,请自行跳过这部分吧!
安装CUDA 10.1
博主的显卡GTX1050ti支持CUDA 10.1,不同型号的显卡可能有不同的适配,请自行在网上查找资料进行安装。CUDA的官网地址点击这里。
笔者安装的版本如图,安装完CUDA之后呢,下载可以适配的CuDNN,安装地址点击这里。
下载完成后解压压缩包,将解压出来的所有东西复制粘贴到C盘的CUDA该文件夹中。
配置python环境
OK,CUDA配置完了,接下来就是Python环境的配置。python版本是3.6,建议使用Anaconda配置环境,懂的都懂。看好torch和tensorflow的版本!!!直接丢个pip list:
Package Version
---------------------- -------------------
absl-py 0.10.0
astunparse 1.6.3
cachetools 4.1.1
certifi 2020.6.20
chardet 3.0.4
click 7.1.2
filelock 3.0.12
future 0.18.2
gast 0.3.3
google-auth 1.21.1
google-auth-oauthlib 0.4.1
google-pasta 0.2.0
grpcio 1.31.0
h5py 2.10.0
idna 2.10
importlib-metadata 1.7.0
joblib 0.16.0
Keras-Preprocessing 1.1.2
Markdown 3.2.2
numpy 1.18.5
oauthlib 3.1.0
opt-einsum 3.3.0
packaging 20.4
Pillow 7.2.0
pip 20.2.2
protobuf 3.13.0
pyasn1 0.4.8
pyasn1-modules 0.2.8
pyparsing 2.4.7
regex 2020.7.14
requests 2.24.0
requests-oauthlib 1.3.0
rsa 4.6
sacremoses 0.0.43
scipy 1.4.1
sentencepiece 0.1.91
setuptools 49.6.0.post20200814
six 1.15.0
tensorboard 2.3.0
tensorboard-plugin-wit 1.7.0
tensorflow 2.3.0
tensorflow-estimator 2.3.0
termcolor 1.1.0
tokenizers 0.8.1rc2
torch 1.6.0+cu101
torchvision 0.7.0+cu101
tqdm 4.48.2
transformers 3.1.0
urllib3 1.25.10
Werkzeug 1.0.1
wheel 0.35.1
wincertstore 0.2
wrapt 1.12.1
zipp 3.1.0
使用Transformers
终于终于进入最激动人心的使用环节了!对了,值得一提的是transformers这个库中有用的东西太多了,推荐大家去看看官方的文档和仓库。
使用BERT
我的代码是在有CUDA的显卡机器上运行的,此外没有大显卡就别做尝试了,我的GTX1050ti实测会显存溢出,如果有人有解决方法欢迎评论。最后我的代码是在服务器上跑的。
# 导入模型和分词器
from transformers import BertTokenizer,BertModel,RobertaTokenizer, RobertaModel
tokenizer = BertTokenizer.from_pretrained('bert-base-cased') # Bert的分词器
bertmodel = BertModel.from_pretrained('bert-base-cased',from_tf=True).cuda() # load the TF model for Pytorch
text = " I love python ! "
# 对于一个句子,首尾分别加[CLS]和[SEP]。
text = "[CLS] " + text + " [SEP]"
# 然后进行分词
tokenized_text1 = tokenizer.tokenize(text)
indexed_tokens1 = tokenizer.convert_tokens_to_ids(tokenized_text1)
# 分词结束后获取BERT模型需要的tensor
segments_ids1 = [1] * len(tokenized_text1)
tokens_tensor1 = torch.tensor([indexed_tokens1]).cuda() # 将list转为tensor
segments_tensors1 = torch.tensor([segments_ids1]).cuda()
# 获取所有词向量的embedding
word_vectors1 = bertmodel(tokens_tensor1, segments_tensors1)[0]
# 获取句子的embedding
sentenc_vector1 = bertmodel(tokens_tensor1, segments_tensors1)[1]
########################################
# 两个句子
########################################
# 在第二个句子末尾加个[EOS]
text2 = " I love Java! "
text3 = " I love C#! "
text = "[CLS] " + text2 + " [SEP]"
tokenized_text2 = tokenizer.tokenize(text)
indexed_tokens2 = tokenizer.convert_tokens_to_ids(tokenized_text2)
segments_ids2 = [0] * len(tokenized_text2) # 第一个句子的索引为0
text = text3 + " [EOS]"
tokenized_text3 = tokenizer.tokenize(text)
indexed_tokens3 = tokenizer.convert_tokens_to_ids(tokenized_text3)
segments_ids3 = [1] * len(tokenized_text3) # 第二个句子的索引为1
segments_ids = segments_ids2 + segments_ids3
indexed_tokens = indexed_tokens2 + indexed_tokens3
tokens_tensor = torch.tensor([indexed_tokens]).cuda() # 将list转为tensor
segments_tensors = torch.tensor([segments_ids]).cuda()
# 获取所有词向量的embedding
word_vectors = bertmodel(tokens_tensor, segments_tensors)[0]
# 获取句子的embedding
sentenc_vector = bertmodel(tokens_tensor, segments_tensors)[1]
使用Roberta
Roberta的使用方法和Bert有些不同,这是BERT的一个改进版本。官方示例使用的代码如下:
如果想要做两个句子的embedding,可以对text做和BERT一样的操作,加[CLS],[SEP],[EOS]就可以了!
from transformers import RobertaTokenizer, RobertaModel
import torch
tokenizer = RobertaTokenizer.from_pretrained('roberta-base')
model = RobertaModel.from_pretrained('roberta-base')
text = "Replace me by any text you'd like."
encoded_input = tokenizer(text, return_tensors='pt')
output = model(**encoded_input)
# 在这里补充说明以下encoded_input是一个字典,保存了两个向量。如果想用显卡加速Roberta的计算,要把他们放到显存上,代码如下:
'''
for key in encoded_input.keys():
encoded_input[key] = encoded_input[key].cuda()
'''
至此关于如今大火大热的BERT的调用说明就结束了!!