fairseq S2T 实战:在 MuST-C 上完成端到端语音翻译(ST)与语音识别(ASR)全流程
发布时间:2026/9/13 19:41:12 作者:尧图编辑部 阅读量:1,286
与语音识别(ASR)全流程)
fairseq S2T 实战在 MuST-C 上完成端到端语音翻译ST与语音识别ASR全流程【免费下载链接】unilmLarge-scale Self-supervised Pre-training Across Tasks, Languages, and Modalities项目地址: https://gitcode.com/GitHub_Trending/un/unilm导读本文基于仓库decoding/IAD/fairseq中自带的 Speech-to-TextS2T模块系统讲解如何在 MuST-C 多语种语音翻译语料上完成端到端语音识别ASR与语音翻译ST的完整实验闭环从数据下载与预处理、TSV manifest 与特征生成到单语/联合 ASR 训练、基于 ASR 预训练编码器初始化的双语/多语言 ST 训练再到检查点平均、WER 与 sacreBLEU 评估。读完本文你将能独立复现原文档中 31M / 76M 参数的 S2T Transformer 训练流程并理解--task speech_to_text、--update-freq、--load-pretrained-encoder-from、--ignore-prefix-size与--prefix-size等关键参数背后的源码机制。一、背景MuST-C 与 fairseq S2TMuST-C 是一个多语种语音到文本翻译speech-to-text translation语料提供基于英文 TED 演讲的 8 种目标语言翻译德语 de、西班牙语 es、法语 fr、意大利语 it、荷兰语 nl、葡萄牙语 pt、罗马尼亚语 ro、俄语 ru。原文档指出在 fairseq S2T 框架下用更简单的模型训练管线即可在 MuST-C 上达到与 ESPNet-ST 相当的水平。fairseq 的 S2T 建模方案对应decoding/IAD/fairseq/examples/speech_to_text/README.md具有如下设计特点TSV manifest 承载数据每个数据集划分split对应一个 TSV 清单文件每列代表一个数据字段包含音频/特征路径、帧数、目标文本、说话人 ID 等特征可预计算语音特征如 log-mel filter bank在训练期间通常固定不变可预先提取为 NumPy 特征文件也可以直接在 manifest 中指向 WAV/FLAC 音频文件由 fairseq S2T 在训练时在线提取。特征/音频文件还可打包进无压缩 ZIP通过字节偏移与长度访问以提升 I/O 性能YAML 数据配置目标文本的分词器与词典路径、特征变换如 CMVN 与 SpecAugment、温度重采样等都由一个 YAML 文件统一管理统一训练/评估接口全部复用fairseq-train/fairseq-generate只需指定--task speech_to_text与--arch fairseq.models.speech_to_text.*下的架构。本文对应的官方示例文档位于 mustc_example.md预处理脚本、数据工具与模型实现均在本仓库内可直接查阅。二、环境准备与数据预处理2.1 安装依赖S2T 数据预处理与模型训练需要额外的 Python 包pip install pandas torchaudio sentencepiece其中pandas用于 TSV manifest 的读写torchaudio用于读取 WAV 与提取特征sentencepiece用于训练子词BPE/Unigram模型与词典。2.2 数据目录约定下载并解压 MuST-C 数据到路径${MUSTC_ROOT}/en-${TARGET_LANG_ID}。也就是说数据根目录${MUSTC_ROOT}下按目标语言组织为en-de、en-fr、en-es等子目录。从源码看预处理脚本decoding/IAD/fairseq/examples/speech_to_text/prep_mustc_data.py中的MUSTCDataset 类定义了两个关键常量SPLITS [train, dev, tst-COMMON, tst-HE]训练/开发/官方测试集tst-COMMON 与 tst-HELANGUAGES [de, es, fr, it, nl, pt, ro, ru]8 种目标语言。它还会校验每个目录下存在data/{split}/wav与data/{split}/txt结构并从txt/{split}.yaml读取音频段元信息偏移 offset、时长 duration、说话人 ID 等从txt/{split}.en与txt/{split}.{lang}读取源文与译文文本。2.3 运行预处理脚本对每个语言执行 ASR 与 ST 两条数据准备命令以--task区分目标文本字段随后再生成两份联合数据joint的词汇表与配置# 生成 TSV manifests、特征、词汇表和每个语言的配置 python examples/speech_to_text/prep_mustc_data.py \ --data-root ${MUSTC_ROOT} --task asr \ --vocab-type unigram --vocab-size 5000 python examples/speech_to_text/prep_mustc_data.py \ --data-root ${MUSTC_ROOT} --task st \ --vocab-type unigram --vocab-size 8000 # 为联合数据增加词汇表和配置 # 基于上面生成好的 manifests 和特征 python examples/speech_to_text/prep_mustc_data.py \ --data-root ${MUSTC_ROOT} --task asr --joint \ --vocab-type unigram --vocab-size 10000 python examples/speech_to_text/prep_mustc_data.py \ --data-root ${MUSTC_ROOT} --task st --joint \ --vocab-type unigram --vocab-size 10000注意这里命令中的路径examples/speech_to_text/...是相对 fairseq 根目录即decoding/IAD/fairseq/而言的在本仓库中脚本实际位于 prep_mustc_data.py。生成的文件分布如下每种语言的数据写入${MUSTC_ROOT}/en-${TARGET_LANG_ID}每个 split 的{split}_{task}.tsv、句子片段模型spm_unigram{size}_{task}.model/.vocabfairseq 词典为spm_unigram{size}_{task}.txt、数据配置config_{task}.yaml联合数据写入${MUSTC_ROOT}config_{task}.yaml与联合词典以及指向各语言 manifest 的软链接形如{split}_{lang}_{task}.tsv。命令行参数说明依据 prep_mustc_data.py 的argparse定义参数类型/取值默认值含义--data-root/-d必填-MuST-C 数据根目录--taskasr/st-ASR 任务目标文本取英文转写ST 任务取目标语言译文--vocab-typebpe/unigram/char必填SentencePiece 子词模型类型--vocab-sizeint8000词汇表大小char 类型时忽略--jointflag关闭是否处理 8 语言联合数据2.4 预处理脚本内部做了什么理解脚本内部流程有助于排查问题源码prep_mustc_data.py特征提取对每个 split用torchaudio加载音频段按 offset/n_frames 切片调用data_utils.extract_fbank_featuresdata_utils.py提取80 维 log-mel filter bank特征保存为fbank80/{utt_id}.npyZIP 打包将全部.npy特征打包为fbank80.zipmanifest 中通过 ZIP 内的字节偏移与长度引用特征避免大量小文件随机读提升 I/O 性能生成 TSV manifest每个 split 一个{split}_{task}.tsv列为id, audio, n_frames, tgt_text, speaker。其中n_frames由音频时长换算1 (duration_ms - 25) / 10对应 10ms 帧移、25ms 窗长tgt_text在--task asr时取英文转写、在--task st时取目标语言译文训练集还会经过filter_manifest_df过滤空句、过短/过长语音等训练词典用训练集目标文本训练 SentencePiece 模型并导出 fairseq 词典。注意gen_vocab在训练句子片段模型时设置了--character_coverage1.0且 ST 联合数据会把 8 个语言 ID 标记lang:de等作为user_defined_symbols注入词典生成配置 YAMLgen_config_yaml写入config_{task}.yaml包含词典文件名、输入通道数1与每通道特征维度80、SentencePiece BPE tokenizer 配置、SpecAugment 策略等。一个值得注意的细节联合 ASR 使用specaugment_policylb联合 ST 使用specaugment_policyld见 prep_mustc_data.py 的process/process_joint且 ST 配置会开启prepend_tgt_lang_tag这正是多语言 ST 训练与解码特殊参数--ignore-prefix-size 1/--prefix-size 1的由来。2.5 预训练模型词汇表如果希望直接使用官方预训练模型原文档提供了对应词汇表文件ASR 的 unigram-5000 词汇表、ST 的 unigram-8000 词汇表、联合 ASR/多语言 ST 的 unigram-10000 词汇表按{语言}_{任务}_vocab_unigram{size}.zip的命名约定组织。这些文件位于外部资源站本文不再展开直接运行上文预处理命令同样可以生成结构一致的自有词汇表。三、生成产物速览TSV manifest 与 config YAML预处理完成后${MUSTC_ROOT}/en-de/下会形成如下关键文件以 ASR 为例train_asr.tsv、dev_asr.tsv、tst-COMMON_asr.tsv、tst-HE_asr.tsvconfig_asr.yamlspm_unigram5000_asr.model、spm_unigram5000_asr.txtfairseq 词典dict.txt对应文件训练时--task speech_to_text会加载这些文件。任务实现位于 fairseq/tasks/speech_to_text.py其关键点--config-yaml参数默认值为config.yaml指向 manifest 根目录下的数据配置本示例实际使用config_asr.yaml/config_st.yaml--max-source-positions默认 6000与--max-target-positions默认 1024控制源/目标序列最大长度setup_task依据 YAML 中的vocab_filename加载 fairseq 词典load_dataset通过SpeechToTextDatasetCreator.from_tsv读取 TSV并按 YAML 配置构造分词器pre_tokenizer/bpe_tokenizer。配置 YAML 中transforms字段决定了训练/评估阶段对特征施加的变换。在 speech_to_text_dataset.py 的get_feature_transforms中支持按 split 通配匹配训练集使用_train通配本示例为[utterance_cmvn, specaugment]其他 split 使用*通配[utterance_cmvn]。也就是说CMVN倒谱均值方差归一化对所有数据在线执行SpecAugment 只对训练集生效与 README 中预处理阶段不再做 CMVN、改为配置 YAML 驱动在线变换的更新说明一致。四、ASR 实验训练、推理与评估4.1 单语言 ASR 训练以 En-De 为例fairseq-train ${MUSTC_ROOT}/en-de \ --config-yaml config_asr.yaml --train-subset train_asr --valid-subset dev_asr \ --save-dir ${ASR_SAVE_DIR} --num-workers 4 --max-tokens 40000 --max-update 100000 \ --task speech_to_text --criterion label_smoothed_cross_entropy --report-accuracy \ --arch s2t_transformer_s --optimizer adam --lr 1e-3 --lr-scheduler inverse_sqrt \ --warmup-updates 10000 --clip-norm 10.0 --seed 1 --update-freq 84.2 联合 ASR 训练8 语言fairseq-train ${MUSTC_ROOT} \ --config-yaml config_asr.yaml \ --train-subset train_de_asr,train_nl_asr,train_es_asr,train_fr_asr,train_it_asr,train_pt_asr,train_ro_asr,train_ru_asr \ --valid-subset dev_de_asr,dev_nl_asr,dev_es_asr,dev_fr_asr,dev_it_asr,dev_pt_asr,dev_ro_asr,dev_ru_asr \ --save-dir ${JOINT_ASR_SAVE_DIR} --num-workers 4 --max-tokens 40000 --max-update 100000 \ --task speech_to_text --criterion label_smoothed_cross_entropy --report-accuracy \ --arch s2t_transformer_s --optimizer adam --lr 1e-3 --lr-scheduler inverse_sqrt \ --warmup-updates 10000 --clip-norm 10.0 --seed 1 --update-freq 8要点解读联合训练的 manifest 根目录是${MUSTC_ROOT}不是某个en-xx子目录--train-subset/--valid-subset用逗号拼接 8 个语言各自的{split}_{lang}_asr子集即预处理脚本创建的软链接--update-freq 8以 8 步梯度累积模拟 8 卡训练效果单卡即可复现使用多卡时应按实际卡数调整评估指标选择--report-accuracy--criterion label_smoothed_cross_entropy使用标签平滑交叉熵学习率采用inverse_sqrt调度 10000 步 warmup--clip-norm 10.0做梯度裁剪。4.3 ASR 推理与评估CHECKPOINT_FILENAMEavg_last_10_checkpoint.pt python scripts/average_checkpoints.py \ --inputs ${ASR_SAVE_DIR} --num-epoch-checkpoints 10 \ --output ${ASR_SAVE_DIR}/${CHECKPOINT_FILENAME} fairseq-generate ${MUSTC_ROOT}/en-de \ --config-yaml config_asr.yaml --gen-subset tst-COMMON_asr --task speech_to_text \ --path ${ASR_SAVE_DIR}/${CHECKPOINT_FILENAME} --max-tokens 50000 --beam 5 \ --scoring wer --wer-tokenizer 13a --wer-lowercase --wer-remove-punct # 联合模型 python scripts/average_checkpoints.py \ --inputs ${JOINT_ASR_SAVE_DIR} --num-epoch-checkpoints 10 \ --output ${JOINT_ASR_SAVE_DIR}/${CHECKPOINT_FILENAME} for LANG in de nl es fr it pt ro ru; do fairseq-generate ${MUSTC_ROOT} \ --config-yaml config_asr.yaml --gen-subset tst-COMMON_${LANG}_asr --task speech_to_text \ --path ${JOINT_ASR_SAVE_DIR}/${CHECKPOINT_FILENAME} --max-tokens 50000 --beam 5 \ --scoring wer --wer-tokenizer 13a --wer-lowercase --wer-remove-punct done检查点平均脚本为 fairseq/scripts/average_checkpoints.py--num-epoch-checkpoints 10取最后 10 个 epoch 的检查点求平均可有效缓解训练末期波动ASR 用--scoring wer计算词错误率WER并配合--wer-tokenizer 13a、--wer-lowercase、--wer-remove-punct对输出做标准化的去标点、小写化处理保证与 Kaldi 口径的 13a tokenizer 可比联合模型需要在tst-COMMON上逐个语言循环评估。4.4 ASR 结果原文档记录数据--archParamsEn-DeEn-NlEn-EsEn-FrEn-ItEn-PtEn-RoEn-RuSingles2t_transformer_s31M18.217.617.717.217.919.118.117.7Joints2t_transformer_m76M16.816.716.916.917.017.417.016.9数值为 tst-COMMON 上的 WER越低越好。单语言模型可逐个下载联合模型为单一 76M 检查点。原文档附有外部模型下载链接本文略去。五、ST 实验训练、推理与评估ST 实验的核心技巧是用 ASR 预训练编码器初始化 ST 编码器由于 ST 需要先将语音编码为语义表示再翻译直接用 ASR 训练好的编码器初始化可以显著加速收敛并提升翻译质量。5.1 双语 ST 训练以 En-De 为例fairseq-train ${MUSTC_ROOT}/en-de \ --config-yaml config_st.yaml --train-subset train_st --valid-subset dev_st \ --save-dir ${ST_SAVE_DIR} --num-workers 4 --max-tokens 40000 --max-update 100000 \ --task speech_to_text --criterion label_smoothed_cross_entropy --report-accuracy \ --arch s2t_transformer_s --optimizer adam --lr 2e-3 --lr-scheduler inverse_sqrt \ --warmup-updates 10000 --clip-norm 10.0 --seed 1 --update-freq 8 \ --load-pretrained-encoder-from ${ASR_SAVE_DIR}/${CHECKPOINT_FILENAME}5.2 多语言 ST 训练8 语言fairseq-train ${MUSTC_ROOT} \ --config-yaml config_st.yaml \ --train-subset train_de_st,train_nl_st,train_es_st,train_fr_st,train_it_st,train_pt_st,train_ro_st,train_ru_st \ --valid-subset dev_de_st,dev_nl_st,dev_es_st,dev_fr_st,dev_it_st,dev_pt_st,dev_ro_st,dev_ru_st \ --save-dir ${MULTILINGUAL_ST_SAVE_DIR} --num-workers 4 --max-tokens 40000 --max-update 100000 \ --task speech_to_text --criterion label_smoothed_cross_entropy --report-accuracy \ --arch s2t_transformer_s --ignore-prefix-size 1 --optimizer adam --lr 2e-3 --lr-scheduler inverse_sqrt \ --warmup-updates 10000 --clip-norm 10.0 --seed 1 --update-freq 8 \ --load-pretrained-encoder-from ${JOINT_ASR_SAVE_DIR}/${CHECKPOINT_FILENAME}要点解读ST 学习率高于 ASR2e-3vs1e-3同样使用--load-pretrained-encoder-from加载 ASR 检查点联合 ST 用联合 ASR 检查点多语言 ST 的关键预处理阶段联合 ST 配置开启了prepend_tgt_lang_tag训练时会在目标序列开头拼上目标语言 ID token如lang:de作为 BOS因此必须用--ignore-prefix-size 1将该 token 排除在损失之外。源码中 fairseq/tasks/speech_to_text.py 的build_criterion会在开启prepend_tgt_lang_tag而ignore_prefix_size ! 1时直接抛错强制用户显式设置该参数。5.3 ST 推理与评估CHECKPOINT_FILENAMEavg_last_10_checkpoint.pt python scripts/average_checkpoints.py \ --inputs ${ST_SAVE_DIR} --num-epoch-checkpoints 10 \ --output ${ST_SAVE_DIR}/${CHECKPOINT_FILENAME} fairseq-generate ${MUSTC_ROOT}/en-de \ --config-yaml config_st.yaml --gen-subset tst-COMMON_st --task speech_to_text \ --path ${ST_SAVE_DIR}/${CHECKPOINT_FILENAME} \ --max-tokens 50000 --beam 5 --scoring sacrebleu # 多语言模型 python scripts/average_checkpoints.py \ --inputs ${MULTILINGUAL_ST_SAVE_DIR} --num-epoch-checkpoints 10 \ --output ${MULTILINGUAL_ST_SAVE_DIR}/${CHECKPOINT_FILENAME} for LANG in de nl es fr it pt ro ru; do fairseq-generate ${MUSTC_ROOT} \ --config-yaml config_st.yaml --gen-subset tst-COMMON_${LANG}_st --task speech_to_text \ --prefix-size 1 --path ${MULTILINGUAL_ST_SAVE_DIR}/${CHECKPOINT_FILENAME} \ --max-tokens 50000 --beam 5 --scoring sacrebleu done与训练端对称多语言 ST 解码时用--prefix-size 1强制解码从目标语言 ID token作为 BOS开始。这一约束同样在任务源码中有强制校验build_generator检测到prepend_tgt_lang_tag而prefix_size ! 1时报错并在生成后通过symbols_to_strip_from_output自动剥离输出中的语言 ID token。评估指标使用--scoring sacrebleusacreBLEU这是 ST/MT 领域的标准评测口径。5.4 ST 结果原文档记录数据--archParamsEn-DeEn-NlEn-EsEn-FrEn-ItEn-PtEn-RoEn-RuBilinguals2t_transformer_s31M22.727.327.232.922.728.121.915.3Multilinguals2t_transformer_m76M24.528.628.234.924.631.123.816.0数值为 tst-COMMON 上的 BLEU越高越好。可见多语言联合模型在几乎全部分向上优于单语言双语模型。六、源码级原理S2T Transformer 架构实验中反复出现的--arch s2t_transformer_s/s2t_transformer_m注册于 fairseq/models/speech_to_text/s2t_transformer.pyS2TTransformerModel一个标准的 Encoder-Decoder 模型FairseqEncoderDecoderModel核心改动是在 Transformer 编码器前插入一个可训练的输入下采样模块既把语音特征投影到编码器维度又沿时间轴降低序列长度以节省计算Conv1dSubsampler由若干层 1D 卷积沿时间维步长 2叠加 GLU 门控线性单元构成forward中每层执行conv - glu并同步按公式((len-1)/21).floor()计算下采样后的序列长度**基础架构base_architecture**默认值卷积核5,5、卷积通道 1024编码器 12 层、嵌入维度由具体架构决定解码器 6 层dropout 0.1m 变体为 0.15编码器/解码器均开启 pre-normnormalize_beforeTrue激活函数 relu架构变体s2t_transformer_s编码器嵌入维度 256、FFN 256×8、注意力头 4约 31M 参数s2t_transformer_m编码器嵌入维度 512、FFN 512×4、注意力头 8约 76M 参数另有s2t_transformer_sp16 层编码器的 s 变体、s2t_transformer_mp、s2t_transformer_l/lp等更大规模配置可供扩展。因此文中 31Ms2t_transformer_s与 76Ms2t_transformer_m参数量的差异主要来自编码器宽度与 FFN 尺寸而不是模型结构上的本质区别——这解释了为什么单语言实验用小模型、联合/多语言实验用大模型。七、关键参数速查表参数取值示例作用--task speech_to_text固定启用 S2T 任务加载 TSV YAML 数据管线--config-yamlconfig_asr.yaml/config_st.yaml指定数据配置词典、tokenizer、特征变换--train-subset/--valid-subsettrain_asr/train_de_asr,...训练/验证 split可逗号拼接做多语言--archs2t_transformer_s/_m模型架构31M / 76M--criterionlabel_smoothed_cross_entropy标签平滑交叉熵损失--report-accuracy-训练中同时报告 token 准确率--max-tokens40000训练/ 50000生成每 batch 最大 token 数--update-freq 8-8 步梯度累积模拟 8 卡--lr1e-3ASR/ 2e-3ST峰值学习率配inverse_sqrt调度--warmup-updates10000学习率 warmup 步数--clip-norm10.0梯度裁剪范数--load-pretrained-encoder-fromASR 检查点路径ST 编码器用 ASR 预训练初始化--ignore-prefix-size 1多语言 ST 训练目标 BOS 语言 ID 不计入损失--prefix-size 1多语言 ST 解码强制以目标语言 ID 作为 BOS 开始解码--scoringwer/sacrebleu评估指标ASR / ST--wer-tokenizer 13a --wer-lowercase --wer-remove-punct-WER 前对输出做标准化八、复现注意事项目录与路径预处理与训练命令中的fairseq-train/fairseq-generate需在 fairseq 安装后可用的环境中执行scripts/average_checkpoints.py对应本仓库 fairseq/scripts/average_checkpoints.pyexamples/speech_to_text/*.py对应 examples/speech_to_text 下的脚本8 语言数据必须齐全process_joint会断言${MUSTC_ROOT}下存在全部 8 个en-{lang}目录否则直接报错联合训练所需的{split}_{lang}_{task}.tsv软链接也由--joint预处理一次性生成多语言 ST 的参数必须成对出现训练端--ignore-prefix-size 1与解码端--prefix-size 1缺一不可任务源码会在配置了prepend_tgt_lang_tag的情况下强制校验这两个值否则训练/生成都无法启动SpecAugment 与 CMVN 由 YAML 驱动特征变换在数据加载时按 split 通配匹配应用训练集_train用utterance_cmvn specaugment其他 split 仅utterance_cmvn无需也不应在预处理阶段手工做 CMVN评估口径ASR 统一用 13a tokenizer 的 WERST 统一用 sacreBLEU评测集固定为tst-COMMON检查点采用最后 10 个 epoch 的平均结果。九、进一步探索其余 S2T 示例LibriSpeech ASR 示例见 librispeech_example.mdCoVoST 2 多语言 ST 示例见 covost_example.mdS2T 框架总览与数据格式说明见 examples/speech_to_text/README.md任务与数据管线实现fairseq/tasks/speech_to_text.py、fairseq/data/audio/speech_to_text_dataset.py模型实现fairseq/models/speech_to_text/s2t_transformer.py。本文完整继承并扩展了官方 mustc_example.md 的全部命令、参数与结果所有实现细节均可回到上述源码文件中逐行核对。【免费下载链接】unilmLarge-scale Self-supervised Pre-training Across Tasks, Languages, and Modalities项目地址: https://gitcode.com/GitHub_Trending/un/unilm创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考