transformers库的使用【三】数据的预处理

处理数据

在这里,将介绍如何使用Transformers库来对数据进行处理,我们主要使用的工具是tokenizer。

你可以创建一个和模型相关的tokenizer类,或者直接使用AutoTokenizer类。

tokenizer是用来把一段文本划分成单词(或者单词的一部分,标点符号等)这些划分以后的到的结果,通常称之为tokens。

接下来把这些tokens转换成numbers,这样就可以创建一个tensor来把它们送到模型当中去。

注意:如果你打算使用一个预选练的模型,那么去使用和该模型配对的tokenizer就很重要!

为了去自动的下载在预训练过程中使用的单词表(vocab)你可以使用from_pretrained()方法:

from transformers import AutoTokenizer
tokenizer = AutoTokenizer.from_pretrained('bert-base-cased')

基础使用

PreTrainedTokenizer有很多的方法,但是你需要记住的只有一个__call__:你只需要把句子直接放到tokenizer对象中,就可以得到结果:

sentence = "Hello, I'm a single sentence!"
encoded_input = tokenizer(sentence)
print(encoded_input)
{'input_ids': [101, 8667, 117, 146, 112, 182, 170, 1423, 5650, 106, 102],
 'token_type_ids': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 'attention_mask': [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]}

返回的结果是一个字典,键是字符串,而值是数字组成的列表。

input_id字段是句子中的每一个token对应的id

attention_mask和token_type_ids将在接下来进行介绍

tokenzier可以对之前得到的token_ids列表进行还原,得到原始的句子:

decoded_input = tokenizer.decode(encoded_input['input_ids'])
print(decoded_input)
[CLS] Hello, I'm a single sentence! [SEP]

如你所见,tokenizer对句子进行还原,并且会根据模型加入一些特殊的token。并不是所有的模型都需要这些特殊的token

举个例子来说,gpt2-medium模型还原的时候,只会得到和原始句子相同的句子,不会加入特殊的符号。

如果你希望它不要添加任何特殊的token,你可以在encoded时设置属性:

add_special_tokens = False

注意:在还原时,没有add_special_tokens属性

要使用skip_special_tokens,默认值为False,所以你可以通过

skip_special_token=True

来阻止添加特殊tokens

decoded_input = tokenizer.decode(encoded_input['input_ids'],skip_special_tokens=True)
print(decoded_input)
Hello, I'm a single sentence!

如果你有一组句子希望去处理,你可以把它放到一个列表里面,然后直接放到tokenizer中就可以得到结果

batch_sentences = ["Hello I'm a single sentence",
"And another sentence",
"And the very very last one"]
encoded_inputs = tokenizer(batch_sentences)
print(encoded_inputs)
{'input_ids': [[101, 8667, 146, 112, 182, 170, 1423, 5650, 102], 
[101, 1262, 1330, 5650, 102],
[101, 1262, 1103, 1304, 1304, 1314, 1141, 102]], 
'token_type_ids': [[0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0]], 'attention_mask': [[1, 1, 1, 1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1]]}

 

那么返回的结果是list组成的list

如果你希望把一组句子一次送入tokenizer来创建batch,那么你可能需要:

1、把所有的句子补全成最大长度

2、根据模型可以接收的最大长度,对所有句子做一个截断

3、返回一个tensor

那么你可以使用接下来的方法

batch = tokenizer(batch_sentences,padding=True,truncation=True,return_tensors='pt')
print(batch)
{'input_ids': tensor([[ 101, 8667,  146,  112,  182,  170, 1423, 5650,  102],
        [ 101, 1262, 1330, 5650,  102,    0,    0,    0,    0],
        [ 101, 1262, 1103, 1304, 1304, 1314, 1141,  102,    0]]), 
'token_type_ids': tensor([[0, 0, 0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0, 0, 0]]), 
'attention_mask': tensor([[1, 1, 1, 1, 1, 1, 1, 1, 1],
        [1, 1, 1, 1, 1, 0, 0, 0, 0],
        [1, 1, 1, 1, 1, 1, 1, 1, 0]])}

