当前位置: 首页 > news >正文

大模型Tokenizer原理:深入理解BPE与WordPiece子词编码技术

大模型Tokenizer原理:深入理解BPE与WordPiece子词编码技术

在大型语言模型的技术架构中,Tokenizer(分词器)是连接原始文本与模型输入的关键桥梁。不同于简单的按空格或标点分割,一个优秀的分词器需要将文本切分为模型能够高效处理的Token序列,同时尽可能保留语义信息。本文深入剖析当前大模型中最常用的两种子词分词算法——Byte Pair Encoding(BPE)和WordPiece,从底层原理到代码实现进行全面讲解。

BPE算法原理与训练过程

BPE最初由Philip Gage在1994年提出,用于数据压缩领域。其核心思想是通过迭代合并高频出现的字节对来构建符号表。这一思想被迁移到NLP领域后,成为构建子词词汇表的标准方法。

BPE训练的核心流程如下。首先,将训练语料中的每个单词拆分为字符序列,并在每个单词末尾添加特殊分隔符。同时统计每个单词出现的频率。例如单词"higher"会变为"h i g h e r“,单词"low"变为"l o w ``”。初始词汇表包含所有单个字符和特殊分隔符。

接下来进入迭代合并阶段。在每次迭代中,算法遍历所有相邻字符对,统计它们在语料库中共同出现的总频率。选择频率最高的字符对作为合并规则,加入词汇表,并将语料库中所有该字符对合并为一个新符号。这个过程重复进行,直到词汇表达到预设大小。

假设语料库中有单词"low"出现5次,“lower"出现2次,“new"出现3次。在初始状态下,字符序列分别为"l o w”、“l o w e r"和"n e w”。经过若干次迭代后,可能形成"lo”、"wer"等子词单元,这些子词能够组合表示原单词,同时在统计意义上具有更高的出现频率。

BPE的最终分词过程是确定性的。对于任意输入单词,首先拆分为字符序列,然后从左到右遍历,贪心地应用已学到的合并规则。每次检查当前位置是否存在可合并的字符对,如果存在则合并,否则保持原样并移动到下一个位置。这种方法保证每个单词都能被分解为词汇表中的子词组合。

WordPiece算法深度解析

WordPiece是Google为语音搜索系统开发的分词技术,后被BERT采用并广为人知。与BPE基于频率的贪心合并不同,WordPiece采用基于概率的训练目标,这导致了本质性的差异。

WordPiece的训练目标是最大化训练语料的语言模型概率。给定一个单词序列,完整的分词方案是将其切分为若干子词单元。设分词结果为(t1, t2, …, tn),则该分词方案的语言模型概率为各个子词条件概率的乘积:

P(分词) = P(``|t1) × P(t1|t2) × P(t2|t3) × … × P(tn-1|tn)

每个条件概率P(ti|ti+1)可以通过统计训练语料中子词对的出现频率计算得到:P(ti|ti+1) = Count(ti, ti+1) / Count(ti+1)。

在训练过程中,WordPiece需要决定哪两个子词应该合并。不同于BPE直接选择最高频的字符对,WordPiece评估的是合并后对语言模型概率的提升。具体来说,对于候选合并对(A, B),计算合并前的联合概率贡献与合并后的联合概率贡献之差,选择使整体似然提升最大的对。

这个差异在实际应用中产生了明显区别。考虑单词"unsupervised",BPE可能优先合并出现频率最高的字符对,而WordPiece会考虑合并后对整体句子概率的影响。如果"un"和"super"在语料中有明确且独立的语义作用,WordPiece可能选择保留它们而非强行合并。

分词阶段也存在差异。BPE采用确定性的贪心匹配,而WordPiece通常采用动态规划或类似Viterbi算法来寻找最优分词路径。具体而言,对于输入单词,从右到左(或从左到右)遍历所有可能的分词位置,计算每种分词方案的概率,选择概率最高的方案。

BPE代码实现详解

理解算法原理后,通过代码实现可以更深入地掌握细节。以下是一个完整的BPE训练和分词实现。

