HuggingFace Tokenizers

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

未经允许不得转载:一亩三分地 » HuggingFace Tokenizers