☰
跨语言预训练模型在低资源机器翻译中的适配优化指南
2026/10/20 3:15:18 网站建设 项目流程

1. 项目背景:跨语言预训练模型怎么就成了机器翻译的"半成品"

做机器翻译的人,这两年应该都有同一种感觉:技术栈变化太快了。早几年我们在中英、中德这类高资源语言对上,用的还是标准的Transformer加各种trick,比如反向翻译、噪声增强、模型集成,拼尽全力把BLEU往上蹭。后来跨语言预训练模型一出来,像mBERT、XLM-R这类,大家发现一个很有意思的现象:你拿它们去做句子表征、做跨语言迁移、做零样本分类,效果都很惊艳,但直接用它们来做机器翻译,反而经常打不过自己从零训练的Transformer基线。

这个现象当时困扰了我们团队很久。某公司内部有个模拟项目X,要做的是十几个低资源语言对之间的互译,人工标注数据少得可怜,传统统计机器翻译和标准神经机器翻译都试了一圈,效果只能说勉强能用。后来我们决定换路线:拿跨语言预训练模型当底座,围绕机器翻译这个任务做针对性优化,而不是直接拿现成模型去微调完事。

这篇文章要讲的,就是这个优化过程踩过的坑、试过的方案、最后沉淀下来的实操经验。适合正在做低资源机器翻译、或者想把手上的跨语言预训练模型真正用起来的同学参考。需要说明的是,文中的参数配置和方案取舍,是我们基于常见实践并结合自身场景调整后的结果,不一定通吃所有任务,但思路是可以复用的。

先说结论:跨语言预训练模型在机器翻译里表现不佳,问题通常不在模型本身,而在"适配"环节。这个词表、预训练目标、训练语料配比、解码端的初始化方式,每一个环节都和标准的Encoder-Decoder翻译模型不一样。把它们理顺了,哪怕数据量不多,也能获得肉眼可见的提升。

2. 核心问题拆解:为什么直接微调总是差一口气

2.1 固定词表带来的覆盖盲区

跨语言预训练模型通常使用SentencePiece在单语语料上训练一个共享词表,mBERT的词汇量大约12万左右,XLM-R是25万。这个规模对分类、序列标注这类任务是够用的,但对机器翻译来说远远不够。

原因很简单:机器翻译的词表不仅承载着输入端的理解,还要支撑输出端的生成。翻译任务里有很多低频词、专有名词、拼写变体,它们在通用语料里出现次数不多,在预训练词表里可能压根就没有。一开始我们直接用mBERT的原始词表跑中英翻译,结果大量人名、地名被拆成碎片,翻译出来就成了音译乱码。这个词表问题不解决,后面做什么都是事倍功半。

2.2 语言模型目标和翻译目标的不匹配

跨语言预训练模型的核心训练目标是MLM(掩码语言建模),也就是预测被遮住的token。这个目标让模型学会了"理解"语言,但没学会"生成"另一种语言。翻译任务需要的条件生成能力——给定源语言句子,逐token生成目标语言句子——这个能力在预训练阶段完全没有被激活。

直接拿预训练模型微调,相当于让一个精通多门语言的读者突然去当同声传译,他听得懂,但嘴跟不上。体现在loss曲线上就是前期降得很快,到某个点之后就开始震荡,BLEU卡在一个不上不下的位置,怎么调学习率都突破不了。

2.3 解码器初始化方式不够讲究

用跨语言预训练模型做翻译,常见的做法是只取Encoder部分,Decoder随机初始化后和Encoder拼起来训练。问题就在这个随机初始化的Decoder上:Encoder端的参数还在预训练状态下,Decoder端是从零开始,两边初始状态差距太大,训练早期梯度震荡特别剧烈。

我们观察过一个有意思的现象:在没有做额外处理的实验组里,前三到五个epoch的loss下降得非常快,但Encoder端的参数几乎没怎么动,全在重构Decoder的随机权重。等Decoder稍微像样了,Encoder才慢悠悠开始更新,训练效率很低。

3. 优化方案设计:四步走解决"看不懂、说不来、对不齐"的毛病

