HuggingFace Tokenizers 是一个高效的文本分词库,用于将自然语言文本分割成单个的标记(tokens),以便用于自然语言处理任务中,如文本分类、命名实体识别、机器翻译等。它支持多种语言,并提供了多种分词器的实现,包括 BPE、WordPiece 和 Unigram。
pip install tokenizers
1. 准备训练集
import pandas as pd
import pickle
import jieba
import logging
jieba.setLogLevel(logging.CRITICAL)
def demo():
data = pd.read_csv('weibo_senti_100k/weibo_senti_100k.csv')
# 去除异常值
data = data.dropna()
# 文本进行分词
corpus = [' '.join(jieba.lcut(review)) for review in data['review'].to_numpy().tolist()]
print(corpus[0])
# 存储语料
pickle.dump(corpus, open('weibo_senti_100k/corpus.pkl', 'wb'))
if __name__ == '__main__':
demo()
更博 了 , 爆照 了 , 帅 的 呀 , 就是 越来越 爱 你 ! 生快 傻 缺 [ 爱 你 ] [ 爱 你 ] [ 爱 你 ]
2. 训练分词器
import pickle
from tokenizers import pre_tokenizers
from tokenizers import normalizers
from tokenizers import processors
from tokenizers import Tokenizer, models
from tokenizers import trainers
def train():
# 初始化分词器,并设置方法为 BPE
tokenizer = Tokenizer(model=models.BPE(unk_token='[UNK]'))
# 在词表中添加特殊的标记
special_tokens = ['[CLS]', '[SEP]', '[UNK]', '[PAD]']
tokenizer.add_special_tokens(special_tokens)
# 1. 对文本进行标准化,例如将文本转换为小写(Lowercase)、统一字符编码(NFC)等
tokenizer.normalizer = normalizers.Sequence([normalizers.Lowercase(), normalizers.NFC()])
# 2. 将文本分割成初步的单元(如单词、字符等),为后续的分词操作提供基础。
tokenizer.pre_tokenizer = pre_tokenizers.WhitespaceSplit()
# 3. 在分词完成后,对分词结果进行进一步处理,例如添加特殊标记(如 [CLS] 和 [SEP])以适配模型的输入格式。
tokenizer.post_processor = processors.TemplateProcessing(
single="[CLS] $A [SEP]",
special_tokens=[
('[CLS]', tokenizer.token_to_id('[CLS]')),
('[SEP]', tokenizer.token_to_id('[SEP]'))
]
)
# 初始化训练器,设置词汇表大小、特殊令牌和最小频率
# continuing_subword_prefix: 子词表示前缀,例如:问答使用两个子词表示:['问', '###答']
# min_frequency: 只有出现频率至少为 min_frequency 的字符对才会被合并
trainer = trainers.BpeTrainer(vocab_size=20000,
min_frequency=0,
continuing_subword_prefix='###',
show_progress=False)
# 从文本数据迭代训练分词器
corpus = pickle.load(open('weibo_senti_100k/corpus.pkl', 'rb'))
tokenizer.train_from_iterator(corpus, trainer)
print('词典大小:', tokenizer.get_vocab_size())
# 保存训练好的分词器
# 1. tokenizer 保存
tokenizer.save('tokenizer.json')
# 2. transfomers 保存
from transformers import PreTrainedTokenizerFast
tokenizer = PreTrainedTokenizerFast(tokenizer_object=tokenizer)
tokenizer.save_pretrained('tokenizer')
if __name__ == '__main__':
train()
3. 使用分词器
import jieba
import logging
jieba.setLogLevel(logging.CRITICAL)
import pickle
from tokenizers import Tokenizer
# 1. encode
def demo01():
# 1. 加载分词器
tokenizer = Tokenizer.from_file('tokenizer.json')
content = '某 问答 社区 上 收到 一 大学生 Edward Meng 发给 我 的 私信。'
encode_content = tokenizer.encode(content, add_special_tokens=True)
print(encode_content.tokens)
print(encode_content.ids)
print(encode_content.word_ids)
# 3. 输出解码
decode_content = tokenizer.decode(encode_content.ids, skip_special_tokens=False)
print(decode_content)
# 2. encode_batch
def demo02():
tokenizer = Tokenizer.from_file('tokenizer.json')
# 启动 PAD 对齐
tokenizer.enable_padding(direction='right', pad_token='[PAD]', pad_id=tokenizer.token_to_id('[PAD]'))
contents = ['我 是 中国人', '我 爱 我 的 国家']
# 批量编码
encode_contents = tokenizer.encode_batch(contents, is_pretokenized=False)
for content in encode_contents:
print(content)
print(content.tokens)
print(content.ids)
# 注意力掩码
print(content.attention_mask)
print(content.special_tokens_mask)
print('-' * 30)
if __name__ == '__main__':
demo01()
print('*' * 30)
demo02()
['[CLS]', '某', '问答', '社区', '上', '收到', '一', '大学生', 'ed', 'ward', 'meng', '发给', '我', '的', '私信', '。', '[SEP]'] [0, 2510, 17166, 9468, 319, 6309, 313, 12022, 7889, 16561, 11938, 10628, 2011, 3488, 6461, 168, 1] [None, 0, 1, 2, 3, 4, 5, 6, 7, 7, 8, 9, 10, 11, 12, 12, None] ! 某 问答 社区 上 收到 一 大学生 ed ward meng 发给 我 的 私信 。 " ****************************** Encoding(num_tokens=7, attributes=[ids, type_ids, tokens, offsets, attention_mask, special_tokens_mask, overflowing]) ['[CLS]', '我', '是', '中国', '人', '[SEP]', '[PAD]'] [0, 2011, 2376, 5921, 414, 1, 20003] [1, 1, 1, 1, 1, 1, 0] [1, 0, 0, 0, 0, 1, 1] ------------------------------ Encoding(num_tokens=7, attributes=[ids, type_ids, tokens, offsets, attention_mask, special_tokens_mask, overflowing]) ['[CLS]', '我', '爱', '我', '的', '国家', '[SEP]'] [0, 2011, 3188, 2011, 3488, 6231, 1] [1, 1, 1, 1, 1, 1, 1] [1, 0, 0, 0, 0, 0, 1] ------------------------------

冀公网安备13050302001966号