从0开始训练自己的tokenizer

1 数据集:

   https://huggingface.co/datasets/CASIA-LM/ChineseWebText

ChineseWebText 是一个大型的中文文本数据集,通常用于训练和评估自然语言处理(NLP)模型。它包含从网络上收集的各种类型的中文文本数据,涵盖了新闻、博客、社交媒体、论坛、技术文档等多种文本来源。该数据集为训练语言模型、文本生成模型、文本分类模型等提供了丰富的语料

主要特点

  1. 多样性:

    • 数据集中的文本涵盖了广泛的主题和领域,反映了互联网上的各种语言风格和表达方式。这种多样性使得模型在训练时能够更好地学习和理解不同领域的语言使用模式。
  2. 规模大:

    • ChineseWebText 通常包含数亿个字词,文本量庞大,适合用来训练大规模语言模型。大数据量使模型能够更好地捕捉中文语言的复杂性。
  3. 真实世界的数据:

    • 数据来自于真实的网络环境,因此它能很好地代表日常使用的语言。它包含了口语化的表达、网络俚语、混合语言等,这对实际应用非常重要。
  4. 广泛应用:

    • 该数据集广泛用于训练各种中文 NLP 模型,如 BERT、GPT 等语言模型。此外,它也被用于诸如文本分类、情感分析、机器翻译等任务的预训练和微调。

使用场景

  1. 语言模型训练:

    • ChineseWebText 可以用于训练大型语言模型,这些模型随后可以用于文本生成、翻译、摘要等任务。
  2. 微调预训练模型:

    • 通过在这个数据集上微调,预训练模型可以适应中文的特定任务,如中文文本分类或问答系统。
  3. 数据增强:

    • 在数据稀缺的情况下,ChineseWebText 可以作为额外的语料资源,用于增强模型的表现。

 2 分词器:

Hugging Face Tokenizer 是 Hugging Face 生态系统中的一个关键组件,用于自然语言处理(NLP)任务中的文本预处理。Tokenizer 的主要功能是将文本转换为模型可以处理的格式,如 token IDs,以便用于各种 NLP 模型的输入。

主要功能

  1. 文本分割:

    • Tokenizer 会将文本分割为较小的单元,这些单元可以是词、子词或字符。常见的分割方法包括词级分词和基于子词的分词(如 BPE 和 WordPiece)。
  2. 文本编码:

    • 分割后的文本会被编码为 token IDs,这些 token IDs 是模型理解的数值形式。编码过程通常包括将词汇表中的词或子词映射到相应的整数。
  3. 特殊标记:

    • Hugging Face 的 Tokenizer 通常会在文本的开头和结尾添加特殊标记,如 [CLS][SEP],以帮助模型理解文本的结构。此外,还有一些用于填充(padding)的标记,用于处理不同长度的输入。
  4. 填充和截断:

    • 为了处理固定长度的输入,Tokenizer 可以自动填充(padding)较短的文本或截断(truncation)较长的文本,使其符合模型的输入要求。
  5. 批处理:

    • Tokenizer 可以高效地处理批量数据,允许对多个文本同时进行分词和编码。这样可以加快处理速度,特别是在大规模数据集上。

3 分词算法

BPE (Byte-Pair Encoding)、WordPiece 和 Unigram 是三种广泛应用于自然语言处理(NLP)中的子词级分词算法。它们的主要目的是在词汇表大小和模型处理能力之间取得平衡,尤其在处理多语言和低资源语言时表现优异。以下是对这三种分词器的详细介绍。

1. BPE (Byte-Pair Encoding)

原理:

  • BPE 是一种基于字符的分词方法,最初用于数据压缩,后来被用于 NLP 分词任务。BPE 从字符级别开始,将最常见的字符对(byte pairs)合并为新的子词,逐步构建词汇表。通过多次合并操作,最终生成一个子词表,每个子词在字典中的频率逐渐降低。

步骤:

  1. 从每个单词的字符级分割开始,初始词汇表包含所有可能的字符。
  2. 找到最频繁的字符对,将其合并为一个新的子词。
  3. 重复以上步骤,直到达到预定的词汇表大小。

优点:

  • BPE 能够处理未登录词(OOV),因为它将罕见的词分割为常见的子词。
  • 通过控制词汇表大小,BPE 在模型大小和性能之间提供了灵活的折中。

应用:

  • BPE 广泛应用于多语言模型(如 GPT-2 和 MarianMT),特别适合处理词形变化丰富的语言。