3.1 词表重训:让输入输出都覆盖到位

方案选型:我们测试了两种路线,一种是在原词表基础上做增量扩展,保留预训练阶段学到的subword切分习惯,只补充缺失的token;另一种是彻底用翻译语料重新训练一个词表。实验下来,增量扩展的稳定性更好,因为完全重训词表意味着Embedding矩阵要从头学,预训练模型的优势损失了一大半。

具体操作上,我们用SentencePiece在源语言和目标语言的混合语料上训练一个扩展词表,设定vocab_size为目标范围,比如原来XLM-R是25万,我们扩展到32万。多出来的部分主要是目标语言里特有字符、常见专名片段、以及一些源语言的高频词。然后做Embedding映射:原词表中已有的token直接拷贝预训练权重里的向量,新token用对应位置相近token的平均值做初始化,构造好新的Embedding矩阵后,把模型里所有涉及词表的层都替换掉。

这里有个细节很关键:词表扩展后,预训练模型输出层的权重(通常和输入Embedding是共享的)也要做同样的扩展,否则forward的时候维度对不上。我们第一次跑就栽在这里,报错信息还特别隐晦,查了半天才发现是输出层忘改了。

3.2 双语语料继续预训练

扩展完词表只是第一步,新加入的那些token在预训练模型里是没有对应表征的,得让模型重新"见见"它们。我们做了一轮双语语料上的继续预训练,用MLM目标在混合语料上训练,但相比标准MLM做了两个改动。

第一个改动:训练时按"翻译方向"组织batch。比如中英翻译,一个batch里同时放中文句子和英文句子,这样模型在MLM训练中会经常看到"同一个语义在不同语言中的不同写法",有助于强化跨语言对齐。第二个改动:适当调高mask比例。标准MLM一般是15%,我们在继续预训练阶段设到20%,因为扩展词表里大量新token平时出现频率低,不多mask几次,它们很难在Embedding矩阵里站稳位置。

继续预训练的数据量不用太大。我们这边每个语言对大概用了几千万句的高质量平行语料和单语语料混合体,训练了约10万步,用的还是XLM-R原来的优化器参数,学习率设在1e-4左右。这个阶段不能训太久,否则会破坏原有的多语言对齐能力,后面微调时就不好收敛了。

3.3 词表映射后的跨语言嵌入对齐

继续预训练解决的是新token的表征问题,但还有一个更隐蔽的问题:源语言和目标语言在预训练模型的嵌入空间里,可能并没有对齐到理想状态。虽然XLM-R这类模型本身有跨语言对齐能力,但这种对齐是"软"的,翻译任务需要的是"硬"一点的对齐。

我们做了一步轻量级的嵌入对齐操作。具体做法:从双语平行语料里按对齐工具(如某开源词对齐工具)抽出一批高度可靠的词对,然后在这批词对的最小化约束下,对Embedding矩阵做一次线性变换微调。这个操作不需要跑完整的forward,直接在嵌入层上做优化,几分钟就能完成,但后续微调的收敛速度会有明显提升。

这个技巧是从几个老开源项目里看到的,算是一种轻量级但有效的"预对齐"操作。它在数据量很少的低资源场景下帮助更大,因为模型微调时没有足够的信号自己去对齐语言对。

3.4 解码器初始化与微调策略

Decoder端我们放弃了完全随机初始化,改用一个替代方案:在翻译语料上先做一小段标准的Seq2Seq预训练,只训练Decoder和交叉注意力部分,Encoder冻结不动,等Decoder的loss降到一个合理区间后,再解冻Encoder做联合微调。

这么设计的原因前面提过:完全随机初始化的Decoder和预训练Encoder是"断层"的,早期训练信号全耗在重建Decoder上了。先冻结Encoder只训Decoder,相当于先让"嘴"能动了,再去调整"理解力",整个训练过程会平稳很多。

联合微调阶段的超参数,我们最后选定的组合是:batch size 256,学习率5e-5,采用warmup加余弦退火,warmup步数设为总步数的10%。label smoothing设0.1,因为翻译任务里存在大量合理的翻译变体,平滑一点能防止模型过度自信。另外把梯度裁剪设到1.0,这个值在后续稳定性测试中表现最优。

