Pytorch——Tokenizers相关使用

   在NLP项目中,我们常常会需要对文本内容进行编码,所以会采tokenizer这个工具,他可以根据词典,把我们输入的文字转化为编码信息,例如我们本文信息是“我爱你”将转化为[2,10,3],其中”我“在字典里对应数字2,”爱“在字典里对应数字10,经过转化之后的文本,就可以作为模型的输入了。因此我们可以知道如果字典不同,那意味着同一句话编码出来的数字也就是不同的,所以对于一个训练好的NLP模型,基本都是有着自己tokenizer工具的,比如BertTokenizer(BERT模型的),ErnieGramTokenizer(百度飞桨的ernie模型),他们这个tokenizer的使用方式大同小异,因此我们就个根据BertTokenizer这里类进行讲解和使用。

加载并使用tokenizer

1、载入预训练模型的词典

  我们可以使用以下代码加载BERT预训练模型的词典,其实我们只需要config.json和vocab.txt这两个文件就可以初始化一个BertTokenizer,因此我们需要传入这两个文件所在的目录地址即可。

from transformers import BertTokenizer
tokenizer = BertTokenizer.from_pretrained(r'./bert-base-uncased')

  这里的'./bert-base-uncased'是包含有config.json和vocab.txt这两个文件的目录地址,而这两个文件可以从官方网站下载。当然如果你在第2行代码中直接传入’bert-base-uncased‘,他会自动下载相关模型的文件到默认的地方。(我这里没有阅读源码所以也不清楚另外的tokenizer.json用来干嘛)

   完成上面的步骤之后你就得到了一个BERT的tokenizer了,下面我们来尝试使用这个tokenizer对我们的语句进行编码。

2、使用tokenizer

  刚才说到我们使用tokenizer的目的是将我们的语句编码成数字,我们可以直接传入一个句话或者一个列表的话,那么最后出来的就是编码后的语句了。直接看例子。

   如果传入单句话输出的结果是一个字典,其中'input_ids'就是这句话编码后的结果,可能有部分同学会有疑问,为什么”我爱你“3个字会编码出来5个数字额,不应该是3个么?其实着是跟你的模型有关的,BERT模型任务中需要在每一句话句首加入[CLS]符号,句尾加[SEP]符号,因此编码会增加2个,大家可以查看vocab.txt这个文件中的第102行和103行(因为编码是从0开始所以对应的是文件的102行和103行)是不是就是这两个字符。至于后面的键值对什么意思,大家可以参看BERT论文来了解。

  下面我们查看如果是使用列表来传入句子该怎么操作。

   可以看到返回的依然是键值对,其中'input_ids'也是个列表,每个元素对应的就是相应的句子得到的编码。

  其实作为NLP模型的输入,对于一些长句子我们还需要对齐进行padding使得每个batch的句子长度应该是一致的,这个过程tokenizer也可以帮我们完成,下面我们看看tokenizer的其他参数,可以参见文档了解更多,常使用的参数如下:

  • padding:给序列补全到一定长度,True or ‘longest’: 是补全到batch中的最长长度,max_length’:补到给定max-length或没给定时,补到模型能接受的最长长度。
  • truncation:截断操作,true or ‘longest_first’:给定max_length时,按照max_length截断,没给定max_lehgth时,达到模型接受的最长长度后截断,适用于所有序列(单或双)。‘only_first’:这个只针对第一个序列。’only_second’:只针对第二个序列。
  • max_length:控制padding和truncation的长度。
  • return_tensors:返回数据的类型,可选’tf’,‘pt’, ‘np’ ,分别表示tf.constant, torch.Tensor或np.ndarray类型。
  • return_token_type_ids :默认返回token_type_id(属于哪个句子)。
  • return_attention_mask :默认返回attention_mask(是否参与attention计算)。

  我们看一看例子。

  可以看到现在每个句子的编码长度都变成了12,响应的其他键值对也跟着在变化。

 3、一些其他的tokenizer方法

   tokenizer还包含有其他的一些方法,比如,

  • tokenizer.convert_tokens_to_ids(tokens):可以把tokens映射为数字id。
  • tokenizer.decode(ids):可以把数字id映射回字符串。
  • tokenizer.tokenize(sequence):把一句话进行分词变成一个一个字符。
tokens = tokenizer.tokenize('我爱中华大地')
print(tokens)
ids = tokenizer.convert_tokens_to_ids(tokens)
print(ids)
sentence = tokenizer.decode(ids)
print(sentence)

  输出结果:

   这里的[UNK]字符说明这个字(华)在字典中是不存在的因此采用这个字符来占位。

训练自己的tokenizer

  如果我自己存在一个语料,我们能不能自己训练一个模型,并且对应有一个tokenizer呢?其实是可以的,具体步骤可以参看参考网页4,其实最主要的就是采用了tokenizers模块把文本进行编码。

 

参考网页:

pytorch:Transformers入门(二) - 简书 (jianshu.com)

3-3 Transformers Tokenizer API 的使用 - 知乎 (zhihu.com)

tokenizers · PyPI

手把手教你用 Transformers 和 Tokenizers 从头训练新语言模型 - 云+社区 - 腾讯云 (tencent.com)

posted @ 2022-01-06 17:49  Circle_Wang  阅读(8624)  评论(0编辑  收藏  举报