侧边栏壁纸
博主头像
小鱼吃猫博客博主等级

你所热爱的,便是你的生活。

  • 累计撰写 115 篇文章
  • 累计创建 47 个标签
  • 累计收到 14 条评论

目 录CONTENT

文章目录

Transformers框架之分词器(Tokenizer)学习

小鱼吃猫
2023-08-02 / 0 评论 / 2 点赞 / 215 阅读 / 5895 字

Transformers框架之分词器(Tokenizer)学习

一、基础用法

导包

from transformers import AutoTokenizer

加载Tokenizer

  • 从Huggingface官网加载
# 从HuggingFace加载Tokenizer  
tokenizer = AutoTokenizer.from_pretrained("bert-base-chinese")
  • 从本地加载
# 从本地加载tokenizer  
tokenizer = AutoTokenizer.from_pretrained("./bert_chinese_tokenizer")

使用分词器

# 分词  
sen = "小鱼吃猫博客网站"  
tokens = tokenizer.tokenize(sen)  
print(tokens)
# ['小', '鱼', '吃', '猫', '博', '客', '网', '站']

二、进阶用法

索引转换

# 将词序列转换为id序列
ids = tokenizer.convert_tokens_to_ids(tokens)
# [2207, 7824, 1391, 4344, 1300, 2145, 5381, 4991]
# 将id序列转换为token序列
tokens = tokenizer.convert_ids_to_tokens(ids)
#  ['小', '鱼', '吃', '猫', '博', '客', '网', '站']
# 将token序列转换为string
str_sen = tokenizer.convert_tokens_to_string(tokens)
# '小 鱼 吃 猫 博 客 网 站'

便捷实现方式

# 将字符串转换为id序列,又称之为编码
# add_special_tokens 代表是否添加特殊token
ids = tokenizer(sen, add_special_tokens=True)
# 将id序列转换为字符串,又称之为解码
str_sen = tokenizer.decode(ids, skip_special_tokens=False)
ids = tokenizer.encode(sen, add_special_tokens=True)
# 将id序列转换为字符串,又称之为解码
str_sen = tokenizer.decode(ids, skip_special_tokens=False)
# '小 鱼 吃 猫 博 客 网 站'

填充与截断

# 填充 至max_length,用[PAD]填充
ids = tokenizer.encode(sen, padding="max_length", max_length=15)
# [101, 2207, 7824, 1391, 4344, 1300, 2145, 5381, 4991, 102, 0, 0, 0, 0, 0]
str_sen = tokenizer.decode(ids, skip_special_tokens=False)
# '[CLS] 小 鱼 吃 猫 博 客 网 站 [SEP] [PAD] [PAD] [PAD] [PAD] [PAD]'
# 截断 超过长度直接舍弃
ids = tokenizer.encode(sen, max_length=5, truncation=True)
#  [101, 2207, 7824, 1391, 102]
# 将id序列转换为字符串
str_sen = tokenizer.decode(ids, skip_special_tokens=True)
# '小 鱼 吃'

其他输入部分

ids = tokenizer.encode(sen, padding="max_length", max_length=15)
ids
[101, 2207, 7824, 1391, 4344, 1300, 2145, 5381, 4991, 102, 0, 0, 0, 0, 0]
# 除了返回编码的id,同时也返回attention_mask, token_type_ids
attention_mask = [1 if idx != 0 else 0 for idx in ids]
token_type_ids = [0] * len(ids)
ids, attention_mask, token_type_ids
([101, 2207, 7824, 1391, 4344, 1300, 2145, 5381, 4991, 102, 0, 0, 0, 0, 0],
 [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])

快速调用方式

# plus的编码方式
inputs = tokenizer.encode_plus(sen, padding="max_length", max_length=15)
inputs
{'input_ids': [101, 2207, 7824, 1391, 4344, 1300, 2145, 5381, 4991, 102, 0, 0, 0, 0, 0], 'token_type_ids': [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, 0, 0, 0, 0, 0]}
# 直接使用tokenizer方法,获得一切
inputs = tokenizer(sen, padding="max_length", max_length=15)
inputs
{'input_ids': [101, 2207, 7824, 1391, 4344, 1300, 2145, 5381, 4991, 102, 0, 0, 0, 0, 0], 'token_type_ids': [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, 0, 0, 0, 0, 0]}

批处理

sens = ["弱小的我也有大梦想",
        "有梦想谁都了不起",
        "追逐梦想的心,比梦想本身,更可贵"]
res = tokenizer(sens)
res
{'input_ids': [[101, 2483, 2207, 4638, 2769, 738, 3300, 1920, 3457, 2682, 102], [101, 3300, 3457, 2682, 6443, 6963, 749, 679, 6629, 102], [101, 6841, 6852, 3457, 2682, 4638, 2552, 8024, 3683, 3457, 2682, 3315, 6716, 8024, 3291, 1377, 6586, 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, 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]]}

Fast / Slow Tokenizer

# 加载分词器时,如果支持Fast Tokenizer,可以传入use_fast可以大大提高速度
fast_tokenizer = AutoTokenizer.from_pretrained("./bert_chinese_tokenizer")
fast_tokenizer
slow_tokenizer = AutoTokenizer.from_pretrained("./bert_chinese_tokenizer", use_fast=False)
slow_tokenizer
inputs = fast_tokenizer(sen, return_offsets_mapping=True)
inputs
{'input_ids': [101, 2207, 7824, 1391, 4344, 1300, 2145, 5381, 4991, 102], 'token_type_ids': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 'attention_mask': [1, 1, 1, 1, 1, 1, 1, 1, 1, 1], 'offset_mapping': [(0, 0), (0, 1), (1, 2), (2, 3), (3, 4), (4, 5), (5, 6), (6, 7), (7, 8), (0, 0)]}
inputs = slow_tokenizer(sen, return_offsets_mapping=False)
inputs

特殊Tokenizer的加载

# 有些分词器有自己的代码,比如THUBaseTokenizer,需要自己加载,传入 trust_remote_code=True
tokenizer = AutoTokenizer.from_pretrained("THUDM/chatglm-6b", trust_remote_code=True)
tokenizer.decode(tokenizer.encode(sen))
2

评论区