XLM-R(XLM-RoBERTa)大规模无监督跨语言表示学习:模型架构、基准评测与 fairseq 实战指南
【免费下载链接】unilmLarge-scale Self-supervised Pre-training Across Tasks, Languages, and Modalities项目地址: https://gitcode.com/GitHub_Trending/un/unilm
导读
本文基于 infoxlm/fairseq/examples/xlmr/README.md 展开,系统梳理 XLM-R(XLM-RoBERTa)这一大规模跨语言句子编码器的核心内容:从 2.5T 语料、100 种语言的预训练背景,到 base/large 两档模型的配置与加载,再到 torch.hub 一键调用、SentencePiece 编码、多层特征提取等完整实战流程。同时结合本仓库 fairseq 源码(model.py、hub_interface.py),深入解析XLMRModel的实现原理与各 API 的底层调用链。读完本文,你将掌握 XLM-R 在 fairseq 中的完整加载、编码、特征提取与下游微调方法。
背景:从 RoBERTa 到跨语言的 XLM-R
XLM-R(XLM-RoBERTa)是 fairseq 提供的规模化跨语言句子编码器。与单语 RoBERTa 不同,XLM-R 在2.5T(2.5 万亿 token)规模的多语言数据上进行无监督预训练,数据覆盖100 种语言,语料从 Common Crawl 中过滤得到。这种"大规模 + 多语言"的无监督训练策略,使其在多个跨语言基准上取得当时领先的结果——这也是"Unsupervised Cross-lingual Representation Learning at Scale"(大规模无监督跨语言表示学习)这一名称的由来。
从本仓库的代码结构看,XLM-R 是 fairseq 中 RoBERTa 体系的直接延伸。model.py 中定义:
@register_model('xlmr') class XLMRModel(RobertaModel): @classmethod def hub_models(cls): return { 'xlmr.base.v0': 'http://dl.fbaipublicfiles.com/fairseq/models/xlmr.base.v0.tar.gz', 'xlmr.large.v0': 'http://dl.fbaipublicfiles.com/fairseq/models/xlmr.large.v0.tar.gz', }即XLMRModel直接继承RobertaModel,核心差异在于:注册名不同、hub 模型映射不同、from_pretrained默认使用bpe='sentencepiece'(而 RoBERTa 默认是 GPT-2 BPE)。这决定了 XLM-R 在分词层面依赖 SentencePiece 模型(SPM)来处理上百种语言的共享词表。
预训练模型一览
原文档给出了两档官方预训练权重,配置与规模如下:
| Model | 描述 | 参数量 | 词表大小 | 权重包 |
|---|---|---|---|---|
xlmr.base.v0 | 采用 BERT-base 架构的 XLM-R | 250M | 250k | xlmr.base.v0.tar.gz |
xlmr.large.v0 | 采用 BERT-large 架构的 XLM-R | 560M | 250k | xlmr.large.v0.tar.gz |
两点说明:
- 两档模型的词表大小均为250k(25 万),这是支撑 100 种语言共享表示的关键设计;原文档提示这两个 v0 权重发布时仍在训练中,后续会更新权重,论文报告的结果基于上述 checkpoint 得出。
- 架构细节可以从源码中的
register_model_architecture定义精确还原(model.py):
| 架构 | encoder_layers | encoder_embed_dim | encoder_ffn_embed_dim | attention_heads |
|---|---|---|---|---|
roberta_base | 12 | 768 | 3072 | 12 |
roberta_large | 24 | 1024 | 4096 | 16 |
这印证了"BERT-base / BERT-large 架构"的说法:base 对应 12 层 Transformer 编码器、隐层 768、FFN 3072、12 个注意力头;large 对应 24 层、隐层 1024、FFN 4096、16 个注意力头。同时base_architecture中默认activation_fn='gelu'、pooler_activation_fn='tanh'、dropout=0.1、attention_dropout=0.1,均为 RoBERTa 体系的经典配置。
跨语言基准评测结果
原文档给出了 XLM-R large 在两大经典跨语言基准上的表现。
XNLI(Conneau et al., 2018):跨语言自然语言推断
XNLI 评测表(15 种语言 + 平均)中,xlmr.large.v0采用TRANSLATE-TRAIN-ALL策略(用全部语言训练),与roberta.large.mnli的TRANSLATE-TEST策略对比:
| Model | avg | en | fr | es | de | el | bg | ru | tr | ar | vi | th | zh | hi | sw | ur |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
roberta.large.mnli(TRANSLATE-TEST) | 77.8 | 91.3 | 82.9 | 84.3 | 81.2 | 81.7 | 83.1 | 78.3 | 76.8 | 76.6 | 74.2 | 74.1 | 77.5 | 70.9 | 66.7 | 66.8 |
xlmr.large.v0(TRANSLATE-TRAIN-ALL) | 82.4 | 88.7 | 85.2 | 85.6 | 84.6 | 83.6 | 85.5 | 82.4 | 81.6 | 80.9 | 83.4 | 80.9 | 83.3 | 79.8 | 75.9 | 74.3 |
可以看到,XLM-R 在平均分上领先单语 RoBERTa 4.6 个点,且在低资源语言(如斯瓦希里语 sw、乌尔都语 ur)上的优势更为明显——这正是大规模多语言预训练价值的直接体现。
MLQA(Lewis et al., 2018):多语言问答
MLQA 使用 F1/EM(精确匹配)双指标,评测 7 种语言:
| Model | avg | en | es | de | ar | hi | vi | zh |
|---|---|---|---|---|---|---|---|---|
BERT-large | - | 80.2/67.4 | - | - | - | - | - | - |
mBERT | 57.7/41.6 | 77.7/65.2 | 64.3/46.6 | 57.9/44.3 | 45.7/29.8 | 43.8/29.7 | 57.1/38.6 | 57.5/37.3 |
xlmr.large.v0 | 70.0/52.2 | 80.1/67.7 | 73.2/55.1 | 68.3/53.7 | 62.8/43.7 | 68.3/51.0 | 70.5/50.1 | 67.1/44.4 |
XLM-R 在平均 F1/EM(70.0/52.2)上显著超越多语言 BERT(mBERT)的 57.7/41.6,验证了更大规模语料与更大词表对跨语言迁移能力的提升。
加载 XLM-R 模型:两种方式
原文档给出了两种加载路径,适用于不同的 PyTorch 版本与使用场景。
方式一:从 torch.hub 加载(PyTorch >= 1.1)
import torch xlmr = torch.hub.load('pytorch/fairseq', 'xlmr.large.v0') xlmr.eval() # disable dropout (or leave in train mode to finetune)xlmr.eval()用于关闭 dropout;若保留在训练模式(不调用 eval)则可直接继续微调。- 其背后正是
XLMRModel.hub_models()提供的 hub 映射表(model.py),xlmr.base.v0与xlmr.large.v0分别指向对应的权重压缩包。
方式二:手动下载权重后从本地加载(PyTorch 1.0 或自定义模型)
# 下载 xlmr.large 模型 wget https://dl.fbaipublicfiles.com/fairseq/models/xlmr.large.v0.tar.gz tar -xzvf xlmr.large.v0.tar.gzfrom fairseq.models.roberta import XLMRModel xlmr = XLMRModel.from_pretrained('/path/to/xlmr.large.v0', checkpoint_file='model.pt') xlmr.eval() # disable dropout (or leave in train mode to finetune)从源码看,XLMRModel.from_pretrained(model.py)会调用hub_utils.from_pretrained,默认bpe='sentencepiece'、load_checkpoint_heads=True,并返回一个RobertaHubInterface实例(hub_interface.py)。这个接口对象内部持有args、task、model三部分,并基于encoders.build_bpe(args)构建 BPE 编码器,同时注册一个_float_tensorbuffer 以便随时查询模型所在设备(xlmr.device)。
使用 SPM 编码器处理输入文本
加载模型后,第一步是把原始文本转成 token 序列。encode方法内部(hub_interface.py)会执行 SentencePiece 分词、拼装特殊符号,再通过task.source_dictionary.encode_line映射为整数索引:
- 每个序列以句首符号
<s>开头,以句尾符号</s>结尾,格式为<s> ... </s>; - 多句输入(句子对)时,用额外的
</s>作为分隔符,即<s> d e f </s> </s> 1 2 3 </s>。
原文档给出的多语言编码示例(含断言验证):
en_tokens = xlmr.encode('Hello world!') assert en_tokens.tolist() == [0, 35378, 8999, 38, 2] xlmr.decode(en_tokens) # 'Hello world!' zh_tokens = xlmr.encode('你好,世界') assert zh_tokens.tolist() == [0, 6, 124084, 4, 3221, 2] xlmr.decode(zh_tokens) # '你好,世界' hi_tokens = xlmr.encode('नमस्ते दुनिया') assert hi_tokens.tolist() == [0, 68700, 97883, 29405, 2] xlmr.decode(hi_tokens) # 'नमस्ते दुनिया' ar_tokens = xlmr.encode('مرحبا بالعالم') assert ar_tokens.tolist() == [0, 665, 193478, 258, 1705, 77796, 2] xlmr.decode(ar_tokens) # 'مرحبا بالعالم' fr_tokens = xlmr.encode('Bonjour le monde') assert fr_tokens.tolist() == [0, 84602, 95, 11146, 2] xlmr.decode(fr_tokens) # 'Bonjour le monde'几个值得注意的细节:
- 英文、法语等使用拉丁字母的语言,SPM 将单词切为子词(如
'Hello' -> 35378、'world' -> 8999),标点独立成 token; - 中文整句
'你好,世界'被切为[6, 124084, 4, 3221],其中 6 与 4 对应中文标点类 token,说明 XLM-R 的词表对中文按子词/字符粒度覆盖; - 印地语(天城文)、阿拉伯语(阿拉伯文)同样得到有效的 token 化,体现 250k 共享词表对多文字系统的支持;
decode是encode的逆过程(hub_interface.py):先去除<s>,再根据连续两个</s>判断文档边界做切分,逐段反解码;单句返回字符串,多句返回列表。
从 XLM-R 提取特征
extract_features是 XLM-R 用于下游任务的核心 API。原文档示例:
# 提取最后一层特征 last_layer_features = xlmr.extract_features(zh_tokens) assert last_layer_features.size() == torch.Size([1, 6, 1024]) # 提取所有层特征(layer 0 为 embedding 层) all_layers = xlmr.extract_features(zh_tokens, return_all_hiddens=True) assert len(all_layers) == 25 assert torch.all(all_layers[-1] == last_layer_features)特征形状的深层含义:
- 中文输入
'你好,世界'编码后为 6 个 token,所以特征张量为[1, 6, 1024]:1为 batch 维,6为序列长度(含<s>与</s>),1024是 large 模型的隐层维度; return_all_hiddens=True时返回25 层特征,即 1 层 embedding(layer 0)+ 24 层 Transformer 编码器,与 large 架构的encoder_layers=24完全对应;all_layers[-1]与last_layer_features相等,验证了"最后一层特征 = 不返回中间状态时的默认输出"这一行为。
从源码看(hub_interface.py),extract_features会:
- 将一维 token 序列升维为
(1, seq_len); - 校验序列长度不超过
model.max_positions()(即args.max_positions); - 以
features_only=True调用模型前向,跳过 LM 头,只取编码器输出; - 若
return_all_hiddens=True,将内部状态从T x B x C转置为B x T x C后逐层返回。
对应的编码器前向逻辑在RobertaEncoder.forward(model.py):features_only=False时会把特征送入RobertaLMHead做词表投影得到 MLM logits;features_only=True时直接返回(batch, src_len, embed_dim)的隐藏表示。
深入源码:XLM-R 的编码器与初始化
RobertaEncoder(model.py)是 XLM-R 的骨干实现,内部使用 fairseq 的TransformerSentenceEncoder,并采用 BERT 风格的关键设置:
num_segments=0:不使用 segment 嵌入(RoBERTa 体系的特征之一);encoder_normalize_before=True:在子层前做 LayerNorm(pre-norm);apply_bert_init=True:应用 BERT 式随机初始化;- LM 头的权重与
embed_tokens词嵌入共享参数(weight=self.sentence_encoder.embed_tokens.weight)。
RobertaModel.__init__中还有一处重要细节:self.apply(init_bert_params)(model.py),即整个模型遵循 BERT 的随机初始化方案,这是 RoBERTa/XLM-R 与原始 Transformer 初始化习惯的差异点。
此外,模型还支持 LayerDrop 与层剪枝:add_args中定义了--encoder-layerdrop(默认 0)和--encoder-layers-to-keep;当传入--encoder-layers-to-keep时,RobertaEncoder会把encoder_layers改为保留的层数,并将同一列表赋给decoder_layers_to_keep,实现"按需裁剪层数"的灵活部署(model.py)。
进阶用法:分类头与掩码填空
除了特征提取,RobertaHubInterface还提供了下游微调与推理的现成接口,可与原文档的"训练模式微调"提示配合使用。
注册分类头并预测
xlmr.register_classification_head('sentence_classification', num_classes=2) logits = xlmr.predict('sentence_classification', tokens, return_logits=True)register_classification_head(hub_interface.py)最终调用RobertaModel.register_classification_head(model.py),生成一个RobertaClassificationHead:其前向(model.py)取序列首 token<s>(等价于 BERT 的[CLS])的特征,经过dense -> activation(tanh) -> dropout -> out_proj输出各类别 logits。predict默认返回log_softmax概率,return_logits=True时返回原始 logits。
掩码语言模型填空
xlmr.fill_mask('He is a <mask> guy', topk=5)fill_mask(hub_interface.py)实现掩码词预测:将输入按<mask>切分后编码,定位mask_idx位置,以features_only=False前向获得词表 logits,取softmax后返回 top-k 的补全结果(每个结果含补全文本、概率值与预测 token),可直接用于零样本的完形填空评测。
生态衔接:XLM-R 与 InfoXLM
XLM-R 在本仓库中还有一层特殊身份:它是 InfoXLM 系列模型的基础。根据 infoxlm/README.md 的说明,InfoXLM、XLM-Align 等模型与 XLM-R使用完全相同的词表、分词器和架构,因此微调时只需把模型名从xlm-roberta-base换成对应模型即可复用全部 XLM-R 的微调代码。同时,InfoXLM 的数据预处理也直接复用 XLM-R 的dict.txt(即 XLM-R 的 250k 词表文件),这从侧面说明本 README 讲解的 XLM-R 是整个跨语言预训练技术栈的地基。
引用
若在研究中使用了 XLM-R,请按以下 BibTeX 引用(来自原文档):
@article{, title = {Unsupervised Cross-lingual Representation Learning at Scale}, author = {Alexis Conneau and Kartikay Khandelwal and Naman Goyal and Vishrav Chaudhary and Guillaume Wenzek and Francisco Guzm\'an and Edouard Grave and Myle Ott and Luke Zettlemoyer and Veselin Stoyanov }, journal={}, year = {2019}, }小结
- 模型与数据:XLM-R 在 2.5T 语料、100 种语言上无监督预训练,提供 base(250M)/ large(560M)两档权重,共享 250k 词表;
- 基准表现:在 XNLI(82.4 平均分,TRANSLATE-TRAIN-ALL)与 MLQA(70.0/52.2 平均 F1/EM)上均领先当时基线;
- 快速上手:
torch.hub.load('pytorch/fairseq', 'xlmr.large.v0')或XLMRModel.from_pretrained(...)两种方式均可加载,配合encode/decode/extract_features完成编码与特征提取; - 实现原理:
XLMRModel继承RobertaModel,编码器为TransformerSentenceEncoder的 BERT 风格配置,SPM 分词 + 共享词表是支撑百语言的关键,相关实现可在 model.py 与 hub_interface.py 中进一步研读。
【免费下载链接】unilmLarge-scale Self-supervised Pre-training Across Tasks, Languages, and Modalities项目地址: https://gitcode.com/GitHub_Trending/un/unilm
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考