导入
from transformers import BertTokenizer
from pytorch_pretrained import BertTokenizer
以上两行代码都可以导入BerBertTokenizer,transformers是当下比较成熟的库,pytorch_pretrained是google提供的源码(功能不如transformers全面)
加载
tokenizer = BertTokenizer.from_pretrained('bert_pretrain')
数据
首先定义一些数据:
sents = [
'人工智能是计算机科学的一个分支。',
'它企图了解智能的实质。',
'人工智能是一门极富挑战性的科学。',
]
tokenize
将句子拆分为token,并不映射为对应的id
token = tokenizer.tokenize(sents[0])
print(token)
# 输出:['人', '工', '智', '能', '是', '计', '算', '机', '科', '学', '的', '一', '个', '分', '支', '。']
convert_tokens_to_ids
将token映射为其对应的id(ids是我们训练中真正会用到的数据)
ids = tokenizer.convert_tokens_to_ids(token)
print(ids)
#输出:[8, 35, 826, 52, 10, 159, 559, 98, 147, 18, 5, 7, 27, 59, 414, 12043]
同理convert_ids_to_tokens,就是上述方法的逆过程
encode(从此方法开始,只有transformers可以实现)
convert_tokens_to_ids是将分词后的token转化为id序列,而encode包含了分词和token转id过程,即encode是一个更全的过程,另外,encode默认使用basic的分词工具,以及会在句子前和尾部添加特殊字符[CLS]和[SEP],无需自己添加。从下可以看到,虽然encode直接使用tokenizer.tokenize()进行词拆分,会保留头尾特殊字符的完整性,但是自己也会额外添加特殊字符。
token = tokenizer.tokenize(sents[0])
print(token)
ids = tokenizer.convert_tokens_to_ids(token)
print(ids)
ids_encode = tokenizer.encode(sents[0])
print(ids_encode)
token_encode = tokenizer.convert_ids_to_tokens(ids_encode)
print(token_encode)
# 输出结果:
#['人', '工', '智', '能', '是', '计', '算', '机', '科', '学', '的', '一', '个', '分', '支', '。']
#[8, 35, 826, 52, 10, 159, 559, 98, 147, 18, 5, 7, 27, 59, 414, 12043]
#[1, 8, 35, 826, 52, 10, 159, 559, 98, 147, 18, 5, 7, 27, 59, 414, 12043, 2]
#['[CLS]', '人', '工', '智', '能', '是', '计', '算', '机', '科', '学', '的', '一', '个', '分', '支', '。', '[SEP]']
从运行结果可以看到encode确实在首尾增加了特殊词元[cls]和[sep]也就是1和2
encode_plus
返回更多相关信息:
ids = tokenizer.encode_plus(sents[0])
print(ids)
# {'input_ids': [1, 8, 35, 826, 52, 10, 159, 559, 98, 147, 18, 5, 7, 27, 59, 414, 12043, 2],
#'token_type_ids': [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]}
相关参数介绍:
out = tokenizer.encode_plus(
text=sents[0],
text_pair=sents[1],
#当句子长度大于max_length时,截断
truncation=True,
#一律补零到max_length长度
padding='max_length',
max_length=30,
add_special_tokens=True,
#可取值tf,pt,np,默认为返回list
return_tensors=None,
#返回token_type_ids
return_token_type_ids=True,
#返回attention_mask
return_attention_mask=True,
#返回special_tokens_mask 特殊符号标识
return_special_tokens_mask=True,
#返回offset_mapping 标识每个词的起止位置,这个参数只能BertTokenizerFast使用
#return_offsets_mapping=True,
#返回length 标识长度
return_length=True,
)
for k, v in out.items():
print(k, ':', v)
#input_ids : [1, 8, 35, 826, 52, 10, 159, 559, 98, 147, 18, 5, 7, 27, 59, 414, 12043, 2, 380, 258, 429, 15, 273, 826, 52, 5, 79, 207, 12043, 2]
#token_type_ids : [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
#special_tokens_mask : [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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]
#length : 30
batch_encode_plus
以 batch 的形式去编码句子
ids = tokenizer.batch_encode_plus([x for x in sents])
print(ids)
# {
#'input_ids': [[1, 8, 35, 826, 52, 10, 159, 559, 98, 147, 18, 5, 7, 27, 59, 414, 12043, 2], [1, 380, 258, 429, 15, 273, 826, 52, 5, 79, 207, 12043, 2], [1, 8, 35, 826, 52, 10, 7, 232, 456, 595, 1373, 267, 92, 5, 147, 18, 12043, 2]],
#'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, 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': [[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]]}