news 2026/5/14 6:38:15

分词的艺术:为 AI 分解文本

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
分词的艺术:为 AI 分解文本

原文:towardsdatascience.com/the-art-of-tokenization-breaking-down-text-for-ai-43c7bccaed25?source=collection_archive---------0-----------------------#2024-09-26

揭开 NLP 的神秘面纱:从文本到嵌入

https://medium.com/@murilogustineli?source=post_page---byline--43c7bccaed25--------------------------------https://towardsdatascience.com/?source=post_page---byline--43c7bccaed25-------------------------------- Murilo Gustineli

·发表于Towards Data Science ·10 分钟阅读·2024 年 9 月 26 日

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/10347347f8af7b1b60b09cc2d9a55932.png

由 Llama-3-8B 生成的分词示例。每个不同颜色的子词代表一个独立的标记(token)。

什么是分词(Tokenization)?

在计算机科学中,我们将像英语和普通话这样的语言称为“自然”语言。相反,像汇编语言和 LISP 这样的语言,专为与计算机交互而设计,被称为“机器”语言,遵循严格的句法规则,几乎没有解释的余地。尽管计算机擅长处理自身高度结构化的语言,但它们在处理人类语言的混乱性方面却表现得相当挣扎。

语言——尤其是文本——构成了我们大部分的沟通和知识存储。例如,互联网主要由文本组成。像ChatGPT、Claude和Llama这样的大型语言模型,都是通过使用复杂的计算技术,在海量的文本上进行训练——本质上是互联网上所有可用的文本。然而,计算机处理的是数字,而不是单词或句子。那么,我们如何弥合人类语言与机器理解之间的差距呢?

这就是**自然语言处理(NLP)**的作用所在。NLP 是一个结合语言学、计算机科学和人工智能的领域,旨在使计算机能够理解、解释和生成自然语言。无论是将文本从英语翻译成法语、总结文章,还是进行对话,NLP 都能让机器从文本输入中生成有意义的输出。

自然语言处理的第一步是将原始文本转化为计算机能够有效处理的格式。这个过程称为分词。分词是将文本分解成更小、易于处理的单位,称为词元,这些词元可以是单词、子词甚至是单个字符。以下是该过程的典型工作方式:

["the","quick","brown","fox","jumps","over","the","lazy","dog"]

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/404ea4ba951265efc54d7a42d444724f.png

