如何使用Hugging Face从零开始训练BPE、WordPiece和Unigram Tokenizers

How to Train BPE, WordPiece, and Unigram Tokenizers from Scratch using Hugging Face

如果你有一些NLP的经验,你可能知道标记化是任何NLP管道的舵手。

标记化通常被认为是NLP的一个子领域,但它有自己的演变故事。现在,它支撑着许多最先进的NLP模型。

这篇文章是关于通过利用Hugging Face的标记化包从头开始训练标记化**。**

在我们进入训练和比较不同标记器的有趣部分之前,我想给你一个关于算法之间关键差异的简要总结。

主要区别在于选择要合并的字符对,以及每个算法用来生成最终标记集的合并策略

BPE算法–基于频率的模型

字节对编码使用子字模式的频率来筛选它们进行合并。

使用频率作为驱动因素的缺点是,你最终可能会有模糊的最终编码,可能对新的输入文本没有用处。

但它在生成无歧义的标记方面仍有改进的余地。

Unigram算法–一个基于概率的模型

接下来我们有一个Unigram模型,它通过计算每个子词组合的可能性来解决合并问题,而不是挑选最频繁的模式。

它计算每个子词标记的概率,然后根据本研究论文中解释的损失函数将其删除

基于损失值的某个阈值,你就可以触发该模型来丢弃底部20-30%的子词标记。

Unigram是一种完全的概率算法,它在每次迭代中都会根据概率选择字符对和最终决定合并(或不合并)。

WordPiece算法

随着2018年BERT的发布,出现了一种新的子词标记化算法,称为WordPiece,可以认为是BPE和Unigram算法的中介。

WordPiece也是一种贪婪的算法,它利用可能性而不是计数频率来合并每个迭代中的最佳配对,但选择配对的字符是基于计数频率的。

因此,在选择字符配对方面,它与BPE相似,在选择最佳配对合并方面,与Unigram相似。

在涵盖了算法差异的情况下,我试图实现这些算法中的每一种(不是从头开始),以比较它们各自产生的输出。

如何训练BPE、Unigram和WordPiece算法

现在,为了对输出进行无偏见的比较,我不想使用预先训练好的算法,因为这将把数据集的大小、质量和内容带入画面。

一种方法可以是使用研究论文从头开始编码这些算法,然后对其进行测试。这是一个很好的方法,以便真正理解每个算法的工作原理,但你可能最终会花几周时间来做这件事。

相反,我使用了Hugging Face的标记器包,它提供了当今所有最常用的标记器的实现。它还允许我在我选择的数据集上从头开始训练这些模型,然后将我自己选择的输入字符串标记化。

如何训练数据集

我选择了两个不同的数据集来训练这些模型。一个是来自古腾堡的免费书籍,作为一个小型数据集,另一个是wikitext-103,这是一个516M的文本。

在Colab中,你可以先下载数据集并解压(如果需要)。

!wget http://www.gutenberg.org/cache/epub/16457/pg16457.txt

!wget https://s3.amazonaws.com/research.metamind.io/wikitext/wikitext-103-raw-v1.zip

!unzip wikitext-103-raw-v1.zip

导入所需的模型和培训师

翻阅文档,你会发现该包的主要API是类Tokenizer.

然后你可以用你选择的模型(BPE/ Unigram/ WordPiece)来实例化任何标记器。

在这里,我导入了主类,所有我想测试的模型,以及它们的训练器,因为我想从头开始训练这些模型。

## importing the tokenizer and subword BPE trainer
from tokenizers import Tokenizer
from tokenizers.models import BPE, Unigram, WordLevel, WordPiece
from tokenizers.trainers import BpeTrainer, WordLevelTrainer, \
                                WordPieceTrainer, UnigramTrainer

## a pretokenizer to segment the text into words
from tokenizers.pre_tokenizers import Whitespace

如何实现训练和标记化的自动化

由于我需要对三个不同的模型执行有点类似的过程,我把这些过程分成3个函数。我只需要为每个模型调用这些函数,我在这里的工作就完成了。

那么,这些函数是什么呢?

第1步 - 准备标记器

准备标记器需要我们用一个我们选择的模型来实例化标记器类。但是,由于我们有四个模型(我也添加了一个简单的词级算法)要测试,我们将写if/else案例来用正确的模型实例化标记器。

为了在小数据集和大数据集上训练实例化的标记器,我们还需要实例化一个训练器,在我们的例子中,这些将是 BpeTrainer, WordLevelTrainer, WordPieceTrainer, and UnigramTrainer.

实例化和训练将需要我们指定一些特殊的标记。这些是未知词的标记和其他特殊的标记,我们以后需要使用这些标记来增加我们的词汇量。

你也可以在这里指定其他训练参数的词汇量大小或最小频率。