2. WordPiece

原理:

  • WordPiece 最初由 Google 为其翻译系统开发,并在 BERT 模型中得到广泛应用。与 BPE 类似,WordPiece 也从字符级别开始,逐步构建子词词汇表。但不同的是,WordPiece 在选择合并对时,不仅考虑频率,还会考虑最大化词汇表的对数似然(log-likelihood)。

步骤:

  1. 从字符级分割开始,构建初始词汇表。
  2. 在每一步合并中,选择那些能最大化语料库对数似然的子词组合。
  3. 重复此过程,直到达到预定的词汇表大小。

优点:

  • WordPiece 在构建词汇表时更加保守,能够更好地平衡词汇表大小与生成的子词长度,通常会生成比 BPE 更短的子词序列。
  • 在处理跨语言任务时,WordPiece 的子词分割往往比 BPE 更一致。

应用:

  • WordPiece 是 BERT、ALBERT、DistilBERT 等模型的默认分词器,特别适合需要大量上下文信息的任务。

3. Unigram

原理:

  • Unigram 是基于概率的子词分割模型,最早由 Google 提出,用于 T5 等生成式模型。不同于 BPE 和 WordPiece 的逐步合并策略,Unigram 直接从一个庞大的子词候选集中选择最优的子词集,以最小化整体损失。

步骤:

  1. 初始化一个大型的子词候选集合,通常包括所有可能的 n-gram。
  2. 通过统计语料库中子词序列的概率,选择能最大化文本生成概率的子词集。
  3. 重复裁剪步骤,移除那些对生成概率贡献最小的子词,直到得到最优词汇表。

优点:

  • Unigram 能够灵活地适应不同的语言和任务,生成的子词序列较为自然。
  • 它可以有效地平衡词汇表大小与模型性能,特别适合生成式任务。

应用:

  • Unigram 被用于 T5 和 SentencePiece 工具中,适合需要精细控制词汇表的任务,如翻译和摘要生成。

代码实践:使用WORDPIECE建立分词器。

from datasets import load_dataset

#数据集https://huggingface.co/datasets/CASIA-LM/ChineseWebText
#下载数据集,从本地直接载入
dataset = load_dataset('json', data_files='./ChineseWebText.json',split="train")

# print(dataset[1]["text"][0])
from tokenizers import (
    decoders,
    models,
    normalizers,
    pre_tokenizers,
    processors,
    trainers,
    Tokenizer,
)
import torch
def get_training_corpus():
    for i in range(0, len(dataset), 10):
        text_batch = dataset[i: i + 10]["text"]
        selected_elements = [text[0] for text in text_batch]  # 只取每个数组的第一个元素
        yield selected_elements

tokenizer = Tokenizer(models.WordPiece(unk_token="[UNK]"))

#数据归一处理,去多余空格,转小写
tokenizer.normalizer = normalizers.Sequence(
    [normalizers.NFD(), normalizers.Lowercase(), normalizers.StripAccents()]
)
print(tokenizer.normalizer.normalize_str("Héllò hôw are ü?"))

tokenizer.pre_tokenizer = pre_tokenizers.BertPreTokenizer()
#特殊TOKEN
special_tokens = ["[UNK]", "[PAD]", "[CLS]", "[SEP]", "[MASK]"]
trainer = trainers.WordPieceTrainer( special_tokens=special_tokens)
#训练 
tokenizer.train_from_iterator(get_training_corpus(), trainer=trainer)
#编码
encoding = tokenizer.encode("我今天吃饭了!")
print(encoding.tokens)#输出 :['我', '##今天', '##吃', '##饭', '##了', '!']


#添加额外信息
tokenizer.post_processor = processors.TemplateProcessing(
    single=f"[CLS]:0 $A:0 [SEP]:0",
    pair=f"[CLS]:0 $A:0 [SEP]:0 $B:1 [SEP]:1",
    special_tokens=[("[CLS]", cls_token_id), ("[SEP]", sep_token_id)],
)
encoding = tokenizer.encode("我今天吃饭了!","你想干什么")
print(encoding.tokens)#输出 :['[CLS]', '我', '##今天', '##吃', '##饭', '##了', '!', '[SEP]', '你', '##想', '##干', '##什么', '[SEP]']
#encoding属性包括Encoding(num_tokens=13, attributes=[ids, type_ids, tokens, offsets, attention_mask, special_tokens_mask, overflowing])

#保存分词器
tokenizer.save("token.json")

 

  • 16
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值