fromcollectionsimportCounter,defaultdictimportreclassBPE:def__init__(self,vocab_size=10000):self.vocab_size=vocab_size self.vocab={}self.merges={}defget_stats(self,vocab):"""统计所有字符对的频率"""pairs=Counter()forword,freqinvocab.items():symbols=word.split()foriinrange(len(symbols)-1):pairs[(symbols[i],symbols[i+1])]+=freqreturnpairsdefmerge_vocab(self,pair,vocab):"""合并所有词汇中的指定字符对"""v_out={}bigram=re.escape(pair[0]+' '+pair[1])pattern=re.compile(r'(?<!\S)'+bigram+r'(?!\S)')forwordinvocab:w_out=pattern.sub(''.join(pair),word)v_out[w_out]=vocab[word]returnv_outdeftrain(self,corpus):""" 训练BPE模型 corpus: 单词列表 """# 初始化词汇表:每个单词拆分为单字符vocab=Counter()forwordincorpus:word_tokens=list(word)+['</w>']vocab[' '.join(word_tokens)]+=1# 迭代合并whilelen(vocab)<self.vocab_size:pairs=self.get_stats(vocab)ifnotpairs:breakbest_pair=max(pairs,key=pairs.get)vocab=self.merge_vocab(best_pair,vocab)self.merges[best_pair]=Trueself.vocab[best_pair]=len(self.vocab)print(f"合并{best_pair},词汇表大小:{len(vocab)}")# 添加单字符到词汇表forcharinset(''.join(corpus))):ifcharnotinself.vocab:self.vocab[char]=len(self.vocab)deftokenize(self,text):"""对输入文本进行分词"""tokens=list(text)+['</w>']whilelen(tokens)>1:# 寻找第一个可合并的位置pairs=[(tokens[i],tokens[i+1])foriinrange(len(tokens)-1)]# 找优先级最高的合并min_rank=Nonemin_pair=Noneforpairinpairs:ifpairinself.merges:rank=self.merges[pair]ifmin_rankisNoneorrank<min_rank:min_rank=rank min_pair=pairifmin_pairisNone:break# 执行合并new_tokens=[]i=0whilei<len(tokens):ifi<len(tokens)-1and(tokens[i],tokens[i+1])==min_pair:new_tokens.append(''.join(min_pair))i+=2else:new_tokens.append(tokens[i])i+=1tokens=new_tokensreturn[tfortintokensift!='</w>']``` 这段实现展示了BPE的核心机制:词汇表构建阶段的迭代合并和分词阶段的贪心应用。关键点在于使用空格分隔符来标记字符边界,以及通过re.escape处理可能包含特殊字符的合并对。### WordPiece代码实现WordPiece的实现更加复杂,因为它需要维护完整的词汇表并使用动态规划进行最优分词。 ```pythonclassWordPiece:def__init__(self,vocab=None):self.vocab=vocabor{}self.unk_token='[UNK]'self.unk_id=0deftokenize(self,text):"""对文本进行分词,返回子词序列"""output_tokens=[]fortokeninself._basic_tokenize(text):chars=list(token)iftokeninself.vocab:output_tokens.append(token)continue# 尝试将单词切分为子词tokens=[]start=0whilestart<len(chars):end=len(chars)cur_substr=None# 从后向前寻找最长匹配whilestart<end:substr=''.join(chars[start:end])ifstart>0:substr='##'+substrifsubstrinself.vocab:cur_substr=substrbreakend-=1ifcur_substrisNone:# 没有找到匹配,返回UNKoutput_tokens.append(self.unk_token)breaktokens.append(cur_substr)start=end output_tokens.extend(tokens)returnoutput_tokensdef_basic_tokenize(self,text):"""基础分词:处理标点和空格"""importre# 简单实现:按空格分词,保留标点tokens=re.findall(r'\w+|[^\s\w]',text)return[t.lower()fortintokens]``` 实际应用中,WordPiece词汇表通常由专门的工具(如Google的sentencepiece或BERT的tokenization工具)生成。词汇表中的子词带有特定前缀标记(``##`)表示这是词内延续。### 大模型中的Tokenizer选择不同大模型选择了不同的Tokenizer策略,这些选择深刻影响了模型的能力边界。 GPT系列采用BPE的变体——ByteLevelBPE。关键改进是使用UTF-8字节而非Unicode字符作为初始单位。UTF-8中任何字符都可以表示为1-4个字节,这意味着词汇表可以从256个基础字节开始训练。这种方法有两个优势:理论上有无限的"字符"词汇表,以及能够处理任意Unicode字符串而不会出现未知字符问题。GPT-4的词汇表包含超过10万个Token,反映了其处理多语言和特殊符号的能力。 BERT采用WordPiece,这与其预训练任务设计密切相关。BERT使用Masked Language Modeling,需要将输入的一部分Token替换为[MASK],WordPiece的概率优化目标与此高度一致。此外,BERT的词汇表中包含丰富的词根和词缀,这有助于模型学习形态学特征。 SentencePiece是另一个值得了解的框架,由Google开发并被T5等模型采用。SentencePiece将输入视为原始字节流,可以直接训练BPE或Unigram模型,无需预分词步骤。这种端到端的处理方式避免了不同语言的分词规则差异,更适合多语言模型。### 分词对模型的影响理解Tokenizer的选择对实际应用至关重要。相同的文本经过不同Tokenizer会产生显著差异的Token序列长度。以"神经网络Transformer大模型"为例: 使用较小词汇表的Tokenizer可能产生15-20个Token,而使用更大词汇表的Tokenizer可能只需要8-12个Token。Token数量的差异直接影响计算成本(与Token数的平方成正比)、显存占用和推理延迟。 此外,分词粒度影响模型对语义的理解能力。过粗的分词(如按空格分词)会导致严重的OOV问题;过细的分词(如纯字符级)会显著增加序列长度,削弱模型捕捉长距离依赖的能力。子词分词在两者之间取得了平衡,通过数据驱动的方式学习适合目标语料的词汇表。---标签:大模型、Tokenization、BPE、WordPiece、NLP
http://www.jsqmd.com/news/725343/

