SpeechLM 实战指南:语音-文本联合预训练、分词器流水线与 ASR/ST 微调

发布时间:2026/9/14 8:20:54
SpeechLM 实战指南:语音-文本联合预训练、分词器流水线与 ASR/ST 微调 SpeechLM 实战指南语音-文本联合预训练、分词器流水线与 ASR/ST 微调【免费下载链接】unilmLarge-scale Self-supervised Pre-training Across Tasks, Languages, and Modalities项目地址: https://gitcode.com/GitHub_Trending/un/unilmSpeechLM 是 unilm 仓库Large-scale Self-supervised Pre-training Across Tasks, Languages, and Modalities中的一个语音预训练项目其核心思想是在语音自监督预训练wav2vec 2.0/HuBERT 式的 masked unit modeling之外额外引入大规模的未配对纯文本数据参与联合训练从而让模型在只有语音的条件下也能获得类似文本预训练的正则化收益。本文以 speechlm/README.md 为主体结合仓库中的模型定义SpeechLM.py、预训练/微调配置speechlm/speechlm/config、联合预训练任务joint_sc2t_pretrain.py与训练脚本完整梳理 SpeechLM-P/SpeechLM-H 两类模型的 tokenizer 构建、预训练、ASR/ST 微调与解码、以及特征提取的完整实操路径并补充 README 中未展开的配置参数含义与底层实现细节。1. 模型家族与环境准备README 将 SpeechLM 划分为两个系列、两档规模模型预训练数据微调数据说明SpeechLM-P Base960 小时 LibriSpeech 40M 词文本无 / 100h LibriSpeech音素级phoneme单位模型SpeechLM-H Base960 小时 LibriSpeech 40M 词文本无 / 100h LibriSpeech隐层单位hidden-unit模型SpeechLM-P Base960 小时 LibriSpeech 40M 词文本En-De / En-Ca / En-Ar / En-Tr CoVoST-2语音翻译ST微调版本SpeechLM-P Large60k 小时 LibriLight 40M 词文本无 / 960h LibriSpeech大规模语音版SpeechLM-P Large60k 小时 LibriLight 40M 词文本En-De / En-Ca / En-Ar / En-Tr CoVoST-2大规模 ST 微调版本其中P 指以音素phoneme为预训练目标单位H 指以离散隐层单位hidden unitsHuBERT 风格 k-means 聚类得到的 token为目标单位。具体权重文件的下载入口请查阅 speechlm/README.md 的 Pre-Trained and Fine-tuned Models 表格该表保留了原始云存储链接。环境准备按 README 的要求fairseq以 git submodule 形式引入仓库中 speechlm/fairseq 目录即为子模块挂载点git submodule update --init SpeechLM/fairseq cd SpeechLM/ pip install --editable fairseq/ pip install sacrebleu1.5.1所有训练脚本都通过fairseq_cli/hydra_train.py启动并用--config-dir指向 speechlm/speechlm/config 下的配置组pretrain/、finetune/、decode/三个子目录因此脚本内部都带有[ ${PWD##*/} ! SpeechLM ] exit的目录校验必须切换到SpeechLM/根目录再执行。2. 模型架构双分支的语音编码器 单位编码器SpeechLM 的推理版实现被合并为单文件 SpeechLM.py另有共享的 modules.py训练版实现在 speechlm/speechlm/models/speechlm.py。从源码结构看整个模型由两类主干组成语音分支wav2vec 2.0 风格的卷积特征提取器ConvFeatureExtractionModel卷积层配置字符串[(512,10,5)] [(512,3,2)] * 4 [(512,2,2)] * 2总下采样 320 倍后接一个encoder_layers层的 Transformer 编码器TransformerEncoder单位文本分支一个TransformerEncoderBaseunit_encoder配置在model.text_transformer下它在预训练时既处理从语音预测出的单位序列也直接处理纯文本样本。SpeechLMConfig 中定义的关键默认值Base 配置会由 YAML 覆盖包括label_rate50目标帧率、mask_prob0.65、final_dim256对比投影维度、mix_with_unitTrue、use_pred_unitFalse、l2_embeddingFalse、add_unit_encoderFalse这些单位分支开关在预训练 YAML 中才会置为true。前向逻辑在 SpeechLM.forward 中按输入分流source非空走forward_speech否则走forward_text文本分支。forward_speech的流程是提特征 →LayerNorm→ 按mask_prob掩码apply_mask掩码片段替换为可学习mask_emb→ 过编码器 → 与单位 embedding 做F.normalize后的对比式预测compute_pred温度由logit_temp控制。当add_unit_encoderTrue时还会调用convert_embeddings把语音编码输出投影到final_dim空间按mix_with_unit配置随机把一部分位置的 soft embedding 替换为离散单位的 embeddingunit_embed_tokens再送入unit_encoder并对替换位置计算l2_embedding损失——从源码结构看这正是让单位编码器同时见得到 soft 语音表征与 hard 单位序列的关键设计。2.1 预训练损失构成训练损失由 speechlm_criterion.py 中的SpeechLMCriterion计算从源码可见总损失由四部分组成L_UMLM语音端pred_masked_weight默认 1.0加权被掩帧的交叉熵pred_nomask_weight默认 0.0加权未掩帧额外正则项loss_weights配置中为[10]作用于模型get_extra_losses返回的features_pen特征 L2 惩罚以及embedding_l2_loss若开启l2_embeddingL_UMLM文本端可选text_mum_weight默认 0.0加权文本分支的 masked unit modelingL_UCTCtext_ctc_weight默认 0.1加权的文本端 CTC 损失compute_ctc_lossblank 为s。预训练 YAMLspeechlm_base_librispeech.yaml 与 speechlm_large_librilight.yaml均显式设置pred_masked_weight: 1.0、pred_nomask_weight: 0.0、loss_weights: [10]、text_ctc_weight: 0.1、text_mum_weight: 0.0即实际生效的是语音端 masked 对比 特征惩罚 文本端 CTC。2.2 Base 与 Large 配置对照两份预训练配置的主要差异如下均可在对应 YAML 中逐行核对配置项BaseBase 语音LargeLibriLightencoder_layers/embed_dim/ffn/heads6 / 768 / 3072 / 812 / 1024 / 4096 / 16text_transformer.encoder6 层 / 76812 层 / 1024extractor_mode/task.normalizedefault/falselayer_norm/true须与特征提取器一致layer_norm_firstfalsetruefeature_grad_mult0.11.0mask_prob0.800.80正则layerdrop/dropout 系列0.1全部 0.0scaling_for_att1.032大模型防注意力溢出优化lr 5e-4max_update400kclip_norm10.0polynomial_decaywarmup 32klr 1e-3max_update400kclip_norm1.0polynomial_decaywarmup 32k分布式world_size32nprocs_per_node8max_tokens1.4M同左max_tokens900k3. 联合预训练任务语音与文本如何在同一 batch 中采样预训练使用的任务是 joint_sc2t_pretrain.py 中注册的joint_sc2t_pretraining。它最核心的机制是用子集subset字符串的语法声明一个多模态数据混合在脚本中形如dataset.train_subsettrain_960train_text.phn-ltr dataset.valid_subsetdev_cleandev_clean.phn-ltr从load_dataset的源码看号分隔的段依次表示语音数据集如train_960加载train_960.tsv与label_dir下的.phn/.km标签、配对文本数据集如train_text.phn-ltr按 源-目标 解析为 phoneme 序列与 letter 序列、可选的未配对单语文本、可选的有监督数据随后由MultiCorpusDataset按resample_multi_modality_dataset计算出的分布比例混合采样。其中文本采样有两个关键超参text_maxtokens_ratio文本 token 预算 max_tokens * ratio / 320与speech_sampling_alpha/text_sampling_alpha温度式重采样系数默认 0.2。语音标签的帧率由model.label_rate决定这正是 P/H 两种模型的分水岭见训练脚本 base_speechlmp.sh 与 base_speechlmh.sh脚本task.labelsmodel.label_rate训练子集base_speechlmp.shP Base[phn]10010 ms 帧率train_960train_text.phn-ltrbase_speechlmh.shH Base[km]5020 ms 帧率train_960train_text.km-ltrlarge_speechlmp.shP Large[phn]100train_960train_text.phn-ltr三个脚本的通用签名为data_dir text_data_dir [mount$PWD] [world_size32] [update_freq1]模型输出到${mount}/exp/pretrain/base_speechlmp_*之类的目录data_dir需包含train_960.{tsv,phn}或.kmtext_data_dir需包含train_text.phn-ltr.{phn,ltr}.{bin,idx}H 模型为train_text.km-ltr.{km,ltr}.{bin,idx}。提示README 在 SpeechLM-H Base model 小节的示例命令中误写了base_speechlmp.sh实际应执行 base_speechlmh.sh其labels与label_rate均不同。4. Tokenizer把未配对数据变成可用的预训练信号README 的 Tokenizers 一节是 SpeechLM 最具辨识度的部分预训练所需的语音单位与文本单位都不是直接标注出来的而是靠四个 tokenizer 构建的。4.1 语音侧音素 tokenizerP 系列这是一个混合 HMM ASR 模型在 Kaldi 配方下用 100 小时 LibriSpeech 标注数据训练 HMM再对 960 小时无标注语音解码从 lattice 中取出帧级对齐音素。README 提供了解码结果train_960.tsv/train_960.phn、dev_clean.tsv/dev_clean.phn帧率为 10010 ms。仓库中保留了小规模示例speechlm/dataset/LibriSpeech/phone_unit/train_sample100.phn 与 train_sample100.tsv可直观查看 tsvwav 路径、采样点数、时长与 phn 序列的一一对应关系。4.2 文本侧音素 tokenizerP 系列把未配对文本变成 (phonemes, letters) 配对数据流水线为words - phonemes - upsampled phones。一键脚本是 speechlm/speechlm/data_process/prepare_phn2ltr_librilm.sh从脚本源码可见其完整步骤下载 LibriSpeech-LM 语料librispeech-lm-norm.txtwrd2ltr.py 把文本转为 letter 序列ltr2kaldi_phn_sil025.py 将字母转为 Kaldi 风格音素静默音统一为SILfilter_paireddata_by_len.py 过滤过长样本先 2000upsample 后按 2800 截断——脚本注释说明 2800 是按 Large 配置下900000/320≈2812token/batch 的预算设定的repeat_withou_insert_sil_less_4375.py 依据mean5_and_std25_sil14_spn32.dict对音素做重复上采样使其对齐到 100 帧/秒50% 的音素重复 5 次、静默音重复 14 次、静音符号 32 次等统计设定txt2idx.sh 生成 fairseq 二进制索引train_text.phn-ltr.phn.{bin,idx}与train_text.phn-ltr.ltr.{bin,idx}。运行前需确保输出目录dataset/LibriLM/phone_unit/bin-idx/下已有仓库提供的 dict.phn.txt 与 dict.ltr.txt仓库中 speechlm/dataset/LibriLM/phone_unit/bin-idx/config.yaml 为配套数据配置。4.3 语音侧隐层单位 tokenizerH 系列按 wav2vec 2.0 manifest 流程准备三样东西1) wav 清单如 speechlm/dataset/LibriSpeech/hidden_unit/train_sample100.tsv2) 从预训练模型第 9 层等隐层抽取后 k-means 量化得到的单位序列如 train_sample100.km3) 单位词表 dict.km.txt。4.4 文本侧隐层单位 tokenizerH 系列用少量 ASR 数据100 小时 LibriSpeech训练一个 FastSpeech 类模型 speechlm/speechlm/models/fasttext2unit.py——与原 FastSpeech 不同它输出离散单位而非连续频谱——作为文本→语音风格单位的生成器。流程为1) 转写文本转音素序列2) 从语音提取隐层单位3) 在配对数据上训练bash speechlm/scripts/tokenizer_fastT2U/train_s_5e-4.sh $data_dir仓库对应 train_s_5e-4.sh4) 用 generate.sh 对大规模文本语料批量生成单位序列bash speechlm/scripts/tokenizer_fastT2U/generate.sh $model_path $gen_set。训练/生成的示例数据在 speechlm/dataset/LibriSpeech/fast_phone2unit含 config.yaml、config_generate.yaml 与genset_examples.tsv模型 checkpoint 的下载链接见 README 原文。5. ASR 微调与解码LibriSpeech5.1 数据准备按 wav2vec 2.0 manifest 的做法生成train.tsv与train.ltr并保证词表与预训练模型使用的 dict.ltr.txt 完全一致仓库提供了 train_sample100.ltr 等示例文件。5.2 微调 CTC 模型# Base 模型speechlm/scripts/tune_speechlm_asr/finetune_base_ctc.sh model_path data_dir cpt_tag [mount$PWD] [world_size8] [update_freq1] model_pathpath/to/your/pre-trained/model data_dirdataset/LibriSpeech/asr bash speechlm/scripts/tune_speechlm_asr/finetune_base_ctc.sh $model_path $data_dir tag400k # Large 模型speechlm/scripts/tune_speechlm_asr/finetune_large_ctc.sh model_path data_dir cpt_tag [mount$PWD] [world_size8] [update_freq4] bash speechlm/scripts/tune_speechlm_asr/finetune_large_ctc.sh $model_path $data_dir tag400k以 finetune_base_ctc.sh 为例脚本基于 speechlm_base_100h.yaml 启动该配置把任务切到fine_tuning: true、labels: [ltr]、single_target: true序列级标签label_rate退化为 -1损失换成标准ctc训练子集train_clean_100、验证子集dev_othermax_update: 30000、lr: 1e-5、max_tokens: 1.6M学习率调度用tri_stagephase_ratio: [0.1, 0.4, 0.5]、final_lr_scale: 0.05。模型侧_name: speechlm_ctc即 speechlm_ctcasr.py保留了预训练式的掩码mask_prob: 0.65、mask_channel_prob: 0.5、mask_channel_length: 64、layerdrop: 0.1且freeze_finetune_updates: 0表示从第一步起全参数更新。cpt_tag参数只用于拼接实验目录名ctc30k_from_tag方便区分不同预训练步数的权重。5.3 三种解码方式# 1) 直接解码 CTC 模型Viterbi bash speechlm/scripts/tune_speechlm_asr/inference_ctc.sh $model_path $data_dir # large 模型改用 inference_ctc_large.sh# 2) 4-gram 语言模型解码flashlight kenlm # 需先把 4-gram.arpa 与词-字母 lexicon librispeech_lexicon.lst 放进 $data_dir bash speechlm/scripts/tune_speechlm_asr/inference_ctc_kenlm.sh $model_path $data_dir# 3) large 模型使用 fairseq-lm 词级 Transformer LM 解码 # 把 lm_librispeech_word_transformer.pt 及其词表 dict.txt 放入 $data_dir/fairseq_word_lm # dict.txt 需首字母大写以匹配词-字母 lexiconlexicon 同样放入 $data_dir bash speechlm/scripts/tune_speechlm_asr/inference_ctc_large_fsqlm.sh $model_path $data_dir dev_other解码脚本统一走 speechlm/speechlm/infer.py config/decode 下的 YAML如 infer_kenlm.yaml。以 inference_ctc_kenlm.sh 为例它对gen-set默认dev_clean,dev_other,test_clean,test_other中的每个子集并行启动解码进程kenlm 搜索 beam 设为 1500并会校验$data_dir/librispeech_lexicon.lst与$data_dir/4-gram.arpa是否就位。脚本末尾还留有一处重要提示fairseq 加载微调模型时会连带加载预训练模型的状态来构建模型实例因此可通过common_eval.model_overrides用 speechlmp_base_cfg.pt只含配置、不含权重的空 checkpoint替换w2v_path避免本地没有预训练权重时报错——如果你的微调模型改过结构如编码器层数需相应修改该 override。6. ST 微调与解码CoVoST-26.1 数据准备下载 Common Voiceversion 4英文音频到$cv_root/en运行 manifest 生成脚本它会把 mp3 转波形、生成语音-翻译对的 tsv 并创建数据配置langde # ca,ar,tr cv_rootdataset/CommonVoice/v4 bash speechlm/data_process/prepare_covost2_enxx.sh $lang $cv_root仓库提供了 en-de 的示例数据 speechlm/dataset/CommonVoice/v4/en/en-de其中 config_base_ende.yaml 与 config_large_ende.yaml 分别是两种模型规模的数据配置spm_char_st_en_de.*为目标语字符级 SentencePiece 词表。6.2 微调 encoder-decoder 模型# Basespeechlm/scripts/tune_speechlm_st/ft_base_covost_enxx.sh model_path data_dir lang cpt_tag [mount$PWD] [world_size8] [update_freq2] model_pathpath/to/your/pre-trained/model langde # ca,ar,tr data_dirdataset/CommonVoice/v4/en/en-${lang} bash speechlm/scripts/tune_speechlm_st/ft_base_covost_enxx.sh $model_path $data_dir $lang tag400k # Largespeechlm/scripts/tune_speechlm_st/ft_large_covost_enxx.sh默认 update_freq4 bash speechlm/scripts/tune_speechlm_st/ft_large_covost_enxx.sh $model_path $data_dir $lang tag400k微调后的模型统一保存在$mount/exp/finetune_covost。6.3 解码# speechlm/scripts/tune_speechlm_st/inference_base.sh model_path data_dir lang [gen-setdev] [beam_size5] bash speechlm/scripts/tune_speechlm_st/inference_base.sh $model_path $data_dir $lang dev # large 模型 bash speechlm/scripts/tune_speechlm_st/inference_large.sh $model_path $data_dir $lang dev从源码结构看ST 微调模型定义在 speechlm/speechlm/models/speechlm_st.py解码使用字符级目标词表示例中的spm_char_st_en_de.vocab做 beam searchbeam_size默认 5。7. 从清洗版 checkpoint 提取特征README 将全部推理相关代码合并到 SpeechLM.py并提供了移除非必要模块后的清洗版checkpointBase/H Base/P Large 三个。特征提取的完整流程直接来自 READMEimport torch import torch.nn.functional as F from SpeechLM import SpeechLMConfig, SpeechLM checkpoint torch.load(path/to/the/cleaned/checkpoint.pt) cfg SpeechLMConfig(checkpoint[cfg][model]) model SpeechLM(cfg) model.load_state_dict(checkpoint[model]) model.eval() wav_input_16khz torch.randn(1, 10000) normalize checkpoint[cfg][task][normalize] # False for base model, True for large model if normalize: wav_input_16khz F.layer_norm(wav_input_16khz[0], wav_input_16khz[0].shape).unsqueeze(0) # extract the representation of last layer rep model.extract_features(wav_input_16khz)[0] # extract the representation of each layer output_layer model.cfg.encoder_layers model.cfg.text_transformer.encoder.layers rep, layer_results model.extract_features(wav_input_16khz, output_layeroutput_layer, ret_layer_resultsTrue)[0] layer_reps [x.transpose(0, 1) for x in layer_results]这段代码与 SpeechLM.extract_features 的实现完全对应值得注意的细节有三点normalize必须与预训练时一致Large 模型配置中task.normalize: true对应extractor_mode: layer_normBase 为false因此 README 用checkpoint[cfg][task][normalize]从 checkpoint 自动读取对需要归一化的输入做逐样本layer_normoutput_layer是 1 起始的全局层号当output_layer超过cfg.encoder_layers时extract_features会先过语音编码器再把其输出经convert_embeddingsmix_with_unitFalse、use_pred_unitFalse送入unit_encoder并按return_all_hiddens收集单位编码器的各层隐藏态拼接进layer_results。因此取全部层表征时层号要写成encoder_layers text_transformer.encoder.layersP Base 为 6612P Large 为 121224ret_layer_resultsTrue时返回二元组(最终特征, [各层隐藏态])各层张量形状为(T, B, D)示例中的transpose(0, 1)即转成(B, T, D)。8. 从零预训练把三要素串起来综合前文从零复现一次 P Base 预训练需要满足三要素语音数据train_960.tsvwav manifest 由 4.1 节 HMM 流程得到的train_960.phn100 帧/秒对齐音素文本数据由 4.2 节脚本产出的train_text.phn-ltr.{phn,ltr}.{bin,idx}及dict.phn.txt/dict.ltr.txt词表命令data_dirdataset/LibriSpeech/phone_unit # 应包含 train_960.{tsv,phn} text_data_dirdataset/LibriLM/phone_unit/bin-idx # 应包含 train_text.phn-ltr.{phn,ltr}.{bin,idx} # Usage: speechlm/scripts/pretrain_speechlm/base_speechlmp.sh data_dir text_data_dir [mount$PWD] [world_size32] [update_freq1] bash speechlm/scripts/pretrain_speechlm/base_speechlmp.sh $data_dir $text_data_dirH Base 与 P Large 分别换成 base_speechlmh.shkm标签、label_rate50、train_text.km-ltr数据与 large_speechlmp.sh60k 小时 LibriLight 数据 Large 配置 speechlm_large_librilight.yaml。训练在 32 卡4 机 × 8 卡规模下max_update: 400000步收敛checkpoint 每 50k 步保留一次Baseupdate_freq用于梯度累积以模拟更大 batch。9. 小结与延伸阅读SpeechLM 的核心贡献可以概括为三句话用 HMM 对齐音素与文本→单位生成器把未配对文本转化为与语音同构的单位序列用joint_sc2t_pretraining任务把语音、配对文本、单语文本按帧率对齐地混在同一 batch 中做 masked unit modeling再用 CTC 微调与 ST 微调验证该表征在 ASR/翻译上的价值。仓库内值得继续深入的文件模型三件套speechlm.py、speechlm_ctcasr.py、speechlm_st.py、联合采样逻辑 joint_sc2t_pretrain.py 的resample_multi_modality_dataset、损失实现 speechlm_criterion.py以及 speechlm/README.md 中保留的全部权重下载链接与论文引用信息论文引用为 Zhang et al., 2022arXiv:2209.15329。【免费下载链接】unilmLarge-scale Self-supervised Pre-training Across Tasks, Languages, and Modalities项目地址: https://gitcode.com/GitHub_Trending/un/unilm创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询