模型容量不够——下一步是加层还是加宽?
模型容量不够——下一步是加层还是加宽?
衔言渡意是一个中英法三语互译的小模型。训练到第二版(15.5M 参数,192 维,6+6 层),BLEU 到 15.6 后走平,val loss 不再下降——容量到顶了。
需要扩容,但往哪个方向扩?
加层和加宽不是同一件事。层数管的是串行处理深度——嵌套从句需要逐层解开,层不够就解不动内层。维度管的是并行信息负载——同一层里能同时追踪多少实体,维度不够就记不住。两种瓶颈的表现不同,扩错方向等于浪费参数。
这篇记录我怎么区分这两种瓶颈、怎么构造诊断测试、以及最终怎么决定扩容方向。
两种瓶颈
层数管串行,维度管并行
Transformer 的每一层在做同样的事:self-attention 让 token 之间交换信息,FFN 做非线性变换,残差连接把结果叠加到上一层的输出上。层与层之间是串行的——第二层的输入是第一层的输出,第三层依赖第二层的结果。
这意味着层数决定了模型能处理多深的串行依赖。翻译里最典型的串行结构是嵌套从句:“大会请秘书长提交关于会员国落实委员会建议的措施的报告”——要先理解“委员会建议”,才能理解“落实建议的措施”,才能理解“关于措施的报告”,才能理解“请秘书长提交”。每一层嵌套都依赖内层的结果,层不够就解不动。
维度管的是另一件事:同一层里能同时追踪多少信息。“中国、法国、联合王国、俄罗斯联邦、美国和日本提出了经济制裁、军事合作、人道主义援助、外交谈判、技术转让和环境保护的提案”——这里没有嵌套,结构很简单(主语 + 谓语 + 宾语),但需要同时记住六个国家和六个议题。维度不够就开始丢东西。
失败模式不同
两种瓶颈在输出里的表现完全不同。
串行不足时,模型犯的是结构性错误。它知道句子里有哪些元素,但组装关系是错的——从句归属搞反,嵌套层级丢失,主句蒸发只剩内层从句。模型不是没看见那些词,是没能把结构关系一层层解开。
并行不足时,模型犯的是遗漏和混淆。结构没问题,主谓宾关系都对,但实体记不全——六个国家只输出四个,张冠李戴,或者同一个实体重复生成。
这个区分是诊断的基础:看输出错在哪里,就能反推是哪个轴到了瓶颈。
诊断方法
识别任务里的两个轴
面对一个序列任务,问两个问题:
“什么必须先算完才能算下一步?”——这是串行轴。翻译里是嵌套从句,代码生成里是嵌套控制流(外层循环依赖内层条件的结果),摘要里是因果链条(结论依赖推理步骤),分类里是条件嵌套(先判断 A 类,A 类里再分 A1 和 A2)。
“什么必须同时记住?”——这是并行轴。翻译里是并列实体,代码生成里是同时追踪的变量,摘要里是需要覆盖的独立主题,分类里是同时权衡的特征。
这两个轴在所有序列任务里都存在,只是具体映射不同。
构造诊断用例
两个轴各分三级难度。关键是控制变量。
测串行时,保持并行负载低——最多两个并列项,只递增嵌套深度。S1 无嵌套,S2 一层嵌套,S3 两层嵌套。
测并行时,保持结构简单——主谓宾,不带嵌套,只递增并列实体数。P1 两项,P2 四项,P3 六项。
混在一起就分不清哪个轴出了问题。
每级不能只放一句,偶然因素太大。衔言渡意用了每级 3 句,2 轴 × 3 级 × 3 句 = 18 句,六个翻译方向随机覆盖。
读失败模式
串行崩溃的特征是结构性错误——从句关系乱,主句蒸发,嵌套层级丢失。
并行崩溃的特征是遗漏和混淆——实体丢失,张冠李戴,重复生成。
如果两边都崩:把难度从高往低降,看哪边先恢复正常。先恢复的是余量更多的轴,后恢复的才是更紧的瓶颈。
实证:衔言渡意的诊断
15.5M 模型的诊断结果
15.5M 模型(192 维,6+6 层),BLEU 15.6 走平后,跑诊断测试集。
并行轴(目标语言均为中文):
P1,2 项并列,全对:
China and France submitted proposals on economic sanctions.→中国和法国提出了经济制裁的建议。
P2,4 项并列,全对:
La Chine, la France, le Royaume-Uni et la Fédération de Russie ont soumis des propositions concernant les sanctions économiques et la coopération militaire.→中国、法国、联合王国和俄罗斯联邦提出了经济制裁和军事合作的建议。
P3,6 项并列,丢实体:
China, France, the United Kingdom, the Russian Federation, the United States and Japan submitted proposals on economic sanctions, military cooperation, humanitarian assistance, diplomatic negotiations, technology transfer and environmental protection.→中国、法国、美利坚合众国和日本提出了经济制裁、军事合作、外交谈判、技术转让和环境保护的建议。
丢了“联合王国”和“俄罗斯联邦”,丢了“人道主义援助”。六个国家只记住四个,六个议题只记住五个。192 维装不下这么多并行信息。
串行轴更严重:
S1,无嵌套,过:
Le Conseil a adopté la résolution à l'unanimité.→理事会未经表决通过了决议。
结构对,“à l'unanimité”(全票通过)译成“未经表决”是词汇映射错误,不是结构问题。
S2,一层嵌套,丢外层从句:
The Committee recommends that Member States adopt measures in accordance with resolution 1325.→会员国根据第1325号决议采取措施。
“The Committee recommends that”整个主句蒸发了。模型只译出了内层从句,好像委员会推荐这件事从来没有发生过。
S3,三层嵌套,全崩:
L'Assemblée générale a prié le Secrétaire général de lui présenter un rapport sur les mesures prises par les États Membres pour donner suite aux recommandations formulées par le Comité dans le rapport soumis à sa soixantième session.→秘书长要求各会员国报告 suite委员会第六十届会议的建议。
结构散架,混入未翻译的法语词“suite”。三层嵌套对 6 层 encoder 来说太深了。
结论:双瓶颈,串行更紧急——S2 一层嵌套就崩,P3 六项才开始丢。
扩容决策
三条线索指向不同方向:
串行诊断指向加层。S2 丢了“The Committee recommends that”,encoder 解不动句级依赖,decoder 映射不出嵌套结构。6+6 不够,扩到 8+8。
并行诊断指向加宽。P3 在六项并列时丢实体,192 维的并行容量到了上限。
S1 的词汇映射错误(“à l'unanimité” → “未经表决”)指向信息密度不足。结构没问题但词义搞错,说明每个 token 分到的参数预算不够精确。token_per_param 从 5 降到 2。
三条线汇合:d_model_calculator 基于 8+8 层和 token_per_param=2 输出 384 维,6 头。最终架构:384d × 6h × 8+8L,51.7M 参数。
验证
拿 15.5M 全崩的句子重新跑。
S3,三层嵌套(15.5M 输出“秘书长要求各会员国报告 suite 委员会...”的那条),51.7M 法→中:
大会请秘书长向各会员国提出关于为执行委员会第六十届会议提交的报告提出的建议而采取的步骤的报告。
三层嵌套结构完整保留——大会请秘书长、会员国采取措施、落实委员会建议、第六十届会议报告,层层关系都在。
P3,六项并列(15.5M 丢了“联合王国”“俄罗斯联邦”“人道主义援助”的那条),51.7M 英→中:
中国、法国、英国、俄罗斯联邦、美国和日本提出了经济制裁、军事合作、人道主义援助、外交谈判、技术转让和环境保护的提案。
六国六议题全部保留,零遗漏。
8+8 层解决了嵌套结构的串行依赖,384 维解决了多实体的并行负载。
局限性
串行和并行不总是能干净分离。嵌套三层从句、每层又带并列项——两轴耦合了,诊断用例的“控制变量”原则就不好守。实际任务里这种耦合很常见,诊断结果会模糊。
诊断用例需要手工构造。你得理解任务的结构特征,知道什么算“串行复杂度递增”、什么算“并行负载递增”,然后自己写测试句。这不是能自动化的事。
这是一个可修正的起点——给你一个有依据的扩容方向,不是精确到层数的答案。实际需要多少层、多少维度,还是要训了才知道。但至少不是盲扩。
上一篇从数据反推层数和维度,给出训练的起点。这篇从训练反馈出发,诊断瓶颈方向,决定怎么扩。两篇合在一起,覆盖了从起点到迭代的路径。
起点定好了,训练撞墙后怎么判断往哪个方向扩——加层还是加宽——是另一个问题。
这个问题现在回答完了。