xTune 实战指南:基于一致性正则的跨语言微调(Consistency Regularization for Cross-Lingual Fine-Tuning)
【免费下载链接】unilmLarge-scale Self-supervised Pre-training Across Tasks, Languages, and Modalities项目地址: https://gitcode.com/GitHub_Trending/un/unilm
xTune 是 unilm 仓库中实现 ACL 2021 论文《Consistency Regularization for Cross-Lingual Fine-Tuning》的官方代码,其核心思想是用两阶段训练加一致性正则(consistency regularization),让 XLM-RoBERTa 在只用英语数据(或少量翻译数据)微调后,仍能泛化到数十种目标语言。读完本文,你将能够完整搭建 xTune 的训练环境、下载并预处理 XTREME 基准数据,使用scripts/train.sh一键跑通分类、序列标注、问答两类任务的跨语言微调,并理解源码中 R1(样本一致性)与 R2(模型一致性)两项正则损失的实现细节。
一、环境与安装
xTune 依赖一个定制版的 transformers(仓库内 xtune/src/transformers 是基于 HuggingFace transformers 2.5.1 的分支,内嵌了XLMRobertaForSequenceClassificationStable等支持一致性损失的模型类),因此官方推荐使用官方 Docker 镜像运行:
# 官方 Docker 镜像 dancingsoul/pytorch:xTune若手动安装,需在xtune/目录下执行(见 xtune/setup.py,其中固定了sentencepiece==0.1.91、seqeval==0.0.12、networkx==1.11等依赖版本):
cd xtune pip install --user .注意:训练脚本默认开启--fp16 --fp16_opt_level O2,依赖 NVIDIA Apex(见 xtune/src/run_cls.py 中对 apex 的 import),并建议在 V100-32GB 级别的 GPU 上运行;若出现 OOM,可减少per_gpu_train_batch_size同时增大gradient_accumulation_steps,或多卡训练。
二、数据与模型准备
2.1 XTREME 数据集
官方微调支持 7 个 XTREME 任务:xnli、pawsx(分类)、panx(NER)、udpos(POS 标注)、mlqa、tydiqa、xquad(问答)。准备步骤(依据 xtune/README.md):
- 在项目根目录创建下载目录:
mkdir -p download- panx 数据集需手动下载:从 XTREME 官方渠道下载
panx_dataset(下载文件名为AmazonPhotos.zip),放入download/目录。xtune/scripts/download_data.sh 中的download_panx函数检测到AmazonPhotos.zip后会解压其中的 40 个语言包(ar.tar.gz…hu.tar.gz),把每个语言的train/dev/test重命名为lg-train等,再调用utils_preprocess.py统一转成 TSV 格式;否则该函数只打印提示并跳过。 - 其余数据集(XNLI、PAWS-X、UD-POS、SQuAD、XQuAD、MLQA、TyDiQA-GoldP、 Tatoeba/BUCC 平行语料)通过一条命令下载并预处理:
bash scripts/download_data.sh从 download_data.sh 的实现可以看到,每个数据集下载后都会执行python utils_preprocess.py --data_dir ... --output_dir ... --task <task>统一格式化为脚本可读取的 TSV;udpos还会额外用 conllu_to_conll.py 把 conllu 转成 conll(保留 fused form,即词级标注,这是 panx/udpos 这类 token 级任务必需的)。
官方 README 特别提醒两点:
- 为了便于评估,仓库保留了测试集标签;而 XTREME 官方仓库在预处理时会删除测试标签并打乱测试句顺序(用于跨语言检索),因此若使用 XTREME 官方仓库的数据,需要在其
utils_process.py中把csv.writer(fout, delimiter='\t')替换为csv.writer(fout, delimiter='\t', quoting=csv.QUOTE_NONE, quotechar='')。 - 训练
panx/udpos前,train.sh会自动调用 preprocess_panx.sh、preprocess_udpos.sh 做二次预处理(按最大长度切分、生成labels.txt),无需手动干预(见 xtune/scripts/train.sh#L29-L33)。
2.2 平行句翻译数据
XTREME 官方提供 SQuAD v1.1(仅 train/dev)、MLQA、PAWS-X、TyDiQA-GoldP、XNLI、XQuAD 的平行翻译,下载后将xtreme_translations文件夹整体移入download/目录即可。
panx 与 udpos 的目标语言翻译官方未提供,xTune 用 Google 翻译补齐了这部分(论文方提供了处理好的版本供下载),并与xtreme_translations合并存放。以 XNLI 为例,脚本从$DATA_DIR/xtreme_translations/XNLI/读取翻译文件(见 train_xnli.sh#L27);panx 则使用xtreme_translations/translate_train.panx.txt(见 train_panx.sh#L47)。
2.3 双语词典(code-switching 用)
cross-lingual-transfer设置下的数据增广使用词级 code-switching,需要从 MUSE 仓库获得英-目标语言平行词典,按download/dicts/en-<lang>.txt的组织方式放入下载目录。源码在 NoisedDataGenerator 初始化 中逐语言读取en-{lang}.txt,每行以src\ttgt解析,构建成lang2dict映射;缺失词典的语言会被自动剔除并打日志。
2.4 预训练模型
仅支持 XLM-RoBERTa(xlm-roberta-base/xlm-roberta-large),采用 HuggingFace 格式,一键下载:
bash scripts/download_model.shdownload_model.sh 会从 HuggingFace 拉取两个模型目录下的pytorch_model.bin、config.json、sentencepiece.bpe.model、tokenizer.json四个文件到download/xlm-roberta-{base,large}/。
三、两阶段微调:train.sh完全参数解析
xTune 的完整调用入口只有两个层级:
bash ./scripts/train.sh [setting] [dataset] [model] [stage] [gpu] [data_dir] [output_dir]train.sh本身只是参数转发器(xtune/scripts/train.sh),7 个位置参数均有默认值,另支持第 8 个可选参数SEED(默认 1):
| 位置参数 | 说明 | 默认值 / 可选值 | |
|---|---|---|---|
[setting] | 数据设置 | translate-train-all:除英语外使用官方平行翻译参与训练;cross-lingual-transfer:只用英语训练,零样本跨语言迁移 | 默认cross-lingual-transfer |
[dataset] | XTREME 任务名 | xnli、panx、pawsx、udpos、mlqa、tydiqa、xquad;默认xnli | |
[model] | 预训练模型 | xlm-roberta-base、xlm-roberta-large | |
[stage] | 训练阶段 | 1或2;默认1 | |
[gpu] | 设置CUDA_VISIBLE_DEVICES | 默认0 | |
[data_dir] | 训练数据目录 | 默认$REPO/download/ | |
[output_dir] | 微调输出目录 | 默认$REPO/outputs/ |
脚本随后分发到scripts/$SETTING/train_${TASK}.sh(共 7 个任务 × 2 个设置 = 14 个任务脚本)。以 XNLI 分类为例,两个设置下的默认超参(translate-train-all/train_xnli.sh 与 cross-lingual-transfer/train_xnli.sh):
| 超参 | 取值 | 含义 |
|---|---|---|
EPOCH | 10 | 训练轮数 |
MAXL | 256 | 最大序列长度 |
LANGS | ar,bg,de,el,en,es,fr,hi,ru,sw,th,tr,ur,vi,zh | 评估语言(XNLI 的 15 种语言,含 en) |
EVALUATE_STEPS | 5000 | 每多少步在训练中途评估一次 |
BATCH_SIZE/GRAD_ACC | base: 32/1;large: 16/2 | 每卡 batch 与梯度累积 |
LR | base: 7e-6;large: 5e-6 | AdamW 学习率 |
R1_LAMBDA | 5.0 | 样本一致性损失权重 λ1 |
R2_LAMBDA | translate-train-all: 1.0;cross-lingual-transfer: 5.0 | 模型一致性损失权重 λ2 |
CSR(仅 cross-lingual-transfer) | 0.3 | code-switching 比例 |
各任务脚本按语言数量与序列长度调整超参,例如 panx 的 40 语言、MAX_LENGTH=128、EVALUATE_STEPS=1000、base 模型LR=1e-5(translate-train-all/train_panx.sh#L26-L45)。
3.1 两阶段训练的语义
- Stage 1:在英语训练集上带「样本一致性(example consistency)」微调——每条原始样本都会生成一个加噪/翻译/码切换后的变体,要求两个视角下的模型输出分布保持一致(R1 损失)。
- Stage 2:在「英语 + 增广」的训练集上继续训练(增广方式按设置而定:
translate-train-all用mt,即用官方平行翻译增广;cross-lingual-transfer用cs,即 code-switching),并额外加载 Stage 1 的最优 checkpoint 作为冻结教师模型,对增广样本施加「模型一致性(model consistency)」正则(R2 损失)。
官方建议:token 级任务(序列标注 panx/udpos、问答 mlqa/tydiqa/xquad)务必两个阶段都跑;文本分类任务在算力受限时可以只跑 Stage 1。
3.2 Stage 2 如何衔接 Stage 1
Stage 2 脚本会显式指定 Stage 1 产物,例如 XNLI translate-train-all 的 Stage 2(train_xnli.sh#L78-L116):
FIRST_STAGE_MODEL_PATH="${OUT_DIR}/xnli/xlm-roberta-base-LR7e-6-epoch10-MaxLen256-Translate-R1_LAMBDA5.0/checkpoint-best" python ./src/run_cls.py ... \ --first_stage_model_path $FIRST_STAGE_MODEL_PATH \ --enable_data_augmentation \ --augment_ratio 1.0 \ --augment_method mt \ --r2_lambda $R2_LAMBDA训练过程中,每当验证集平均指标超过历史最优,会把模型另存为checkpoint-best(见 save_checkpoint_best,分类任务以valid_avg.acc为选择标准,rel任务用 ndcg)。checkpoint-best正是 Stage 2 加载的教师模型来源,因此Stage 2 必须在 Stage 1 同一OUT_DIR下运行。
四、示例:XNLI 的两种数据设置
4.1 translate-train-all:利用各语言平行翻译
# Stage 1(必跑) bash ./scripts/train.sh translate-train-all xnli xlm-roberta-base 1 # Stage 2(可选,推荐) bash ./scripts/train.sh translate-train-all xnli xlm-roberta-base 2该设置下 Stage 1 开启--enable_translate_data --translation_path $DATA_DIR/xtreme_translations/XNLI/,即在 R1 一致性配对中直接随机替换成其他语言译文;Stage 2 再以--augment_method mt --augment_ratio 1.0把等量的翻译样本加入训练集。
4.2 cross-lingual-transfer:只用英语,零样本迁移
# Stage 1(必跑) bash ./scripts/train.sh cross-lingual-transfer xnli xlm-roberta-base 1 # Stage 2(可选,推荐) bash ./scripts/train.sh cross-lingual-transfer xnli xlm-roberta-base 2该设置下训练数据完全来自英语,增广手段是词级 code-switching:--overall_ratio 1.0 --enable_code_switch --code_switch_ratio 0.3 --dict_dir $DATA_DIR/dicts --dict_languages ar,bg,de,el,es,fr,hi,ru,sw,th,tr,ur,vi,zh(cross-lingual-transfer/train_xnli.sh#L77-L81)。Stage 2 中增广方法切换为cs,并且 Stage 1/Stage 2 的R2_LAMBDA均为 5.0。
panx、udpos、mlqa、tydiqa、xquad、pawsx 的调用方式完全一致,只是把[dataset]换成对应任务名;token 级任务入口是 xtune/src/run_tag.py、问答任务入口是 xtune/src/run_qa.py,分类任务入口是 xtune/src/run_cls.py,参数体系相同。
五、源码级原理:R1 与 R2 一致性损失
5.1 数据侧:NoisedDataGenerator 如何构造「噪声视图」
run_cls.py 中的NoisedDataGenerator负责为每条样本生成一致性配对,支持多种扰动手段(命令行参数在 main() 中定义):
enable_translate_data/translation_path:通过get_translation_pair(run_cls.py#L499-L533)把当前句随机换成某个目标语言的官方平行译文;tgt2src_dict保证从目标语言视角也能映射回英语原文,实现「en↔tgt」双向替换。enable_code_switch/code_switch_ratio/dict_dir/dict_languages:在encode_sentence(run_cls.py#L240-L277)中逐 token 以overall_ratio × code_switch_ratio的概率把英文词替换为双语词典中的目标语言对应词,并统计实际码切换比例(训练日志会打印XX.XX% tokens have been code-switched)。enable_bpe_sampling:用 SentencePiece 的nbest_size+alpha采样替代词级扰动;enable_random_noise:在词嵌入上叠加 uniform/normal 噪声(noise_eps控制幅度);enable_word_dropout:按word_dropout_rate将 token 替换为[UNK]。enable_data_augmentation+augment_ratio+augment_method:Stage 2 专用。augment_examples(run_cls.py#L204-L215)按ceil(N × augment_ratio)复制样本并打乱,mt方法把复制件替换为译文、cs方法对复制件做码切换编码;被复制的样本被标记is_augmented=1和r1_mask=1,原始样本同样标r1_mask=1。
每条样本最终被编码为 9 元张量数据集:original_input_ids / attention_mask / token_type_ids / labels / is_augmented / noised_input_ids / noised_attention_mask / noised_token_type_ids / r1_mask(convert_examples_to_dataset)。
5.2 模型侧:总损失 = 原始 CE + 噪声 CE + R1 + R2
自定义模型XLMRobertaForSequenceClassificationStable(modeling_xlm_roberta.py#L207-L390)在一次 forward 中同时计算原始输入与噪声输入的两路 logits,总损失为:
loss = original_loss + noised_loss + r1_loss + r2_loss其中:
original_loss:由--original_loss开启,对原始输入的交叉熵(L364-L367);noised_loss:由--noised_loss开启,对噪声输入的交叉熵(默认脚本不启用,仅靠一致性约束);r1_loss(样本一致性,--enable_r1_loss+--r1_lambda):对r1_mask=1的样本,计算两路 logits 概率分布的双向 KL 散度之和再乘 λ1(L374-L383):r1_loss_f = KL(noised_logits, logits.detach()) r1_loss_b = KL(logits, noised_logits.detach()) r1_loss = (r1_loss_b + r1_loss_f) * r1_lambdar2_loss(模型一致性,Stage 2 专用):当传入first_stage_model_logits且 batch 中存在is_augmented=1的样本时,用当前模型在这些增广样本上的 logits 对Stage 1 冻结模型(torch.no_grad()下计算,见 train())的输出做 KL 散度,乘 λ2;也可通过--use_hard_labels改用教师模型的 argmax 硬标签(L322-L333)。
这个设计对应论文的两个核心正则:Stage 1 让模型对「同一句话的不同语言/噪声视角」给出一致预测;Stage 2 让模型在扩充(含翻译/码切换)数据上学习时,不偏离 Stage 1 已经建立的跨语言一致解。run_tag.py/run_qa.py对应的 Stable 模型类以同样模式在 token 级(起始/结束位置、token 对齐项)与句级上实现 R1/R2(modeling_xlm_roberta.py#L1125-L1176)。
5.3 训练循环与评估
- 优化器为 AdamW(
bias、LayerNorm.weight不衰减,train()#L594-L605),线性 warmup + 线性衰减,--warmup_steps -1时以 0 warmup 直接衰减;fp16 通过 Apexamp.initialize+opt_level O2启用。 - 训练中途评估:
--evaluate_during_training --evaluate_steps 5000触发evaluate(),对--language列表里每种语言的 valid + test 集逐语言计算 acc/F1(xtreme_compute_metrics),并聚合valid_avg/test_avg;评估结果写入evaluate_logs.txt与 TensorBoard(run_cls.py#L937-L1015)。训练日志中会逐行打印loss / original_loss / noised_loss / r1_loss / r2_loss,便于观察正则项的收敛情况(L683-L697)。 - 缓存:特征按
cached_{split}_xlmr-base-final_{maxlen}_{task}_{lang}缓存在data_dir下(load_and_cache_examples),重复运行可省去重新 tokenize 的开销。
六、复现建议与常见坑
- OOM 处理:README 给出的官方策略是降低
per_gpu_train_batch_size、提高gradient_accumulation_steps或多卡;脚本中 large 模型默认BATCH_SIZE=16, GRAD_ACC=2(XNLI)或32/1(panx),可以照此比例调整。 - 目录约定:
download/下必须同时具备xnli、pawsx、udpos、panx、mlqa、tydiqa、xquad、xtreme_translations、dicts、xlm-roberta-base|large十类目录,缺一项对应设置(尤其是cross-lingual-transfer缺dicts、translate-train-all缺xtreme_translations)都会直接失败。 - 输出目录:每次运行的
OUTPUT_DIR命名中包含 LR、epoch、MaxLen、R1_LAMBDA、增广方式等超参指纹(如...-Translate-R1_LAMBDA5.0与...-Aug1.0-MT-R2_Lambda1.0),Stage 2 会去同指纹的 Stage 1 目录下找checkpoint-best;如果 Stage 1 超参被改过,务必保证两个阶段的 LR/epoch/MaxLen 等指纹一致,否则路径对不上。 - 依赖版本:仓库内 transformers 为 2.5.1 定制版(xtune/setup.py#L78-L81),
run_cls.py顶层from transformers import ...导入的正是本目录src/transformers,请勿用新版 transformers 覆盖安装,否则XLMRobertaForSequenceClassificationStable、xtreme_*系列符号会缺失。 - 种子:
SEED为train.sh第 8 个可选参数(默认 1),会同步到 Python/NumPy/PyTorch(set_seed)。
七、引用
若使用了 xTune 的资源,请引用 ACL 2021 论文(xtune/README.md):
@inproceedings{bo2021xtune, author = {Bo Zheng, Li Dong, Shaohan Huang, Wenhui Wang, Zewen Chi, Saksham Singhal, Wanxiang Che, Ting Liu, Xia Song, Furu Wei}, booktitle = {Proceedings of ACL 2021}, title = {{Consistency Regularization for Cross-Lingual Fine-Tuning}}, year = {2021} }主要参考的仓库文件:xtune/README.md、xtune/scripts/train.sh、xtune/scripts/download_data.sh、xtune/scripts/download_model.sh、xtune/src/run_cls.py、xtune/src/transformers/modeling_xlm_roberta.py、xtune/setup.py。
【免费下载链接】unilmLarge-scale Self-supervised Pre-training Across Tasks, Languages, and Modalities项目地址: https://gitcode.com/GitHub_Trending/un/unilm
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考