HuggingFace学习笔记--Tokenizer的使用

1--AutoTokenizer的使用

官方文档

AutoTokenizer() 常用于分词,其可调用现成的模型来对输入句子进行分词。

1-1--简单Demo

测试代码:

python 复制代码
# 分词器测试Demo
from transformers import AutoTokenizer

if __name__ == "__main__":
    checkpoint = "distilbert-base-uncased-finetuned-sst-2-english" # 使用该模型
    tokenlizer = AutoTokenizer.from_pretrained(checkpoint) # 加载该模型对应的分词器
    
    raw_input = [
        "I love kobe bryant.",
        "Me too."
    ]
    
    inputs = tokenlizer(raw_input, padding = True, return_tensors = "pt") # padding并返回pytorch版本的tensor
    print("After tokenlizer: \n", inputs) # 打印分词后的结果
    
    str1 = tokenlizer.decode(inputs['input_ids'][0]) # 将词ID恢复
    print("str1: \n", str1)
    
    print("All done!")

输出结果:

bash 复制代码
After tokenlizer: 
{
'input_ids': tensor([[101,  1045,  2293, 24113, 12471,  1012,   102],
                        [101,  2033,  2205,  1012,   102,     0,     0]]),          
'attention_mask': tensor([[1, 1, 1, 1, 1, 1, 1],
                    [1, 1, 1, 1, 1, 0, 0]])
}
str1: 
 [CLS] i love kobe bryant. [SEP]

分析:

上述代码将输入的句子进行分词,并将每一个词利用一个 ID 进行映射;例如上述代码中,101 对应 [CLS],1045 对应 I,2293 对应 love,24113 对应 kobe,12471 对应 bryant,1012 对应 . 符号,102 对应 [SEP];

input_ids 存储了每一个句子分词后对应的 ID,0 表示 padding 的词;由于上面测试代码设置了padding,因此会将每一个句子自动padding为最长句子的长度,padding的词用 0 来表示。

attention_mask 标记了哪些词是真正有意义的,只有为 1 的词才会参与后续的 attention 等计算。

利用 decode 可以将词 ID 重新解码为句子。

1-2--常用参数

1-2-1--padding

设置 padding 时,可以指定具体的 padding 长度;

python 复制代码
from transformers import AutoTokenizer

if __name__ == "__main__":
    checkpoint = "distilbert-base-uncased-finetuned-sst-2-english"
    tokenlizer = AutoTokenizer.from_pretrained(checkpoint) 
    
    raw_input = [
        "I love kobe bryant.",
        "Me too."
    ]
    
    input1 = tokenlizer(raw_input, padding = "longest", return_tensors = "pt") # padding长度与输入中的最长句子相同
    input2 = tokenlizer(raw_input, padding = "max_length", return_tensors = "pt") # padding到最大句子长度,默认是512
    input3 = tokenlizer(raw_input, padding = "max_length", max_length = 10, return_tensors = "pt") # 指定最大长度是10
    print("After tokenlizer: \n", input1['input_ids'].shape)
    print("After tokenlizer: \n", input2['input_ids'].shape)
    print("After tokenlizer: \n", input3['input_ids'].shape)

输出结果:

python 复制代码
After tokenlizer: 
 torch.Size([2, 7])
After tokenlizer: 
 torch.Size([2, 512])
After tokenlizer: 
 torch.Size([2, 10])

1-2-2--truncation

设置 truncation 时,用于截断,可以指定截断的长度。

python 复制代码
from transformers import AutoTokenizer

if __name__ == "__main__":
    checkpoint = "distilbert-base-uncased-finetuned-sst-2-english"
    tokenlizer = AutoTokenizer.from_pretrained(checkpoint) 
    
    raw_input = [
        "I love kobe bryant.",
        "Me too."
    ]
    
    # 长度超过5的部分会被截断
    input1 = tokenlizer(raw_input, padding = "longest", truncation = True, max_length=5, return_tensors = "pt")
    print("After tokenlizer: \n", input1)
    
    str1 = tokenlizer.decode(input1['input_ids'][0]) # 将词ID恢复
    print("str1: \n", str1)