4. 实操记录:从数据准备到训练收敛

4.1 数据清洗与语料配比

训练语料以平行句对为主,我们大约收集了中英3000万句对、中德2000万句对,低资源语言对只有几百万句对。数据清洗按翻译项目的标准流程来:去重、去长句(超过100个token的句子直接砍掉,因为这类样本训练效率低)、基于语言识别做噪声过滤,然后用一个快速的自训练双语评分模型做一遍句子级筛选,把明显不对齐的句对打掉。

另外我们做了一点反向翻译(back-translation)增强,把单语目标语言句子用早期的弱模型翻译回源语言,构造出大量伪平行句对。这一步对低资源语言对的提升尤其明显,但要注意控制伪平行数据的比例,我们实验下来30%到40%是甜点区,太高了模型会被噪声带偏。

4.2 训练流程与关键监控指标

整个训练分为三个阶段。第一阶段是上面说的继续预训练,大约10万步;第二阶段是解码器预训练,大概5万步,这一阶段我们特意把学习率调大了一点,用到3e-4,让随机初始化的Decoder先快速成型;第三阶段是联合微调,约20万步。

训练过程中重点盯着三个指标:验证集Loss、验证集BLEU、以及源语言和目标语言表征之间的相似度。第三个指标是我们内部加的,每5000步抽一批双语句对,取Encoder最后一层的平均表征算一下相似度。这个值在训练早期的上升速度和最终BLEU有很强的正相关关系。如果训练了很长时间这个值都提不上去,大概率是嵌入对齐环节出了问题。

4.3 推理阶段也需要配套改动

训练完的模型在推理时也做了两处调整。第一处是beam search的beam size和length penalty。我们在几个验证集上扫了一遍,发现beam size 4、length penalty 0.6的组合普遍比默认参数高0.5到1个BLEU。第二处是加了覆盖惩罚机制,防止模型在长句子上重复翻译同一个片段。覆盖惩罚系数设在0.3左右,太高了会让翻译变短,太低又控制不住重复问题。

另一个值得提的推理细节:因为扩展词表里有很多低频token,beam search在解码后期容易陷入低频token的局部最优,导致输出里出现奇怪的碎片。我们加了一个简单的后处理规则:连续出现两个以上的unk token时,强制回退到上一步的最佳候选。这个小改动看起来不优雅,但在低资源语言上救回了不少翻译质量。

5. 对比实验与效果分析

5.1 三组关键对比实验

为了验证每一步优化的有效性,我们设计了三组消融实验。第一组是基线,直接用XLM-R的Encoder加随机初始化Decoder做微调,词表不变;第二组只做词表扩展,其他流程同基线;第三组是完整方案,依次做完词表扩展、继续预训练、嵌入对齐、解码器预训练、联合微调。

结果差异非常明显。在中英方向上,基线BLEU是32.1,第二组是33.4,完整方案是35.2。低资源语言对上的差距更大,基线的BLEU只有18.6,甚至比不过我们之前从零训练的标准Transformer基线,但完整方案能做到23.8,直接把原来那个模型甩开了。

这说明一个问题:跨语言预训练模型不是不能用在机器翻译上,而是需要一套和任务匹配的改造流程。每个环节单独看提升幅度都不大,但叠加起来就是质的差别。

5.2 参数敏感度测试

我们还顺带测了几个关键参数的敏感性。一个是继续预训练的步数,从5万步拉到50万步,BLEU先升后降,拐点大概在10万步左右,印证了"训太久会遗忘原有能力"的判断。另一个是伪平行句对的比例,0%、20%、35%、50%四档对比,35%左右最优,50%开始出现明显的噪声引入问题。

解码器预训练这一步,我们也试过完全不做的对照组。对比发现,不做这一步的话,联合微调要多跑大约40%的步数才能达到相同的BLEU水平。在训练预算受限的场景下,这步的性价比是最高的。

5.3 与轻量级对照模型的比较