插图灵感来源于《Python 深度学习作者:François Chollet](https://www.manning.com/books/deep-learning-with-python-second-edition)中的“图 11.1 从文本到向量”

分词不仅仅是拆分文本;它是以一种保留意义和上下文的方式准备语言数据,以便计算模型使用。不同的分词方法会显著影响模型理解和处理语言的效果。

在本文中,我们将重点讨论文本标准化和分词,探讨几种技术和实现方法。我们将为将文本转换为机器可以处理的数值形式打下基础——这是迈向更高级主题(如词嵌入和语言建模)的一项关键步骤,未来的文章中我们将深入讨论这些内容。

文本标准化

请看这两个句子:

1.“dusk fell, i was gazing at the Sao Paulo skyline. Isnt urban life vibrant??”

2.“Dusk fell; I gazed at the São Paulo skyline. Isn’t urban life vibrant?”

初看这些句子,它们传达了类似的意思。然而,当计算机处理这些句子时,尤其是在分词或编码任务中,由于微小的变化,它们可能表现出截然不同的结果:

这些差异可能会显著影响算法如何解读文本。例如,“Isnt”没有撇号,可能不会被识别为“is not”的缩写,而像“São”中的特殊字符“ã”可能会被误解或导致编码问题。

文本标准化是自然语言处理中的一个关键预处理步骤,它解决了这些问题。通过标准化文本,我们减少了无关的变化,确保输入到模型中的数据是一致的。这个过程是一种特征工程方法,我们消除了对于当前任务没有意义的差异。

一种简单的文本标准化方法包括:

将这些步骤应用到我们的句子中,我们得到:

1.“dusk fell i was gazing at the sao paulo skyline isnt urban life vibrant”

2.“dusk fell i gazed at the sao paulo skyline isnt urban life vibrant”

现在,句子更加统一,突出了只有在单词选择上的有意义差异(例如“was gazing at”“gazed at”的区别)。

虽然有更高级的标准化技术,如词干提取(将单词还原为词根形式)和词形还原(将单词还原为词典形式),但这种基本方法有效地最小化了表面上的差异。

文本标准化的 Python 实现

下面是如何在 Python 中实现基本文本标准化的方法:

importreimportunicodedatadefstandardize_text(text:str)->str:# Convert text to lowercasetext=text.lower()# Normalize unicode characters to ASCIItext=unicodedata.normalize('NFKD',text).encode('ascii','ignore').decode('utf-8')# Remove punctuationtext=re.sub(r'[^\w\s]','',text)# Remove extra whitespacetext=re.sub(r'\s+',' ',text).strip()returntext# Example sentencessentence1="dusk fell, i was gazing at the Sao Paulo skyline. Isnt urban life vibrant??"sentence2="Dusk fell; I gazed at the São Paulo skyline. Isn't urban life vibrant?"# Standardize sentencesstd_sentence1=standardize_text(sentence1)std_sentence2=standardize_text(sentence2)print(std_sentence1)print(std_sentence2)

输出:

dusk fell i was gazing at the sao paulo skyline isnt urban life vibrant dusk fell i gazed at the sao paulo skyline isnt urban life vibrant

通过标准化文本,我们已经最小化了可能会混淆计算模型的差异。模型现在可以专注于句子之间的变化,比如“was gazing at”“gazed at”之间的区别,而不是像标点符号或大小写等差异。

标记化

在文本标准化后,自然语言处理中的下一个关键步骤是标记化。标记化涉及将标准化后的文本拆分成更小的单元,称为标记。这些标记是模型用来理解和生成自然语言的基本构建块。标记化为向量化做准备,其中每个标记都被转换为机器可以处理的数值表示。

我们的目标是将句子转换成计算机可以高效处理的形式。标记化有三种常见方法:

1. 单词级标记化

根据空格和标点符号将文本拆分成单独的单词。这是分解文本最直观的方式。

text="dusk fell i gazed at the sao paulo skyline isnt urban life vibrant"tokens=text.split()print(tokens)

输出:

['dusk','fell','i','gazed','at','the','sao','paulo','skyline','isnt','urban','life','vibrant']

2. 字符级标记化

将文本拆分成单独的字符,包括字母,有时也包括标点符号。

text="Dusk fell"tokens=list(text)print(tokens)

输出:

['D','u','s','k',' ','f','e','l','l']

3. 子词标记化

将单词拆分成更小的、有意义的子词单元。这种方法在字符级别的分词粒度与词汇级别分词的语义丰富性之间取得了平衡。像字节对编码(BPE)WordPiece这样的算法属于这一类别。例如,BertTokenizer 将“I have a new GPU!”分词如下:

fromtransformersimportBertTokenizer text="I have a new GPU!"tokenizer=BertTokenizer.from_pretrained("bert-base-uncased")tokens=tokenizer.tokenize(text)print(tokens)

输出:

['i','have','a','new','gp','##u','!']

在这里,“GPU”被拆分为“gp”“##u”,其中“##”表示“u”是前一个子词的延续。

子词分词提供了一种在词汇大小和语义表示之间的平衡方法。通过将稀有词拆解为常见的子词,它保持了可管理的词汇大小,而不牺牲含义。子词携带着有助于模型更有效理解上下文的语义信息。这意味着,模型可以通过将新词或稀有词分解成熟悉的子词来处理它们,从而提高其处理更广泛语言输入的能力。

例如,考虑单词“annoyingly”,它在训练语料库中可能比较稀有。它可以被拆解为子词“annoying”“ly”“annoying”“ly”在它们各自的形式中更为常见,并且它们的组合含义保留了“annoyingly”的本质。这种方法在粘着语(如土耳其语)中尤其有益,因为这些语言中的单词可以通过将子词组合在一起,形成极长的词来传达复杂的含义。

请注意,标准化步骤通常会集成到分词器本身。大型语言模型在处理文本时,使用标记作为输入和输出。以下是由 Llama-3–8B 在Tiktokenizer上生成的标记的可视化表示:

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/9dc6a0f02ad1b56bfc550734d2ff6555.png

Tiktokenizer示例使用Llama-3–8B。每个标记都用不同的颜色表示。

此外,Hugging Face 提供了一份出色的分词器总结指南,我在本文中使用了其中的一些示例。

现在让我们探索不同的子词分词算法是如何工作的。请注意,所有这些分词算法都依赖于某种形式的训练,通常是在与对应模型训练相关的语料库上进行的。

字节对编码(BPE)

B字节对编码(Byte-Pair Encoding,BPE)是一种子词分词方法,最早由 Sennrich 等人在 2015 年的论文 《使用子词单元的稀有词神经机器翻译》 中提出。BPE 从一个包含所有唯一字符的基础词汇开始,逐步合并最频繁的符号对——这些符号可以是字符或字符序列——以形成新的子词。这个过程会持续进行,直到词汇表达到预定义的大小,这是你在训练前选择的超参数。

假设我们有以下单词及其频率:

我们的初始基础词汇包含以下字符:[“h”, “u”, “g”, “p”, “n”, “b”, “s”]

我们将单词拆分为单个字符:

接下来,我们计算每个符号对的频率:

最频繁的字符对是“u g”(出现 20 次),因此我们将“u”“g”合并为“ug”并更新我们的单词:

我们继续进行此过程,合并下一个最频繁的符号对,例如将“u n”合并为“un”,直到达到我们期望的词汇大小。

BPE 通过指定合并操作的次数来控制词汇大小。频繁的单词保持不变,从而减少了大量记忆的需求。同时,罕见或未见过的单词可以通过已知子词的组合来表示。它被用于像GPTRoBERTa这样的模型中。

Hugging Face 分词器库提供了一种快速且灵活的方法来训练和使用分词器,包括 BPE。

训练 BPE 分词器

下面是如何在一个示例数据集上训练 BPE 分词器的方法:

fromtokenizersimportTokenizerfromtokenizers.modelsimportBPEfromtokenizers.trainersimportBpeTrainerfromtokenizers.pre_tokenizersimportWhitespace# Initialize a tokenizertokenizer=Tokenizer(BPE())# Set the pre-tokenizer to split on whitespacetokenizer.pre_tokenizer=Whitespace()# Initialize a trainer with desired vocabulary sizetrainer=BpeTrainer(vocab_size=1000,min_frequency=2,special_tokens=["[UNK]","[CLS]","[SEP]","[PAD]","[MASK]"])# Files to train onfiles=["path/to/your/dataset.txt"]# Train the tokenizertokenizer.train(files,trainer)# Save the tokenizertokenizer.save("bpe-tokenizer.json")

使用训练好的 BPE 分词器:

fromtokenizersimportTokenizer# Load the tokenizertokenizer=Tokenizer.from_file("bpe-tokenizer.json")# Encode a text inputencoded=tokenizer.encode("I have a new GPU!")print("Tokens:",encoded.tokens)print("IDs:",encoded.ids)

输出:

Tokens:['I','have','a','new','GP','U','!']IDs:[12,45,7,89,342,210,5]

WordPiece

WordPiece是另一种子词分词算法,由 Schuster 和 Nakajima 于 2012 年 提出,并由像BERT这样的模型广泛使用。与 BPE 相似,WordPiece 也从所有唯一字符开始,但在选择合并的符号对时有所不同。

下面是 WordPiece 的工作原理:

  1. 初始化:从包含所有唯一字符的词汇表开始。

  2. 预分词:将训练文本拆分为单词。

  3. 构建词汇表:通过迭代添加新的符号(子词)到词汇表中。

  4. 选择标准:与选择最常见的符号对不同,WordPiece 选择的符号对是将其加入词汇表后,最大化训练数据的可能性。

使用与之前相同的词频,WordPiece 评估哪个符号对在合并后能最有效地提高训练数据的概率。这比 BPE 基于频率的方法更具概率性。

类似于 BPE,我们可以使用tokenizers库训练一个 WordPiece 分词器。

训练一个 WordPiece 分词器

fromtokenizersimportTokenizerfromtokenizers.modelsimportWordPiecefromtokenizers.trainersimportWordPieceTrainerfromtokenizers.pre_tokenizersimportWhitespace# Initialize a tokenizertokenizer=Tokenizer(WordPiece(unk_token="[UNK]"))# Set the pre-tokenizertokenizer.pre_tokenizer=Whitespace()# Initialize a trainertrainer=WordPieceTrainer(vocab_size=1000,min_frequency=2,special_tokens=["[UNK]","[CLS]","[SEP]","[PAD]","[MASK]"])# Train the tokenizertokenizer.train(files,trainer)# Save the tokenizertokenizer.save("wordpiece-tokenizer.json")

使用训练好的 WordPiece 分词器:

fromtokenizersimportTokenizer# Load the tokenizertokenizer=Tokenizer.from_file("wordpiece-tokenizer.json")# Encode a text inputencoded=tokenizer.encode("I have a new GPU!")print("Tokens:",encoded.tokens)print("IDs:",encoded.ids)

输出:

Tokens:['I','have','a','new','G','##PU','!']IDs:[10,34,5,78,301,502,8]

结论

分词是自然语言处理中的基础步骤,旨在为计算模型准备文本数据。通过理解和实施适当的分词策略,我们使模型能够更有效地处理和生成自然语言,为像词嵌入和语言建模等高级主题打下基础。

本文中的所有代码也可以在我的 GitHub 仓库中找到:github.com/murilogustineli/nlp-medium

其他资源

除非另有说明,所有图片均由作者创建。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/14 6:36:06

柔性数据库设计:AI Agent时代的关系型数据库Schema动态扩展方案

1. 项目概述:一个为AI Agent设计的柔性数据库框架如果你和我一样,经常在Claude、Cursor这类AI IDE里折腾,想把各种零散信息——比如网页摘录、会议笔记、PDF报告、甚至是聊天记录——都规整到一个地方,那你肯定遇到过这个头疼的问…

作者头像 李华
网站建设 2026/5/14 6:31:05

Sticky便签:Linux桌面笔记管理的终极解决方案

Sticky便签:Linux桌面笔记管理的终极解决方案 【免费下载链接】sticky A sticky notes app for the linux desktop 项目地址: https://gitcode.com/gh_mirrors/stic/sticky 你是否曾在灵感闪现时手忙脚乱找纸笔?是否因为忘记重要事项而错失良机&a…

作者头像 李华
网站建设 2026/5/14 6:21:10

解决腾讯云服务器上 Git 克隆超时与 Docker 镜像拉取失败问题

背景 近日在腾讯云服务器(Ubuntu 22.04)上部署开源项目 new-api 时,遇到了两个典型问题: 使用 git clone 从 GitHub 拉取代码时,出现 RPC failed: curl 56 Recv failure: Connection timed out 错误,导致克…

作者头像 李华