NeMo 语音自监督预训练(SSL)配置完全指南:数据集、增强、对比损失与多任务 loss_list 实战

发布时间:2026/9/13 23:43:53
NeMo 语音自监督预训练(SSL)配置完全指南:数据集、增强、对比损失与多任务 loss_list 实战 NeMo 语音自监督预训练SSL配置完全指南数据集、增强、对比损失与多任务 loss_list 实战【免费下载链接】SpeechA scalable generative AI framework built for researchers and developers working on Large Language Models, Multimodal, and Speech AI (Automatic Speech Recognition and Text-to-Speech)项目地址: https://gitcode.com/GitHub_Trending/nem/Speech导读本文聚焦 NeMoSpeech语音自监督预训练Self-Supervised Pre-training, SSL的配置体系以 configs.rst 为骨架系统讲解 SSL 模型在数据集构建、预处理器、MaskedPatchAugmentation 增强、编码器架构、对比损失ContrastiveLoss以及多损失loss_list组合contrastive mlm / ctc / rnnt等方面的完整配置写法。读完本文你将能够独立编写一份可运行的 NeMo SSL 预训练配置并理解每一步配置背后的源码实现逻辑为后续将编码器迁移到 ASR 下游微调打下基础。一、SSL 配置文件概览与标准 ASR 配置的关系在 NeMo 中语音自监督预训练模型的配置文件如 conformer_ssl.yaml在整体组织上与标准 ASR 训练配置高度一致——都包含model、trainer、exp_manager三大顶层块其中trainerPyTorch Lightning 训练器与exp_manager实验管理器的通用配置方式可参考 核心配置文档。与 ASR 监督训练不同的是SSL 配置需要额外关注三个专属环节训练/验证数据集的时长控制对比损失要求 batch 内所有样本被 mask 的 patch 数量一致因此必须控制样本时长分布谱图级增强MaskedPatchAugmentation以 patch 为单位对语谱图进行 mask解码器与损失配置自监督解码器体积很小、且会在迁移微调时被丢弃其配置方式与 ASR 头完全不同。二、数据集配置为对比损失控制时长分布2.1 为什么 SSL 数据集配置与 ASR 不同自监督数据集配置与标准 ASR 训练大体相同通用字段可参考 ASR 数据集配置核心差异在于执行对比损失时需要为 batch 中所有 utterance 掩蔽等量的 patch 数。这意味着应尽量避免单个 batch 内样本时长差异过大——否则短样本可掩蔽的 patch 数不足长样本又浪费算力。NeMo 提供三种手段方式一min_duration直接过滤短样本。在数据集配置中设置min_duration所有低于该时长的 utterance 会被直接丢弃。适合剔除这些样本对总数据量影响不大的场景。方式二random_segment扰动切段。若数据集中存在大量时长超过约 16 秒、且长度参差不齐的长音频可以在运行时从完整样本中随机切出固定长度的片段低于片段长度的样本会被 padding。配置如下augmentor: random_segment: prob: 1.0 duration_sec: 16 # 指定目标片段时长方式三Bucketing。通过分桶bucketing让同一 batch 内样本时长接近具体机制参见 NeMo 文档中 Bucketing 相关章节bucketing_strategy、bucketing_batch_size等参数在下面的完整示例中体现。2.2 完整的 SSL train / validation 数据集配置示例model: train_ds: manifest_filepath: ??? sample_rate: ${model.sample_rate} batch_size: 16 # 显存充足时可调大 shuffle: true num_workers: 8 pin_memory: false use_start_end_token: true trim_silence: false max_duration: 16.7 min_duration: 8.0 # tarred 数据集 is_tarred: false tarred_audio_filepaths: null shuffle_n: 2048 # bucketing 参数 bucketing_strategy: synced_randomized bucketing_batch_size: null validation_ds: manifest_filepath: ??? sample_rate: ${model.sample_rate} batch_size: 16 # 显存充足时可调大 shuffle: false num_workers: 8 pin_memory: true use_start_end_token: false min_duration: 8.0要点说明use_start_end_token在训练集开启、验证集关闭用于区分句首/句尾边界max_duration: 16.7与min_duration: 8.0共同将样本框定在 816.7 秒区间配合random_segment或 bucketing 保证 batch 内时长齐整若使用 tarred 数据集需要打开is_tarred: true并指定tarred_audio_filepathsshuffle_n控制 tarred 场景下的 shuffle 窗口大小bucketing_strategy: synced_randomized是带同步随机化的分桶策略bucketing_batch_size: null表示继承batch_size。三、预处理器配置MFCC / Mel 谱图特征预处理器负责计算 MFCC 或 mel 语谱图作为模型输入。其写法与 ASR 完全一致可参考 NeMo ASR 预处理器配置章节。SSL 场景推荐使用AudioToMelSpectrogramPreprocessor参考 conformer_ssl.yamlpreprocessor: _target_: nemo.collections.asr.modules.AudioToMelSpectrogramPreprocessor sample_rate: ${model.sample_rate} normalize: per_feature window_size: 0.025 window_stride: 0.01 window: hann features: 80 n_fft: 512 log: true frame_splicing: 1 dither: 0.00001 pad_to: 16 pad_value: 0.0其中features: 8080 维 mel 特征会被ContrastiveLoss的in_dim引用${model.preprocessor.features}修改特征维度时务必同步检查损失配置。四、增强配置MaskedPatchAugmentation 谱图掩蔽自监督预训练官方推荐的谱图增强类是MaskedPatchAugmentation实现见 audio_preprocessing.py。它将 utterance 切分为固定大小的 patch再掩蔽固定数量或固定比例的 patch同时可通过freq_masks/freq_width叠加频带掩蔽内部复用 SpecAugment。spec_augment: _target_: nemo.collections.asr.modules.MaskedPatchAugmentation patch_size: 48 # 单个 patch 的大小 mask_patches: 0.5 # 掩蔽 patch 的比例也可填固定整数数量 freq_masks: 3 # 切掉三个频带 freq_width: 20 # 每个频带最大宽度 20源码中的关键语义audio_preprocessing.pymask_patches 1时被解释为固定数量的 patch取整0 mask_patches 1时被解释为占总 token 的比例向上取整负值会直接抛出ValueError同一 batch 内所有样本保证被掩蔽等量的时间步这正是对比损失所依赖的性质若min_len patch_size * mask_patches会自动将mask_patches收缩为min_len // patch_size避免越界频率掩蔽通过内部构造SpecAugment(freq_masks, time_masks0, freq_width, time_width0)实现因此与 SpecAugment 的频带掩蔽行为一致。4.1 负样本数量与掩蔽步数的配比约束若对比损失采用仅从同一 utterance 的被掩蔽步中采样负样本sample_from_same_utterance_only: true且sample_from_non_masked: false必须保证每条 utterance 中被掩蔽的步数足够多否则无法采样出足量负样本。文档给出的工程经验编码器 stride 为 4x、想采样 100 个负样本时需要400 个以上的被掩蔽步使用默认patch_size: 48时mask_patches至少要设为9若使用比例形式掩蔽mask_patches 1还需确保样本最小时长对应的 patch 总数足够支撑所需负样本数。五、模型架构配置可复用的编码器 可丢弃的解码器SSL 配置文件需完整描述模型架构。自监督预训练通常只训练编码器之后将其复用于下游微调因此编码器可按 ASR 模型的方式配置——任意 ASR 编码器Conformer、FastConformer 等均可搭配任意预训练方法在相同模型规模下官方经验是使用 Conformer 能获得更好的下游效果。与编码器不同解码器与对应损失是自监督预训练专属的且体积很小迁移微调时可直接丢弃。以ConformerEncoder为例见 conformer_ssl.yaml关键参数包括d_model、n_layers、subsampling推荐stridingsubsampling_factor: 4、self_attention_model: rel_pos、conv_kernel_size等。5.1 最基础的对比任务配置编码器 stride 4x最基础的预训练方式即 wav2vec 2.0 采用的对比学习任务。对于 stride 为 4x 的编码器解码器与损失配置如下decoder_out: 128 decoder: _target_: nemo.collections.asr.modules.ConvASRDecoderReconstruction feat_in: ${model.encoder.d_model} feat_hidden: 128 feat_out: ${model.decoder_out} stride_layers: 0 # 若 loss.combine_time_steps 小于编码器 stride # 则需要在解码器中补充相应数量的 stride_layers #此处 stride 与 combine_time_steps 均为 4 non_stride_layers: 0 loss: _target_: nemo.collections.asr.losses.ContrastiveLoss in_dim: ${model.preprocessor.features} proj_dim: ${model.decoder_out} combine_time_steps: 4 # 多少个语谱图时间步组合成一个对比任务的目标/表征 quantized_targets: true # 使用量化器还是线性层 codebook_size: 300 # 单个 codebook 的大小 num_groups: 2 # 量化器使用的 codebook 数量 num_negatives: 100 # 每个目标采样的负样本数 sample_from_same_utterance_only: true # 负样本是否只从同一条 utterance 中采样 sample_from_non_masked: false # 负样本是否从非掩蔽步中采样这里combine_time_steps: 4表示把输入语谱图的 4 个时间步合并为一个token用于损失计算与编码器 4x stride 对应。ContrastiveLoss的完整实现见 contrastive.py其核心逻辑为对掩蔽步的表征与1 个正样本 N 个负样本计算余弦相似度再以交叉熵形式让模型从负样本中识别出真正的目标表征sample_from_same_utterance_only决定负样本在单句内采样还是跨句采样sample_from_non_masked决定是否允许从非掩蔽步采样。量化器方面quantized_targets: true时会内部构造GumbelVectorQuantizer见 contrastive.py其dim in_dim * combine_time_stepsnum_vars codebook_sizegroups num_groups并带有温度退火机制quantizer_temp_start/quantizer_temp_min/quantizer_temp_decay等超参数。5.2 stride 8x 编码器用 stride_layer 对齐时间步combine_time_steps与编码器 stride 可以不同。若编码器为 FastConformerstride 8x需要给解码器加一层stride_layers配合stride_tranpose: true使用转置卷积把 8x 的步长降回 4xdecoder: _target_: nemo.collections.asr.modules.ConvASRDecoderReconstruction feat_in: ${model.model_defaults.enc_final} feat_hidden: 128 feat_out: ${model.model_defaults.decoder_out_channels} stride_layers: 1 # 若 loss.combine_time_steps 小于编码器 stride则需要补充相应数量的 stride_layers #此处 stride 为 8、combine_time_steps 为 4因此加 1 层 non_stride_layers: 0 stride_tranpose: true # stride 层是否使用转置卷积 loss: _target_: nemo.collections.asr.losses.ContrastiveLoss in_dim: *n_mels proj_dim: ${model.model_defaults.decoder_out_channels} combine_time_steps: 4 # 多少个语谱图时间步组合成一个对比任务的目标/表征 quantized_targets: false # 使用量化器还是线性层 sample_from_same_utterance_only: true sample_from_non_masked: false注意此处quantized_targets: false即改用线性层target_proj nn.Linear(in_dim * combine_time_steps, proj_dim)见 contrastive.py生成目标表征。六、多损失组合loss_list配置体系将对比损失与其他损失如 MLM 掩蔽语言建模损失类似 W2V-Bert 的做法结合通常更有益。此时不再写单个decoderloss而是通过loss_list声明任意数量的解码器-损失对。loss_list在 ssl_models.py 中被解析每个命名子配置可包含以下字段且均带默认值字段含义默认值decoder解码器配置_target_类与参数必填loss对应的损失配置_target_类与参数必填loss_alpha该损失的加权系数1.0targets_from_loss从哪个对比损失提取标签当 manifest 中没有标签、而该损失又需要标签时必填Nonetranspose_encoded是否在送入该损失前对编码特征做转置Falsestart_step从哪个全局训练步开始启用该解码器损失0output_from_layer从编码器哪个中间层提取特征送入该解码器null表示使用最后一层输出null从 ssl_models.py 的源码实现看训练时SpeechSSLModel会按output_from_layer从编码器对应层提取特征必要时先transpose_encoded再根据targets_from_loss从指定对比损失处获取伪标签最终将各损失乘以loss_alpha求和start_step通过trainer.global_step self.start_step[name]判断该损失当前是否激活。这为先对比预训练、再逐步叠加监督损失的训练策略提供了精确的调度能力。6.1 示例contrastive mlm 组合以下配置中MLM 损失直接使用对比损失量化模块产出的伪标签因此对比损失的quantized_targets必须为truedecoder_out: 128 loss_list: contrastive: decoder: _target_: nemo.collections.asr.modules.ConvASRDecoderReconstruction feat_in: ${model.encoder.d_model} feat_hidden: 128 # 解码器隐藏层特征维度 feat_out: ${model.decoder_out} stride_layers: 0 # 若 loss.combine_time_steps 小于编码器 stride则需要补充相应数量的 stride_layers #此处 stride 与 combine_time_steps 均为 4 non_stride_layers: 0 loss: _target_: nemo.collections.asr.losses.ContrastiveLoss in_dim: ${model.preprocessor.features} proj_dim: ${model.decoder_out} combine_time_steps: 4 # 多少个语谱图时间步组合成一个对比任务的目标/表征 quantized_targets: true # 是否使用量化器或线性层 #需要量化器为其他损失提取伪标签 codebook_size: 300 num_groups: 2 sample_from_same_utterance_only: true # 负样本是否只从同一条 utterance 中采样 sample_from_non_masked: false # 负样本是否从非掩蔽步中采样 mlm: decoder: _target_: nemo.collections.asr.modules.ConvASRDecoder feat_in: ${model.encoder.d_model} num_classes: 90000 # 需等于对比损失中的 codebook_size^num_groups loss: _target_: nemo.collections.asr.losses.MLMLoss combine_time_steps: 4 targets_from_loss: contrastive # 该损失需要标签可从 manifest 获取也可取自量化对比损失 loss_alpha: 1000. # 该损失相对其他损失的加权倍数 transpose_encoded: false # 是否转置输入取决于送入解码器的层 start_step: 0 # 该损失从哪个全局步开始启用 # 训练足够长时可设更高的值有助于早期训练稳定性 output_from_layer: null # 如需使用非最后一层编码器输出可在此指定层名要点mlm.decoder.num_classes必须等于codebook_size ^ num_groups示例中 300² 90000这是量化器组合出的伪标签类别总数targets_from_loss: contrastive让 MLM 损失从量化对比损失中提取标签这是 manifest 无标签时多任务组合的必要条件loss_alpha: 1000.表明 MLM 损失相对对比损失有更高的权重MLM 每个 token 的损失量级通常更小。6.2 示例contrastive ctc 组合与reduce_ids也可以将 CTC 等需要标签的监督损失与对比损失组合。与 MLM 不同的是CTC/RNNT 不要求目标与步一一对齐因此可同时把对比损失的reduce_ids设为true——它会把连续重复的量化 id 合并为单个 id源码实现见 contrastive.py 的torch.unique_consecutive逻辑decoder_out: 128 loss_list: contr: decoder: _target_: nemo.collections.asr.modules.ConvASRDecoderReconstruction feat_in: ${model.encoder.d_model} feat_hidden: 128 feat_out: ${model.decoder_out} stride_layers: 0 non_stride_layers: 0 loss: _target_: nemo.collections.asr.losses.ContrastiveLoss in_dim: ${model.preprocessor.features} proj_dim: ${model.decoder_out} combine_time_steps: 4 quantized_targets: true codebook_size: 300 num_groups: 2 sample_from_same_utterance_only: true sample_from_non_masked: false reduce_ids: true ctc: decoder: _target_: nemo.collections.asr.modules.ConvASRDecoder feat_in: ${model.encoder.d_model} num_classes: 90000 loss: _target_: nemo.collections.asr.losses.CTCLossForSSL num_classes: 90000 targets_from_loss: contr start_step: 3000注意start_step: 3000CTC 损失在训练 3000 步之后才被激活让对比损失先收敛形成稳定的表征与伪标签再叠加 CTC 目标。6.3 示例contrastive rnnt 组合RNNT 组合需要配置完整的预测网络prednet与联合网络joint并通过RNNTDecoderJointSSL将二者包装为 SSL 解码器损失使用RNNTLossForSSLdecoder_out: 128 loss_list: contr: decoder: _target_: nemo.collections.asr.modules.ConvASRDecoderReconstruction feat_in: ${model.encoder.d_model} feat_hidden: 128 feat_out: ${model.decoder_out} stride_layers: 0 non_stride_layers: 0 loss: _target_: nemo.collections.asr.losses.ContrastiveLoss in_dim: ${model.preprocessor.features} proj_dim: ${model.decoder_out} combine_time_steps: 4 quantized_targets: true codebook_size: 24 sample_from_same_utterance_only: true sample_from_non_masked: false reduce_ids: true rnnt: decoder: _target_: nemo.collections.asr.modules.RNNTDecoderJointSSL decoder: _target_: nemo.collections.asr.modules.RNNTDecoder normalization_mode: null # 目前仅支持 null 以便导出 random_state_sampling: false # 随机状态采样https://arxiv.org/pdf/1910.11455.pdf blank_as_pad: true # 必须开启以支持 RNNT 模型导出与高效推理 vocab_size: 576 prednet: pred_hidden: 640 pred_rnn_layers: 1 t_max: null dropout: 0.1 joint: _target_: nemo.collections.asr.modules.RNNTJoint log_softmax: null # null 会根据 CPU/GPU 设备自动设置 preserve_memory: false # 开启会显著拖慢训练但可节省部分显存 experimental_fuse_loss_wer: false jointnet: encoder_hidden: 512 pred_hidden: 640 joint_hidden: 640 activation: relu dropout: 0.1 num_classes: 576 loss: _target_: nemo.collections.asr.losses.RNNTLossForSSL num_classes: 576 targets_from_loss: contr start_step: 1000此处对比损失的codebook_size: 24、num_groups: 2组合伪标签类别为 24² 576与 RNNT 的vocab_size/num_classes保持一致。6.4 进阶从编码器中间层提取特征的多损失组合还可让多个损失分别使用编码器不同中间层的输出相关方法可参考论文引用 configs.rst 中的 ssl_inter 相关工作。下面的示例组合了 1 个对比损失与 3 个 MLM 损失后者分别使用编码器第 6 层、第 12 层与最终层输出通过output_from_layer指定层名配合transpose_encoded: true转置特征decoder_out: 128 loss_list: contr: decoder: _target_: nemo.collections.asr.modules.ConvASRDecoderReconstruction feat_in: ${model.encoder.d_model} feat_hidden: 128 feat_out: ${model.decoder_out} stride_layers: 0 non_stride_layers: 0 loss: _target_: nemo.collections.asr.losses.ContrastiveLoss in_dim: ${model.preprocessor.features} proj_dim: ${model.decoder_out} combine_time_steps: 4 quantized_targets: true codebook_size: 300 sample_from_same_utterance_only: true sample_from_non_masked: false loss_alpha: 5. mlm: decoder: _target_: nemo.collections.asr.modules.ConvASRDecoder feat_in: ${model.encoder.d_model} num_classes: 90000 loss: _target_: nemo.collections.asr.losses.MLMLoss combine_time_steps: 4 targets_from_loss: contr loss_alpha: 1000. mlm_2: decoder: _target_: nemo.collections.asr.modules.ConvASRDecoder feat_in: ${model.encoder.d_model} num_classes: 90000 loss: _target_: nemo.collections.asr.losses.MLMLoss combine_time_steps: 4 targets_from_loss: contr loss_alpha: 300. output_from_layer: layers.5 transpose_encoded: true mlm_3: decoder: _target_: nemo.collections.asr.modules.ConvASRDecoder feat_in: ${model.encoder.d_model} num_classes: 90000 loss: _target_: nemo.collections.asr.losses.MLMLoss combine_time_steps: 4 targets_from_loss: contr loss_alpha: 300. output_from_layer: layers.11 transpose_encoded: true这里各损失的loss_alpha不尽相同5.0 / 1000.0 / 300.0 / 300.0体现出对比损失为主、浅层与深层 MLM 辅助的权重设计思路。output_from_layer的取值如layers.5、layers.11与编码器内部模块命名直接相关需与所用编码器结构对应。七、可运行的完整参考conformer_ssl.yamlNeMo 仓库提供了开箱即用的 SSL 预训练参考配置 conformer_ssl.yaml对应约 120M 参数的 Conformer 编码器其要点编码器使用ConformerEncoderd_model: 512、n_layers: 18、n_heads: 8、subsampling: striding、subsampling_factor: 4损失组合为contrastive mlm即上文 6.1 的完整形态优化器采用adamw学习率5.0、betas: [0.9, 0.98]、weight_decay: 1e-3配合NoamAnnealing调度器与warmup_steps: 25000——默认学习参数针对2K 有效 batch size调优若使用更小的有效 batch size需要重调学习参数或增大accumulate_grad_batches该文件头部注释还给出了 Small / Medium / Large 三种 Conformer-SSL 变体的规模-学习率对照表trainer侧注意benchmark: false变长语音输入下开启会拖慢训练、enable_checkpointing: False与logger: false均由exp_manager提供exp_manager通过checkpoint_callback_params.monitor: val_loss监控验证损失保存最优检查点save_top_k: 5并可配置 WB logger。八、总结与迁移要点回顾 NeMo SSL 配置的核心逻辑数据集层用min_duration/random_segment/ bucketing 三种手段控制 batch 内时长一致性为对比损失铺路增强层用MaskedPatchAugmentation按 patch 掩蔽谱图保证 batch 内掩蔽步数一致并按负样本数校核掩蔽数量如 4x stride、100 负样本、patch_size 48 时需要mask_patches 9架构层编码器完全复用 ASR 配置解码器/损失为 SSL 专属且迁移时可丢弃损失层单损失直接用decoder loss多损失用loss_list组合通过targets_from_loss、loss_alpha、start_step、output_from_layer、transpose_encoded五个字段精确调度每个损失组合监督损失CTC/RNNT时为对比损失开启reduce_ids以合并连续重复 id并让num_classes/vocab_size与量化器伪标签类别数codebook_size ^ num_groups保持一致。预训练完成后只需丢弃 SSL 解码器与损失将训练好的编码器权重加载到 ASR 模型中即可进行下游微调这正是以 SSL 配置为起点、以编码器复用为核心的 NeMo 自监督预训练实践路径。更多模型、数据集与结果信息可参阅 SSL 模块总览、模型说明 与 数据集说明。【免费下载链接】SpeechA scalable generative AI framework built for researchers and developers working on Large Language Models, Multimodal, and Speech AI (Automatic Speech Recognition and Text-to-Speech)项目地址: https://gitcode.com/GitHub_Trending/nem/Speech创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考