词表大小对训练的影响:32K、50K、100K 词表,哪个训练效率最高?

有一段时间我特别迷信“词表越大,训练越快”这个说法。理由是:词表越大,一段文本被切成的token数量就越少,序列越短,模型的训练计算量自然就越小。这个逻辑看着毫无破绽。直到我把一个模型的词表从32K换成100K,训练了快一整晚,步数没省,损失还掉得更慢了。我盯着训练曲线想了很久才明白:我完全忽略了一个事实——词表变大不只是把序列变短,它还让模型的每一个token都要面对一个更大的预测空间,同时嵌入层的参数也暴涨了。

AI technology illustration

这里有个关键概念需要先说清:我们说的“词表”,是tokenizer里所有独立token的集合。模型并不直接读单词,它先把文本切成token,再把每个token映射成一个向量。比如GPT系列常用的BPE算法,就是把“united kingdom”切成“united”和“kingdom”这样的子词单元。词表大小就是这个“词典”里一共收录了多少个token。

既然词表大小决定token切分方式,它就直接影响两件事:

  • 序列长度 L:词表越大,每个词越可能被一个token表示,句子整体被切得更短。
  • 预测空间 V:模型每一步都要从V个token中预测下一个,V越大,分类头越重,计算量越大。

Transformer训练的总计算量大致由两部分构成:一部分来自序列长度L,注意力部分是O(L²)的复杂,前馈网络部分是O(L·d²);另一部分来自词表V,就是最后那个softmax层需要计算V个logits。于是你会发现,改变词表大小其实是在两本账之间做交易:用更大的V换取更小的L。但问题是,这个交易的汇率并不是固定的。

我用一个常见的7B模型参数d_model=4096来算笔账(这里只算词表相关的开销):

词表大小 嵌入层参数量(百万) Softmax相对开销 序列长度(相对) 适合场景
32K 131 1.0 小模型、低资源、短序列
50K 205 1.56× 约0.85 通用大模型、英文为主
100K 410 3.13× 约0.7 超大模型、多语言、长文本

注意表格里的序列长度只是示意,不是精确数字。它取决于语料分布和tokenizer训练方式。英文上,从32K扩到100K,序列长度能压缩15%~30%就算不错;但softmax的开销却翻了3倍多。如果模型本身不大,前馈网络和注意力计算占比有限,那么省下的序列成本根本填不上softmax增加的坑。

来看一个更具体的假设。假设一段语料有512个英文单词,在32K词表下平均每个词被切成1.7个token,序列长870;在100K词表下平均每个词只切1.3个token,序列长666。注意力部分从870²≈75.7万次交互降到666²≈44.4万次,省了40%;前馈网络部分跟序列长度线性相关,省了约23%。但与此同时,softmax的计算量涨了3倍多(32K→100K)。如果模型层数多、前馈网络占大头,序列变短带来的收益会超过softmax的损失;反过来,如果你的模型很小,每一步的softmax占比很高,大词表就会拖累训练速度。

这就是为什么历史那些著名模型并没有整齐地选同一个词表。GPT-2GPT-3用的是50,257个token(字节级BPE),T5用了32,000(SentencePiece),LLaMA系列也选择32,000。为什么?因为当时它们主要面对英文社群,32K到50K之间是英文BPE的分割效率拐点——再往上,序列长度压缩的边际收益开始递减,而参数和计算开销却线性上涨,不划算。

顺带提一句,50K这个数字不是玄学。在英文语料上,当BPE词表低于32K时,常见的复合词只能拆成碎片,序列长度显著增长;高于50K之后,新加入的词条大多是专有名词和生僻词,出现次数太少,对序列长度的边际改善极小。所以GPT系列没有继续膨胀,反而是有道理的。

值得说的是,多语言模型普遍选择更大的词表。mT5的词汇表达到了250K,因为要覆盖100多种语言,字符集和词法差异巨大,没有足够的token会在很多语言上造成“死区”。你可以把语言看作一个分量——单语模型用50K可以,但跨语种模型可能需要100K甚至更高。

到此你可能以为大词表唯一的代价是参数多、softmax慢。但还有一个更隐蔽的问题:梯度稀疏。训练时每个batch里出现的token只是全词表的一个子集。假设batch里有2000个不同的token,但词表是100K,那么只有2%的嵌入行会被更新。低频token本来就接触少,分到它们的梯度更是少得可怜。结果是:大词表上的罕见词嵌入长期停留在随机初始化附近,不但在训练时拖累收敛,还会在推理时生成怪异的token。

还有一个很多人没算到的成本:显存。7B模型d=4096时,100K词表的嵌入层有4.09亿参数,按bf16算大约820MB;而32K只需要250MB。多卡训练要把这部分显存分摊出去,否则就得减小batch size,这又会间接拖慢训练效率。

那该怎么选?给你一套我自己的判断框架:

  1. 如果你在训练小于10B的模型,且语料以英文为主,32K~50K基本不出错。
  2. 如果你的语料包含大量中文、日文等多字节语言,或者任务需要更快的推理速度,64K~100K值得尝试,但要准备好显存和调参成本。
  3. 如果你在做多语言大模型,直接对标mT5那种100K~250K的方案,别在32K上纠结。

最后,用一句我踩坑后才记住的话收尾:词表小,序列长,但每一步轻;词表大,序列短,但每一步重。训练效率是这两股力量拔河的结果,不是看谁听起来更“高端”。下一次看到某个模型炫耀自己词表100K,先别急着羡慕,算算你自己的显存和数据量。

常见问题

Q:为什么我增加词表后训练速度反而更慢?

因为你的模型可能比较小,或序列本身就短,softmax和嵌入的计算占比高,大词表带来的序列压缩不足以补偿新增的开销。

Q:100K词表的模型生成文本更快吗?

有可能,但不一定。生成速度取决于“每步解码一个token”的时间。如果100K词表让每个词从2个token变成1个token,确实解码步数变少;但每一步的logits计算也变慢,是否划算要实测。

Q:可不可以先训练大词表,之后再压缩?

压缩词表需要重新训练tokenizer和嵌入层,通常会掉点,而且很可能并不比一开始选对词表更省事。实践中不如在训练前做好这个决策。

进阶:大词表的工程补救

如果因为某些原因必须用超大词表,有几种常见方案:嵌入层分解(factorized embedding)、adaptive softmax、输入输出嵌入共享等。这些方案能把参数规模压下来,但会引入新的结构复杂度,适合已经明确需要大词表的场景。

原创文章,作者:guanweilu,如若转载,请注明出处:https://guanweilu.cn/article/706.html

(0)
上一篇 2小时前
下一篇 2小时前

相关推荐