还有一个大家可能关心的点:这套优化流程造出来的模型,和直接上更大规模的翻译专用模型比,到底有没有优势?我们拿了一个参数量接近的翻译专用预训练模型做了对照,在部分高资源语言对上确实是我们略低,但在低资源语言对上我们领先了将近两个BLEU。原因也很好理解:翻译专用模型的预训练语料偏重中英德法这类高资源语言,低资源语言覆盖并不好;而跨语言预训练模型本身就是在几百种语言上训出来的,我们在此基础上做的优化,相当于既保留了多语言覆盖,又补上了翻译能力。

6. 常见问题与排查实录

6.1 词表扩展后OOV不降反升

这是我们遇到的第一个坑。扩展词表不是简单地把新token加进去就行,如果SentencePiece的训练数据里源语言和目标语言占比配得不合理,会出现一个奇怪的现象:扩展后总词汇量变大了,但某些语言的token覆盖率反而降了。

排查后发现原因是混合语料里高资源语言占比太高,SentencePiece的训练会被高资源语言主导,低资源语言的字符片段被拆得过碎。解决办法是均衡语料比例,让每种语言在训练数据里占大致相同的比例,甚至低资源语言可以稍微过采样。调整之后再训一次词表,低资源语言的OOV率直接降了6个百分点。

6.2 继续预训练阶段的灾难性遗忘

前面提到过继续预训练步数太长会破坏原有表征。实际日志里也能看到这个现象:验证集上的MLM loss在下降,但下游微调时的初始BLEU反而变低了。这个问题的早期信号很隐蔽,我们后面加了一个监控指标:在继续预训练过程中,每隔一段时间跑一次微调基线,看初始BLEU的变化趋势。如果发现初始BLEU开始下降,就赶紧停掉继续预训练,或者把学习率降下来再训一小段。

6.3 训练速度太慢和显存爆炸

跨语言预训练模型的Encoder部分本来就比普通Transformer大,扩展词表之后Embedding矩阵也跟着变大,显存就成了麻烦。我们这边的解决办法是:把词表扩展后的Embedding层拆出来单独存成映射,不做成常规的nn.Embedding层,而是在数据加载阶段先把源语言token映射到扩展ID空间,Embedding只加载需要用到的行向量。

这样做的理由是:训练语料里实际出现的token只是扩展词表的一个子集,没必要把所有Embedding都塞进显存里。我们实测显存占用大概降了30%到40%,训练速度也快了不少。推理阶段更明显,因为beam search要频繁访问输出层的概率分布,精简后的映射能让前向计算快一大截。

6.4 尺寸导致的部署问题

优化后的模型虽然参数总量和原来差不多,但因为词表变大,整体体积会膨胀不少。我们部署到线上服务时遇到了延迟超标的问题,后来用蒸馏的方式把模型压缩了一版:用完整优化模型的输出作为soft label,训练一个词表较小(保留原有25万)、层数减半的学生模型。蒸馏后BLEU掉了大约1.2个点,但推理速度提升了近三倍,线上场景下这个trade-off是可以接受的。

7. 写在最后的几点体会

这套优化流程前前后后花了我们一个多月的时间,中间踩坑无数。最深的体会是:跨语言预训练模型是一个很好的底座,但"借用"它来做机器翻译时,一定要想清楚哪些部分要保留、哪些部分必须改造。词表是入口,嵌入对齐是桥梁,解码器初始化是引擎,三个阶段各管一段,缺了哪个都会在后面的训练里找回来。

我个人在实际项目里还有一个习惯:每改动一个环节,就先用一个小数据集做快速验证,而不是直接上全量训练。词表扩展、解码器预训练这类改动,跑一次小实验的成本很低,但能提前暴露80%以上的问题。如果未来你也要做类似的项目,建议也按这个节奏来,别嫌麻烦。

再补充一点,这套思路不局限于某个特定模型,mBERT、XLM-R以及其他跨语言预训练模型基本都能套用,只是需要根据具体模型调整一下词表大小和继续预训练的步数。真正动手做的时候,大概率还会遇到别的问题,但核心方法论在,排查方向就不会跑偏。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询