注意:可以清楚地看到,input_ids已经是一个tensor类型

而且所有句子经过编码后的长度都已经相同,不足的地方被补了0

处理句子对

有时你需要送一对句子到模型当中去,举个例子来说,如果你希望把两个句子十分相似的句子分成一类,或者送到一个问答的模型当中去,对于Bert来说,输入是接下来这种形式:

【CLS】 Sequence A 【SEP】 Sequence B【SEP】

你可以把两个句子同时送入tokenizer

注意⚠️这时候两个句子不要放到list中

sentence1="How old are you"
sentence2="I'm 6 years old"
encoded_input = tokenizer(sentence1,sentence2)
print(encoded_input)
{'input_ids': [101, 1731, 1385, 1132, 1128, 102, 146, 112, 182, 127, 1201, 1385, 102], 
'token_type_ids': [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1], 
'attention_mask': [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]}

结果可以看到,在input_ids中:

101代表[CLS]

102代表[SEP]

这说明一次传入句子对的时候,模型会自动添加一些特殊的标签,来划分两个句子。

同样的,也可以对得到的结果进行还原:

tokenizer.decode(encoded_input['input_ids'])
[CLS] How old are you [SEP] I'm 6 years old [SEP]

如果你有很多句问题,很多句回答,这时候该怎么做呢?

你可以使用接下来的做法:

batch_sentences = ["Hello I'm a single sentence",
"And another sentence",
"And the very very last one"]

batch_of_second_sentences = ["I'm a sentence that goes with the first sentence",
"And I should be encoded with the second sentence",
"And I go with the very last one"]

encoded_inputs = tokenizer(batch_sentences,batch_of_second_sentences)
print(encoded_inputs)
{'input_ids': 
[[101, 8667, 146, 112, 182, 170, 1423, 5650, 102, 146, 112, 182, 170, 5650, 1115, 2947, 1114, 1103, 1148, 5650, 102],
[101, 1262, 1330, 5650, 102, 1262, 146, 1431, 1129, 12544, 1114, 1103, 1248, 5650, 102],
[101, 1262, 1103, 1304, 1304, 1314, 1141, 102, 1262, 146, 1301, 1114, 1103, 1304, 1314, 1141, 102]], 
'token_type_ids': 
[[0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], 
[0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
 [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1]],
 'attention_mask': 
[[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], 
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], 
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]]}

 

同样的,也可以使用decode方法进行还原:

for ids in encoded_inputs['input_ids']:
    print(tokenizer.decode(ids))
[CLS] Hello I'm a single sentence [SEP] I'm a sentence that goes with the first sentence [SEP]
[CLS] And another sentence [SEP] And I should be encoded with the second sentence [SEP]
[CLS] And the very very last one [SEP] And I go with the very last one [SEP]

 

当使用padding与truncation时,你需要知道的事

首先,这里有三个参数:padding、truncation、max_length

padding控制对句子长度不够的句子进行填充的任务

True或者"longest"是指把句子填补成在整个batch中最长的句子的长度(如果只有一个句子,不需要进行padding)

'max_length'则是最大的长度

False或者"do_not_pad"则是默认值,默认不会对batch的句子进行填充

truncation则控制着对句子进行裁剪,取值为布尔类型或者字符串类型

True或者"only_first"则是可以把句子裁剪到由max_length指明的长度,如果不指明max_length,会自动把长度裁剪到模型可以接受的大小。

only_second根据max_length把句子对中的第二个句子进行裁剪

Longest_first则是把句子对中最长的句子进行裁剪到max_length大小

False或者"do_not_truncate"则不做任何裁剪

处理预先token化的输入

如果你事先对输入已经进行了处理,比如在命名实体识别NER或者POS任务中,通常会事先处理。

那么这时候你只需要指明is_split_into_words=True即可(在encode的方法)

split_sentences=["Hello","I'm","a","single","sentence"]
encoded_input = tokenizer.encode(split_sentences,is_split_into_words=True)
print(encoded_input)
[101, 8667, 146, 112, 182, 170, 1423, 5650, 102]

 

  • 22
    点赞
  • 43
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值