unk_token = "<UNK>"  # token for unknown words
spl_tokens = ["<UNK>", "<SEP>", "<MASK>", "<CLS>"]  # special tokens

def prepare_tokenizer_trainer(alg):
    """
    Prepares the tokenizer and trainer with unknown & special tokens.
    """
    if alg == 'BPE':
        tokenizer = Tokenizer(BPE(unk_token = unk_token))
        trainer = BpeTrainer(special_tokens = spl_tokens)
    elif alg == 'UNI':
        tokenizer = Tokenizer(Unigram())
        trainer = UnigramTrainer(unk_token= unk_token, special_tokens = spl_tokens)
    elif alg == 'WPC':
        tokenizer = Tokenizer(WordPiece(unk_token = unk_token))
        trainer = WordPieceTrainer(special_tokens = spl_tokens)
    else:
        tokenizer = Tokenizer(WordLevel(unk_token = unk_token))
        trainer = WordLevelTrainer(special_tokens = spl_tokens)
    
    tokenizer.pre_tokenizer = Whitespace()
    return tokenizer, trainer

我们还需要添加一个预标记器,将我们的输入分成单词,因为如果没有预标记器,我们可能会得到与几个单词重叠的标记:例如,我们可能得到一个 **"there is"**令牌,因为这两个词经常挨着出现。

使用预标记器将确保没有标记比预标记器返回的单词大。

这个函数将返回标记器及其训练器对象,我们可以用它来在数据集上训练模型。

在这里,我们对所有的模型都使用相同的预标记器(Whitespace)。你可以选择用其他人来测试它。

第2步 - 训练标记器

在准备好标记化器和训练器之后,我们可以开始训练过程。

这里有一个函数,它将接收我们打算训练标记器的文件以及算法标识符。

  • ‘WLV’ - 字级算法
  • ‘WPC’ - 字片算法
  • ‘BPE’ - 字节对编码
  • ‘UNI’ - 单词组
def train_tokenizer(files, alg='WLV'):
    """
    Takes the files and trains the tokenizer.
    """
    tokenizer, trainer = prepare_tokenizer_trainer(alg)
    tokenizer.train(files, trainer) # training the tokenzier
    tokenizer.save("./tokenizer-trained.json")
    tokenizer = Tokenizer.from_file("./tokenizer-trained.json")
    return tokenizer

这是我们在训练标记器时需要调用的主要函数。它将首先准备标记器和训练器,然后开始用提供的文件训练标记器。

训练结束后,它将模型保存在一个JSON文件中,从文件中加载,并返回训练好的标记器,开始对新输入进行编码。

第3步 - 对输入字符串进行标记

最后一步是开始对新的输入字符串进行编码,并比较每种算法所产生的标记。

在这里,我们将写一个嵌套的for循环,首先在较小的数据集上训练每个模型,然后在较大的数据集上训练,并将输入字符串标记化。

输入字符串 - “这是一个深度学习标记化的教程。标记化是深度学习NLP管道的第一步。我们将比较每个标记化模型所产生的标记。很兴奋吧!😍”

small_file = ['pg16457.txt']
large_files = [f"./wikitext-103-raw/wiki.{split}.raw" for split in ["test", "train", "valid"]]

for files in [small_file, large_files]:
    print(f"========Using vocabulary from {files}=======")
    for alg in ['WLV', 'BPE', 'UNI', 'WPC']:
        trained_tokenizer = train_tokenizer(files, alg)
        input_string = "This is a deep learning tokenization tutorial. Tokenization is the first step in a deep learning NLP pipeline. We will be comparing the tokens generated by each tokenization model. Excited much?!😍"
        output = tokenize(input_string, trained_tokenizer)
        tokens_dict[alg] = output.tokens
        print("----", alg, "----")
        print(output.tokens, "->", len(output.tokens))

下面是输出结果。

对输出的分析。

看一下输出,你会发现标记生成方式的不同,这反过来又导致了标记生成数量的不同。

  • 一个简单的词级算法无论在哪个数据集上训练都会产生35个标记。
  • BPE算法在较小的数据集上训练时创造了55个标记,在较大的数据集上训练时创造了47个标记。这表明,在较大的数据集上训练时,它能够合并更多的字符对。
  • Unigram模型在两个数据集上创造了类似的(68和67)个标记。但你可以看到生成的标记的差异。

有了更大的数据集,合并更接近于生成更适合于编码我们经常使用的真实世界的英语语言单词的标记。

WordPiece在较小的数据集上训练时创造了52个标记,在较大的数据集上训练时创造了48个标记。生成的代币有双#,表示代币作为前缀/后缀的使用。

当在较大的数据集上训练时,这三种算法都产生了较差和较好的子词令牌。

如何比较令牌

为了比较标记,我把每个算法的输出存储在一个字典中,我将把它变成一个数据框架,以便更好地查看标记的差异。

