【LLM基础知识】深入理解 Tokenization:大语言模型的第一课

📅 发布时间:2026/7/10 7:34:02 👁️ 浏览次数:
【LLM基础知识】深入理解 Tokenization:大语言模型的第一课
在大语言模型处理任何文本之前都需要先将人类的语言转化为机器能理解的数字序列——这个过程就是 Tokenization分词。理解它是理解整个 LLM 技术栈的起点。引言​ 当你在 ChatGPT 的对话框中输入今天天气真好并按下回车时模型看到的并不是这几个汉字而是一串数字比如[38392, 45668, 8997, 1325]。这个从自然语言到数字序列的转换过程就是Tokenization分词。​ 分词看似简单实际上它的设计直接影响模型的词汇量、上下文理解能力、对多语言和罕见词的处理效果甚至影响推理速度和训练成本。可以说分词是整个 NLP 系统设计中影响最深远的决策之一。​ 本文将从基本概念出发逐步介绍分词的原理、流程和常见方法帮助你建立对 Tokenization 的系统性理解。一、什么是 Tokenization​Tokenization分词是将文本拆分为更小单元的过程这些单元称为词元Token。词元可以是单词、子词或字符分词使大语言模型能够以结构化且高效的方式处理语言输入是 NLP 和 LLM 训练中的基础步骤。​ 需要注意的是在深度学习模型中词元不一定等同于自然语言中的单词。例如unhappiness可能被拆分为[un, happi, ness]三个词元而不是作为一个完整的词处理。​ 分词不仅仅是将文本拆开它更像是为计算机构建语言的理解入口。模型并不像人类一样能够自然地识别词语和语义边界因此必须提前将文本切分成便于处理的基本单位。这一过程需要以尽可能保留语义结构和上下文关联的方式来组织数据从而使模型更准确地理解句子的含义。1.1 词元(Token)和嵌入(Embedding)​ 词元和嵌入是理解 LLM 工作原理的两个核心概念。语言模型处理文本时首先将其切分成词元然后将每个词元转换为数值表示—即嵌入向量Embedding。嵌入向量是一个多维数值向量能够捕捉词元的含义和上下文关系。​​ 如下图所示每个词被映射到向量空间中的一个点语义相近的词在空间中的距离也更近。如果没有对词元和嵌入的深入理解就无法清楚地了解 LLM 的工作原理、构建方式及其未来的发展方向。1.2 为什么需要 Tokenization​ 为什么不能直接把原始文本交给模型处理主要有两个原因统一输入格式LLM 对固定大小的输入进行操作但自然语言输入的长度是动态的。分词将文本分解为固定格式的词元序列使其成为模型可以处理的标准化输入。降低词汇维度如果以完整的单词作为最小单位词汇表将非常庞大英语中有数十万个单词。通过使用子词分词模型可以用一个更小的词汇表来表示几乎所有文本大幅减少了参数量和计算成本。此外不同的分词方式会直接影响模型的表现影响维度说明语义理解能力分词粒度决定了模型能否识别词义的完整性罕见词处理子词分词可以将未见过的词拆解为已知的子词序列长度与计算效率粒度越细序列越长计算成本越高模型泛化能力合理的分词策略有助于模型在不同领域间迁移二、Tokenization的完整流程​ 从原始文本到模型输入Tokenization 包含以下几个步骤文本标准化Text Normalization对文本进行预处理以确保一致性包括转小写、移除标点、Unicode 归一化等。分词Tokenization将标准化文本切分成词元文本被切分成词向量。例如the dog sat on the couch可以被分为[the, dog, sat, on, the, couch]。数值编码Numericalization每个词元被映射到词汇表中的唯一索引转换为模型可以处理的数字序列。词元 → Token ID查词表映射为整数索引。嵌入EmbeddingToken ID → 稠密向量通过 Embedding 层将离散 ID 映射为连续的高维向量在实际操作中还需要事先完成以下准备工作选择分词方法常用方法包括字节对编码BPEGPT 系列使用和 WordPieceBERT 使用。设置分词器参数包括词汇量大小模型可识别的唯一词元数以及特殊词元如句子开头/结尾标记。在目标数据上训练分词器分词器应在与推理场景匹配的数据集上训练。在英语文本上训练的分词器其词汇表与在代码或多语言数据集上训练的分词器会有很大差异。2.1 文本标准化Text Normalization​ 当我们处理自然语言文本时看似相似的句子对计算机而言却可能完全不同。例如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​ 尽管人类可以轻松理解这两句话表达的是同一意思但以下细微差别都会改变文本的表示方式大写差异Duskvs.dusk标点差异逗号、分号、问号的有无缩写差异Isntvs.Isnt特殊字符Sao Paulovs.São Paulo​文本标准化的目标是减少这些无关的文本变异性使文本在进入模型前变得一致且可控。它是一种典型的特征工程操作通过消除噪声强化对模型真正有意义的信息。(1) 基础标准化方法​ 基础的文本标准化方法包括全部转为小写Lowercasing减少大小写导致的重复项。例如Apple与apple被视为同一词。移除标点符号Removing Punctuation对某些任务标点不影响语义移除它们可降低干扰。归一化特殊字符Unicode Normalization如将ã→a降低编码差异带来的影响。自然语言中存在大量 Unicode 变体原字符Unicode 标准化后ASCII“São”“São” (a ~)“Sao”“caf锓café” (e ´)“cafe”(2) Python实现​ 主要经过 lower → NFKD ASCII → 去标点 → 压缩空格 四步处理最终输出干净的文本供后续分词使用。转小写texttext.lower()“Dusk” → “dusk”“São” → “são”。消除大小写差异。Unicode 归一化 ASCII 转换textunicodedata.normalize(NFKD,text)texttext.encode(ascii,ignore).decode(utf-8)​ 首先normalize(NFKD, text)— 将字符分解为基字符 组合符号。例如 ã 被分解为 a 组合波浪号é 被分解为 e 组合锐音符。​ 之后.encode(ascii, ignore)— 编码为 ASCIIignore 参数表示丢弃所有非 ASCII 字符组合符号会被丢掉。​ 最后.decode(utf-8)— 再解码回字符串。​ 效果“são paulo” → “sao paulo”“café” → “cafe”除标点text re.sub(r[^\w\s], , text)正则含义\w— 匹配字母、数字、下划线\s— 匹配空白字符[^\w\s]— 匹配既不是字母数字也不是空白的字符即标点符号替换为空字符串等于删除效果isnt urban life vibrant?? → isnt urban life vibrant压缩空格textre.sub(r\s, ,text).strip()\s— 匹配一个或多个连续空白字符替换为单个空格 .strip()— 去除首尾空格防止前面的操作如移除标点留下多余空格。完整代码importreimportunicodedataimportlogging# 配置 logginglogging.basicConfig(levellogging.INFO,format%(asctime)s - %(levelname)s - %(message)s)loggerlogging.getLogger(__name__)defstandardize_text(text:str)-str: 对输入文本执行标准化处理包括 1. 转为小写lowercase 2. Unicode 规范化并转为 ASCII 3. 移除标点符号 4. 规范空格格式 logger.info(Original text: %s,text)# 将文本转换为小写texttext.lower()logger.info(After lowercasing: %s,text)# Unicode 规范化为 ASCIItextunicodedata.normalize(NFKD,text)texttext.encode(ascii,ignore).decode(utf-8)logger.info(After Unicode normalization: %s,text)# 移除标点符号textre.sub(r[^\w\s],,text)logger.info(After removing punctuation: %s,text)# 移除多余的空格textre.sub(r\s, ,text).strip()logger.info(After removing extra spaces: %s,text)returntext# 例句sentence1dusk fell, i was gazing at the São Paulo skyline. Isnt urban life vibrant??sentence2Dusk fell; I gazed at the São Paulo skyline. Isnt urban life vibrant?# 标准化句子std_sentence1standardize_text(sentence1)std_sentence2standardize_text(sentence2)​ 运行输出2025-11-1810:32:45 - INFO - Original text: dusk fell, i was gazing at the São Paulo skyline. Isnt urban life vibrant?? 2025-11-18 10:32:45 - INFO - After lowercasing: dusk fell, i was gazing at the são paulo skyline. isnt urban life vibrant??2025-11-1810:32:45 - INFO - After Unicode normalization: dusk fell, i was gazing at the sao paulo skyline. isnt urban life vibrant??2025-11-1810:32:45 - INFO - After removing punctuation: dusk fell i was gazing at the sao paulo skyline isnt urban life vibrant2025-11-1810:32:45 - INFO - After removing extra spaces: dusk fell i was gazing at the sao paulo skyline isnt urban life vibrant​ 标准化后两句的输出为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 atvs.gazed at而不是无意义的格式差异。​ 通过文本标准化我们能最大限度地减少由大小写、标点、字符编码等因素引入的噪声使模型将注意力集中在真正有用的内容上。(3) 高级标准化技术除了上述基础方法实际应用中还可以使用更高级的标准化技术来进一步减少词形变化。词干提取Stemming 通过截断词尾获得词干。例如 gazing → gaz。这种方法速度快但结果可能不是合法的单词。词形还原Lemmatization 通过查找词典将词还原为标准形式。例如 gazing →gaze。语义保留更好但依赖词典资源速度相对较慢。两者的核心区别在于Stemming 是基于规则的粗暴截断Lemmatization是基于词典的精确还原。在对语义精度要求较高的场景中推荐使用 Lemmatization。2.2 分词方法​ 经过文本标准化之后下一步就是选择合适的分词方法。常见的分词方法有三种字符级分词、词级分词和子词分词它们在粒度和语义表达之间做出了不同的权衡。类型示例特点Word Token(词级分词)“I love NLP” → [“I”, “love”, “NLP”]按空格或标点分词适合英语等语言Subword Token(子词级分词)“unhappiness” → [“un”, “happi”, “ness”]通过 BPE / WordPiece 等方法将稀有词拆分为子词Character Token(字符级分词)“hello” → [“h”, “e”, “l”, “l”, “o”]最小粒度OOV未登录词处理能力强Byte / Byte-Pair Token字节级分词兼容任意编码支持多语言常用于 GPT / LLaMA 等模型(1) 字符级分词​ 字符级分词将文本分解成单个字符是粒度最细的分词方式。它的词汇表非常小例如英语只需 26 个字母加少量符号且天然不存在未登录词OOV问题。但缺点是生成的序列很长单个字符难以承载语义信息。外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传defchar_level_tokenizer(text:str)-list:tokenslist(text)returntokensChar level tokenization: [d, u, s, k, , f, e, l, l, , ...](2) 词级分词​ 词级分词根据空格和标点符号将文本拆分成单个单词是最直观的分词方式。它保留了完整的词义信息但面对未见过的新词OOV时无能为力且词汇表可能非常庞大。最简单的实现方式是使用 Python 的split()函数defword_level_tokenizer(text:str)-list:tokenstext.split()returntokens对之前标准化后的两句话进行词级分词Word level tokenization1: [dusk, fell, i, was, gazing, at, the, sao, paulo, skyline, isnt, urban, life, vibrant] Word level tokenization2: [dusk, fell, i, gazed, at, the, sao, paulo, skyline, isnt, urban, life, vibrant](3) 子词分词​ 子词分词将单词拆分成更小、更有意义的子词单元。这种方法兼顾了字符级分词的灵活性和词级分词的语义丰富性是目前主流 LLM 采用的方案。字节对编码BPE和WordPiece是两种最常用的子词分词算法。​ 例如使用 BERT 的 WordPiece 分词器对I have a new GPU!进行分词fromtransformersimportBertTokenizerdefsubword_level_tokenizer(text:str)-list:tokenizerBertTokenizer.from_pretrained(bert-base-uncased)tokenstokenizer.tokenize(text)returntokens# 输出: [i, have, a, new, gp, ##u, !]​ 可以看到常见词如have、new保持完整而较少见的词GPU被拆分为gp和##u##前缀表示该子词是前一个词的延续部分。​子词分词在词汇量和语义表示之间提供了平衡通过将罕见词分解为常用子词它在不牺牲语义的前提下保持了可控的词汇量使模型能够处理更广泛的语言输入。三、Tokenizer 数据流​ 了解了分词的概念和方法之后我们来看看在实际的模型训练流程中Tokenizer 是如何工作的。下图展示了训练 Tokenizer 并将其应用于 NLP 模型的完整流程收集语料首先收集大量原始文本作为训练语料语料应覆盖目标语言和领域。训练 Tokenizer使用训练语料训练分词器如 BPE、WordPiece、SentencePiece 等输出词表vocabulary和分词规则。文本编码使用训练好的分词器对预训练语料进行编码将文本转换为词元序列Token IDs。模型输入Token ID 序列输入神经网络模型进行向量化、嵌入计算和后续任务处理。四、总结​ 本文从 Tokenization 的基本概念出发介绍了它在 LLM 中的核心作用将人类语言转化为模型可处理的数字序列。我们依次讨论了文本标准化的预处理技术、三种主流分词方法字符级、词级、子词级的原理与优劣以及 Tokenizer 在实际训练流程中的数据流。​ 关键要点回顾分词是 NLP 的基础——它决定了模型看到的是什么。文本标准化是分词的前置步骤消除噪声、统一格式。子词分词如 BPE、WordPiece是目前的主流方案在词汇量和语义表达之间取得了最佳平衡。分词方法的选择会直接影响模型的性能、效率和泛化能力。在后续文章中我们将深入探讨 BPE 和 WordPiece 等子词分词算法的具体实现原理敬请期待。