输出结果:

python 复制代码
After tokenlizer: 
{
'input_ids': tensor([[  101,  1045,  2293, 24113,   102],
        [  101,  2033,  2205,  1012,   102]]), 
'attention_mask': tensor([[1, 1, 1, 1, 1],
        [1, 1, 1, 1, 1]])
}
str1: 
 [CLS] i love kobe [SEP]

2--BertTokenizer的使用

2-1--简单Demo

① 编码两个句子:

python 复制代码
from transformers import BertTokenizer

if __name__ == "__main__":
    tokenizer = BertTokenizer.from_pretrained(pretrained_model_name_or_path = 'bert-base-chinese')
    sents = ['我喜欢科比布莱恩特.', '我也是.', '我喜欢他的后仰跳投', '我喜欢他的曼巴精神']
    
    # 编码两个句子    
    inputs = tokenizer.encode(
        text = sents[0],
        text_pair = sents[1],
        truncation = True, # 截断
        padding = 'max_length', # padding到最大长度
        add_special_tokens = True,
        max_length = 20, # 设置最大长度
        return_tensors = None # None默认返回list,可取值tf,pt,np
    )

    print(inputs)
    print(tokenizer.decode(inputs))

输出结果:

python 复制代码
inputs: 
 [101, 2769, 1599, 3614, 4906, 3683, 2357, 5812, 2617, 4294, 119, 102, 2769, 738, 3221, 119, 102, 0, 0, 0]
decode: 
 [CLS] 我 喜 欢 科 比 布 莱 恩 特. [SEP] 我 也 是. [SEP] [PAD] [PAD] [PAD]

② 增强编码

python 复制代码
from transformers import BertTokenizer

if __name__ == "__main__":
    tokenizer = BertTokenizer.from_pretrained(pretrained_model_name_or_path = 'bert-base-chinese')
    sents = ['我喜欢科比布莱恩特.', '我也是.', '我喜欢他的后仰跳投', '我喜欢他的曼巴精神']
    
    # 增强编码两个句子
    inputs = tokenizer.encode_plus(
        text = sents[0],
        text_pair = sents[1],
        truncation = True, # 截断
        padding = 'max_length', # padding到最大长度
        add_special_tokens = True,
        max_length = 30, # 设置最大长度
        return_tensors = None, # None默认返回list,可取值tf,pt,np,
        return_token_type_ids = True,
        return_attention_mask = True,
        return_special_tokens_mask = True,
        return_length = True
    )
        
    for k, v in inputs.items():
        print(k, ':', v)
        
    print(tokenizer.decode(inputs['input_ids']))

输出结果:

python 复制代码
input_ids : [101, 2769, 1599, 3614, 4906, 3683, 2357, 5812, 2617, 4294, 119, 102, 2769, 738, 3221, 119, 102, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

token_type_ids : [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

special_tokens_mask : [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

length : 30

decode: 
 [CLS] 我 喜 欢 科 比 布 莱 恩 特. [SEP] 我 也 是. [SEP] [PAD] [PAD] [PAD] [PAD] [PAD] [PAD] [PAD] [PAD] [PAD] [PAD] [PAD] [PAD] [PAD]

③ 批量编码:

python 复制代码
from transformers import BertTokenizer

if __name__ == "__main__":
    tokenizer = BertTokenizer.from_pretrained(pretrained_model_name_or_path = 'bert-base-chinese')
    sents = ['我喜欢科比布莱恩特.', '我也是.', '我喜欢他的后仰跳投', '我喜欢他的曼巴精神']
    
    # 批量编码句子
    inputs = tokenizer.batch_encode_plus(
        batch_text_or_text_pairs = [sents[0], sents[1]],
        truncation = True, # 截断
        padding = 'max_length', # padding到最大长度
        add_special_tokens = True,
        max_length = 20, # 设置最大长度
        return_tensors = None, # None默认返回list,可取值tf,pt,np,
        return_token_type_ids = True,
        return_attention_mask = True,
        return_special_tokens_mask = True,
        return_length = True
    )
        
    for k, v in inputs.items():
        print(k, ':', v)
        
    print("decode: \n", tokenizer.decode(inputs['input_ids'][0]))
    print("decode: \n", tokenizer.decode(inputs['input_ids'][1]))

输出结果:

python 复制代码
input_ids : [[101, 2769, 1599, 3614, 4906, 3683, 2357, 5812, 2617, 4294, 119, 102, 0, 0, 0, 0, 0, 0, 0, 0], [101, 2769, 738, 3221, 119, 102, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]

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]]

special_tokens_mask : [[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1], [1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]]

length : [12, 6]

attention_mask : [[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0], [1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]

decode: 
 [CLS] 我 喜 欢 科 比 布 莱 恩 特. [SEP] [PAD] [PAD] [PAD] [PAD] [PAD] [PAD] [PAD] [PAD]

decode: 
 [CLS] 我 也 是. [SEP] [PAD] [PAD] [PAD] [PAD] [PAD] [PAD] [PAD] [PAD] [PAD] [PAD] [PAD] [PAD] [PAD] [PAD]

④ 批量编码成对的句子:

python 复制代码
from transformers import BertTokenizer

if __name__ == "__main__":
    tokenizer = BertTokenizer.from_pretrained(pretrained_model_name_or_path = 'bert-base-chinese')
    sents = ['我喜欢科比布莱恩特.', '我也是.', '我喜欢他的后仰跳投', '我喜欢他的曼巴精神']
    
    # 批量编码成对的句子
    inputs = tokenizer.batch_encode_plus(
        batch_text_or_text_pairs=[(sents[0], sents[1]), (sents[2], sents[3])],
        truncation = True, # 截断
        padding = 'max_length', # padding到最大长度
        add_special_tokens = True,
        max_length = 20, # 设置最大长度
        return_tensors = None, # None默认返回list,可取值tf,pt,np,
        return_token_type_ids = True,
        return_attention_mask = True,
        return_special_tokens_mask = True,
        return_length = True
    )
        
    for k, v in inputs.items():
        print(k, ':', v)
        
    print("decode: \n", tokenizer.decode(inputs['input_ids'][0]))
    print("decode: \n", tokenizer.decode(inputs['input_ids'][1]))

输出结果:

python 复制代码
input_ids : [[101, 2769, 1599, 3614, 4906, 3683, 2357, 5812, 2617, 4294, 119, 102, 2769, 738, 3221, 119, 102, 0, 0, 0], [101, 2769, 1599, 3614, 800, 4638, 1400, 814, 6663, 2832, 102, 2769, 1599, 3614, 800, 4638, 3294, 2349, 5125, 102]]

token_type_ids : [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1]]

special_tokens_mask : [[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1]]

length : [17, 20]

attention_mask : [[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]]

decode: 
 [CLS] 我 喜 欢 科 比 布 莱 恩 特. [SEP] 我 也 是. [SEP] [PAD] [PAD] [PAD]

decode: 
 [CLS] 我 喜 欢 他 的 后 仰 跳 投 [SEP] 我 喜 欢 他 的 曼 巴 精 [SEP]

⑤ 获取字典:

python 复制代码
from transformers import BertTokenizer

if __name__ == "__main__":
    tokenizer = BertTokenizer.from_pretrained(pretrained_model_name_or_path = 'bert-base-chinese')
    sents = ['我喜欢科比布莱恩特.', '我也是.', '我喜欢他的后仰跳投', '我喜欢他的曼巴精神']
    
    # 批量编码成对的句子
    inputs = tokenizer.batch_encode_plus(
        batch_text_or_text_pairs=[(sents[0], sents[1]), (sents[2], sents[3])],
        truncation = True, # 截断
        padding = 'max_length', # padding到最大长度
        add_special_tokens = True,
        max_length = 20, # 设置最大长度
        return_tensors = None, # None默认返回list,可取值tf,pt,np,
        return_token_type_ids = True,
        return_attention_mask = True,
        return_special_tokens_mask = True,
        return_length = True
    )
        
    # 获取字典
    token_dict = tokenizer.get_vocab()

    print(type(token_dict))
    print(len(token_dict))
    print('喜' in token_dict) # 中文是按字来编码的,因此喜在字典里
    print('喜欢' in token_dict) # 同理,喜欢不在字典里

输出结果:

python 复制代码
<class 'dict'>
21128
True
False

⑥ 添加新字典:

python 复制代码
from transformers import BertTokenizer

if __name__ == "__main__":
    tokenizer = BertTokenizer.from_pretrained(pretrained_model_name_or_path = 'bert-base-chinese')
    sents = ['我喜欢科比布莱恩特.', '我也是.', '我喜欢他的后仰跳投', '我喜欢他的曼巴精神']
    
    # 批量编码成对的句子
    inputs = tokenizer.batch_encode_plus(
        batch_text_or_text_pairs=[(sents[0], sents[1]), (sents[2], sents[3])],
        truncation = True, # 截断
        padding = 'max_length', # padding到最大长度
        add_special_tokens = True,
        max_length = 20, # 设置最大长度
        return_tensors = None, # None默认返回list,可取值tf,pt,np,
        return_token_type_ids = True,
        return_attention_mask = True,
        return_special_tokens_mask = True,
        return_length = True
    )
        
    # 添加新词
    tokenizer.add_tokens(new_tokens=['喜欢', '跳投'])
    # 添加新符号
    tokenizer.add_special_tokens({'eos_token': '[EOS]'})
    # 获取字典
    token_dict = tokenizer.get_vocab()
    print('喜欢' in token_dict) # 添加新词后,喜欢在字典里
    print('喜欢: ', token_dict['喜欢'])
    print('跳投: ', token_dict['跳投'])
    print('[EOS]: ', token_dict['[EOS]'])
    
    # 编码新句子,测试新词的编码
    test = tokenizer.encode(
        text = '我喜欢科比的后仰跳投[EOS]',
        text_pair = None,
        truncation = True,
        padding = 'max_length',
        add_special_tokens = True,
        max_length = 15,
        return_tensors = None
    )
    print(test)

输出结果:

python 复制代码
True
喜欢:  21128
跳投:  21129
[EOS]:  21130
[101, 2769, 21128, 4906, 3683, 4638, 1400, 814, 21129, 21130, 102, 0, 0, 0, 0]

# 将喜欢、跳投和[EOS]直接编码,并没有拆开按字来编码
相关推荐
聆风吟º11 小时前
CANN runtime 全链路拆解:AI 异构计算运行时的任务管理与功能适配技术路径
人工智能·深度学习·神经网络·cann
User_芊芊君子11 小时前
CANN大模型推理加速引擎ascend-transformer-boost深度解析:毫秒级响应的Transformer优化方案
人工智能·深度学习·transformer
智驱力人工智能12 小时前
小区高空抛物AI实时预警方案 筑牢社区头顶安全的实践 高空抛物检测 高空抛物监控安装教程 高空抛物误报率优化方案 高空抛物监控案例分享
人工智能·深度学习·opencv·算法·安全·yolo·边缘计算
人工不智能57712 小时前
拆解 BERT:Output 中的 Hidden States 到底藏了什么秘密?
人工智能·深度学习·bert
h64648564h12 小时前
CANN 性能剖析与调优全指南:从 Profiling 到 Kernel 级优化
人工智能·深度学习
心疼你的一切12 小时前
解密CANN仓库:AIGC的算力底座、关键应用与API实战解析
数据仓库·深度学习·aigc·cann
学电子她就能回来吗14 小时前
深度学习速成:损失函数与反向传播
人工智能·深度学习·学习·计算机视觉·github
Coder_Boy_15 小时前
TensorFlow小白科普
人工智能·深度学习·tensorflow·neo4j
大模型玩家七七15 小时前
梯度累积真的省显存吗?它换走的是什么成本
java·javascript·数据库·人工智能·深度学习
kkzhang15 小时前
Concept Bottleneck Models-概念瓶颈模型用于可解释决策:进展、分类体系 与未来方向综述
深度学习