相关文章:

  • 别再只调参了!手把手教你用PyTorch把ECA和CBAM‘拼’成新模块(附完整代码)
  • 别再只盯着L1了!手把手教你用GSS7000测试GPS L5信号(附PosApp实战避坑指南)
  • 保姆级教程:用Intel RealSense Viewer搞定D435i深度摄像头自校准,附三种场景实测对比
  • iMX93 Pro工业开发套件:边缘AI与实时控制解析
  • 软实时、NTP还是PTP?矿山数采时间同步方案实测与选型
  • Bilibili-Evolved性能优化实战:如何让B站视频播放更流畅稳定
  • 【2026实测】留学生怎么降论文AI率?3款应对海外检测工具盘点
  • 如何查看VM磁盘IOPS和吞吐量?esxtop实操指南
  • 手把手教你用ChmlFrp免费搞定远程桌面,告别向日葵和ToDesk收费烦恼
  • 从cursor-free-vip项目解析自动化工具开发与软件授权机制
  • 如何三步打造专属MapleStory游戏世界:全能编辑器解决方案
  • 达梦DCA认证通关后,我总结的这12个高频考点操作命令(附脚本)
  • WarcraftHelper:三步搞定魔兽争霸3性能优化,解锁300帧率与宽屏体验
  • 终极指南:如何使用HSTracker在macOS上免费管理炉石传说套牌与对战数据
  • Nintendo Switch文件处理终极指南:5个核心技巧让NSC_BUILDER成为你的游戏管理利器
  • 机器翻译评估工具对比与性能优化实践
  • WeChatMsg:终极微信聊天记录备份与导出完整指南
  • 【matlab代码】基于粒子群算法的分布式电源选址定容多目标优化
  • 3大核心模块:UiCard框架为Unity卡牌游戏提供完整UI解决方案
  • 2026年PP喷淋塔厂家深度选型:如何为工业废气治理匹配最佳方案? - 博客湾
  • 给驱动开发者的避坑指南:如何避免你的代码触发Linux内核的RCU Stall警告
  • BiliRoamingX:解锁B站完整观影体验的实用指南
  • 区块链预言机如何让天气数据驱动DeFi与智能合约应用
  • 大模型岗位傻傻分不清?小白程序员必看!收藏这份超全解析,助你轻松入行大模型!
  • 2026 广西北海靠谱旅行社盘点推荐,细节拉满,旅途更舒心 - 品牌智鉴榜
  • LeRobot实战指南:3步构建端到端机器人AI系统
  • 深度解析Bilibili-Evolved架构设计:实现60fps流畅播放的系统级优化方案
  • “薪资open”“不设上限”:谈薪资时HR的5种套路及反杀话术
  • 从安装到调优:手把手教你配置ShardingSphere-Proxy的server.yaml与解决启动报错
  • ScienceDecrypting:终极CAJ文档解密方案,一键解除科学文库访问限制