由于每个模型产生的标记数量不同,我添加了一个标记,以使数据成为矩形并适合数据框架。

在数据框架中基本上是nan。

import pandas as pd

max_len = max(len(tokens_dict['UNI']), len(tokens_dict['WPC']), len(tokens_dict['BPE']))
diff_bpe = max_len - len(tokens_dict['BPE'])
diff_wpc = max_len - len(tokens_dict['WPC'])

tokens_dict['BPE'] = tokens_dict['BPE'] + ['<PAD>']*diff_bpe
tokens_dict['WPC'] = tokens_dict['WPC'] + ['<PAD>']*diff_wpc

del tokens_dict['WLV']

df = pd.DataFrame(tokens_dict)
df.head(10)

这里是输出结果。

你也可以用集合来查看标记的差异。

要查看代码,请到这个Colab笔记本。

结束语和后续步骤

根据生成的标记的种类,WPC似乎确实生成了在英语中更常见的子词标记–但不要让我相信这一观察。

这些算法彼此之间略有不同,在开发一个像样的NLP模型方面做得有些类似。但大部分性能取决于你的语言模型的使用情况、词汇量大小、速度和其他因素。

这就结束了我们对标记化算法的考察。深入研究的下一步是了解什么是嵌入,标记化如何在创建这些嵌入中发挥重要作用,以及它们如何影响模型的性能。

对这些算法的进一步推进是SentencePiece算法,它是解决整个标记化问题的一种健康的方法。但是HuggingFace缓解了这个问题的大部分,甚至更好–他们在一个GitHub repo中实现了所有的算法。

如何零基础入门 / 学习AI大模型?

大模型时代,火爆出圈的LLM大模型让程序员们开始重新评估自己的本领。 “AI会取代那些行业?”“谁的饭碗又将不保了?”等问题热议不断。

不如成为「掌握AI工具的技术人」,毕竟AI时代,谁先尝试,谁就能占得先机!

想正式转到一些新兴的 AI 行业,不仅需要系统的学习AI大模型。同时也要跟已有的技能结合,辅助编程提效,或上手实操应用,增加自己的职场竞争力。

但是LLM相关的内容很多,现在网上的老课程老教材关于LLM又太少。所以现在小白入门就只能靠自学,学习成本和门槛很高

那么我作为一名热心肠的互联网老兵,我意识到有很多经验和知识值得分享给大家,希望可以帮助到更多学习大模型的人!至于能学习到多少就看你的学习毅力和能力了 。我已将重要的AI大模型资料包括AI大模型入门学习思维导图、精品AI大模型学习书籍手册、视频教程、实战学习等录播视频免费分享出来。

这份完整版的大模型 AI 学习资料已经上传优快云,朋友们如果需要可以微信扫描下方优快云官方认证二维码免费领取【保证100%免费

👉 福利来袭优快云大礼包:《2025最全AI大模型学习资源包》免费分享,安全可点 👈

全套AGI大模型学习大纲+路线

AI大模型时代的学习之旅:从基础到前沿,掌握人工智能的核心技能!

read-normal-img

640套AI大模型报告合集

这套包含640份报告的合集,涵盖了AI大模型的理论研究、技术实现、行业应用等多个方面。无论您是科研人员、工程师,还是对AI大模型感兴趣的爱好者,这套报告合集都将为您提供宝贵的信息和启示。

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

👉学会后的收获:👈
基于大模型全栈工程实现(前端、后端、产品经理、设计、数据分析等),通过这门课可获得不同能力;

能够利用大模型解决相关实际项目需求: 大数据时代,越来越多的企业和机构需要处理海量数据,利用大模型技术可以更好地处理这些数据,提高数据分析和决策的准确性。因此,掌握大模型应用开发技能,可以让程序员更好地应对实际项目需求;

• 基于大模型和企业数据AI应用开发,实现大模型理论、掌握GPU算力、硬件、LangChain开发框架和项目实战技能, 学会Fine-tuning垂直训练大模型(数据准备、数据蒸馏、大模型部署)一站式掌握;

能够完成时下热门大模型垂直领域模型训练能力,提高程序员的编码能力: 大模型应用开发需要掌握机器学习算法、深度学习框架等技术,这些技术的掌握可以提高程序员的编码能力和分析能力,让程序员更加熟练地编写高质量的代码。

👉 福利来袭优快云大礼包:《2025最全AI大模型学习资源包》免费分享,安全可点 👈

img

这份完整版的大模型 AI 学习资料已经上传优快云,朋友们如果需要可以微信扫描下方优快云官方认证二维码免费领取【保证100%免费

作为普通人,入局大模型时代需要持续学习和实践,不断提高自己的技能和认知水平,同时也需要有责任感和伦理意识,为人工智能的健康发展贡献力量。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值