ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

基于 SpeechBrain 与 Libri-Light 的 BEST-RQ 自监督预训练实战指南(离线与流式)

基于 SpeechBrain 与 Libri-Light 的 BEST-RQ 自监督预训练实战指南(离线与流式) 基于 SpeechBrain 与 Libri-Light 的 BEST-RQ 自监督预训练实战指南离线与流式【免费下载链接】speechbrainA PyTorch-based Speech Toolkit项目地址: https://gitcode.com/GitHub_Trending/sp/speechbrainBEST-RQBErt-based Speech pre-Training with Random-projections Quantizer是一种免梯度量化的自监督语音预训练方法SpeechBrain 在recipes/Libri-Light/self-supervised-learning/BEST-RQ目录中提供了完整可复现的训练配方基于 Libri-Light 数据集small / medium / large 三个规模训练一个约 94M 参数的小型 BEST-RQ 模型同时支持离线训练与基于 Dynamic Chunk Training 的流式训练。读完本文你将掌握 Libri-Light 的 VAD 切分与数据准备流程、单卡与多卡torchrun训练命令、BEST-RQ 核心超参数的含义以及如何用产出的 checkpoint 微调到下游 ASR 任务。配方概览目录结构与运行入口该配方位于 recipes/Libri-Light/self-supervised-learning/BEST-RQ 目录包含三个核心文件文件作用README.md数据准备与训练说明文档librilight_prepare.py将 VAD 后的 Libri-Light 音频扫描成 CSV 清单的数据准备脚本train.py训练入口定义BestRQBrain训练逻辑hparams/BEST-RQ.yaml全部超参数、模型结构与优化器配置训练流水线可概括为下载 Libri-Light → 用官方cut_by_vad.py做 VAD 切分 → 准备 dev 集 →train.py自动扫描音频并生成 CSV → 训练 BEST-RQ 模型。数据准备阶段会在主进程上自动执行见 train.py 中的run_on_main(prepare_librilight, ...)调用无需手动单独运行。第一步下载 Libri-Light 数据并完成 VAD 切分Libri-Light 是 Facebook Research 发布的大规模无标注英文语音数据集官方提供了 small / medium / large 三个规模的分片。README 要求先从其官方数据准备工具下载数据然后 git clone Libri-Light 仓库使用仓库内的data_preparation/cut_by_vad.py脚本对每个分片做 VAD 切分。以 small 分片、目标切分长度 20 秒为例python cut_by_vad.py \ --input_dir path_to_Libri-Light/small \ --output_dir Libri-Light_VAD/small_vad \ --target_len_sec 20medium 与 large 分片同理python cut_by_vad.py \ --input_dir path_to_Libri-Light/medium \ --output_dir Libri-Light_VAD/medium_vad \ --target_len_sec 20 python cut_by_vad.py \ --input_dir path_to_Libri-Light/large \ --output_dir Libri-Light_VAD/large_vad \ --target_len_sec 20使用时有两点需要注意多分片必须输出到同一父目录如果同时使用多个分片务必把每个分片的 VAD 结果保存到同一个文件夹如Libri-Light_VAD/下后续--data_folder直接指向该父目录--vad_splits指定其中的子目录名。large 分片耗时以天计下载与 VAD 切分 large 分片可能需要数天时间请预留充足的磁盘空间与耐心。从源码看librilight_prepare.py 中的check_librilight_folders会逐一校验data_folder下每个 split 子目录是否存在若缺失会抛出OSError因此 VAD 输出目录的命名如small_vad必须与--vad_splits参数完全一致。第二步准备验证集dev setLibri-Light 本身没有官方 dev 划分README 明确建议借用其他数据集的 dev 集来监控训练过程例如LibriSpeech dev-clean——它属于域内in-domain数据是理想的验证集。实践中你只需把任意一批 wav/flac 文件放进一个文件夹把该文件夹路径作为--dev_folder传入即可。在数据准备阶段librilight_prepare.py 会递归扫描dev_folder下所有.flac文件并生成dev.csv对应 YAML 中的valid_csv。验证时不会做数据增强且compute_objectives会在验证阶段额外统计 masked frame 的预测准确率并记录到日志中见 train.py。第三步运行训练单卡与多卡数据准备完成后即可启动训练python train.py hparams/BEST-RQ.yaml \ --data_folder Libri-Light_VAD/ \ --dev_folder /path/to/LibriSpeech/dev-clean \ --vad_splits[small_vad]由于 Libri-Light 数据量很大官方推荐使用多 GPU 训练。例如 8 卡torchrun --nproc_per_node8 train.py hparams/BEST-RQ.yaml \ --data_folder Libri-Light_VAD/ \ --dev_folder /path/to/LibriSpeech/dev-clean \ --vad_splits[small_vad]--vad_splits直接决定训练数据量不同组合对应的时长如下--vad_splits取值训练数据量[small_vad]约 600 小时[small_vad, medium_vad]约 6k 小时[small_vad, medium_vad, large_vad]约 60k 小时这些值同样记录在 hparams/BEST-RQ.yaml 的注释中。多分片时prepare_librilight会为每个 split 单独生成 CSV再通过merge_csvs合并为train.csvmerge_lst与merge_name均由vad_splits与train.csv传入见 train.py。需要说明的是该配置基于 8 张 V100 GPU 设定seconds_per_batch: 400、grad_accumulation_factor: 2若你的硬件条件不同应相应调整 batch 相关参数。此外训练入口在 train.py 头部注释中还提示可通过--find_unused_parameters选项运行DDP 场景下有用。核心超参数解析BEST-RQ.yamlrecipes/Libri-Light/self-supervised-learning/BEST-RQ/hparams/BEST-RQ.yaml 是本配方的总控台下面按模块逐一拆解。运行与日志参数默认值说明seed1000随机种子通过speechbrain.utils.seed_everything应用data_folder!PLACEHOLDERVAD 后的 Libri-Light 父目录dev_folder!PLACEHOLDER验证集目录如 LibriSpeech dev-cleanvad_splits!PLACEHOLDER训练分片列表train_csv/valid_csvoutput_folder/train.csv、dev.csv自动生成的 CSV 路径skip_prepFalse为 True 时跳过数据准备log_interval500每 N 个优化器 step 记录一次训练日志max_grad_norm10梯度裁剪阈值precisionfp16支持fp16/bf16/fp32data_folder、dev_folder、vad_splits在 YAML 中都是!PLACEHOLDER正是要通过命令行覆盖传入的三个参数。训练轮数与停止条件number_of_epochs: 3000 optimizer_step_limit: 300000训练会在number_of_epochs3000 epoch与optimizer_step_limit30 万优化器 step两者中先达到者停止。这是大规模自监督预训练的典型设置以 step 数而非 epoch 数作为主控目标。数据加载与批处理# This setup is for 8 V100. seconds_per_batch: 400 train_num_buckets: 150 grad_accumulation_factor: 2seconds_per_batch: 400每个 batch 的目标总音频秒数由DynamicBatchSampler动态组批见 train.py。这是 SpeechBrain 推荐的基于时长的动态批处理方式可避免因句长差异导致的 GPU 浪费。train_num_buckets: 150动态批处理的桶数量。grad_accumulation_factor: 2梯度累积因子等效于把 batch size 放大 2 倍。avoid_if_longer_than: 60.0/avoid_if_shorter_than: 2.0训练集中剔除时长超过 60 秒或不足 2 秒的音频通过filtered_sorted实现见 train.py。测试阶段不使用动态批处理固定batch_size: 8num_workers均为 4。特征与前处理# Mel-Filterbank parameters sample_rate: 16000 n_fft: 400 n_mels: 80 hop_length: 10 pad_to_divisible_by: 416kHz 采样率、400 点 FFT、80 维 Mel 滤波器组、10ms 帧移由speechbrain.lobes.features.Fbank计算并按句sentence做InputNormalizationnorm_type: sentence。pad_to_divisible_by: 4是 BEST-RQ 的一个关键细节BEST-RQ 的量化器会把相邻帧**堆叠stack**后再量化时间维需要能被堆叠因子整除。由于 CNN 前端在时间维上做了 4 倍降采样输入量化器的特征也必须做 4 倍降采样因此train.py中的pad_feats会把时间维 padding 到 4 的倍数见 train.py。掩码Masking参数# Masking parameters mask_length: 4 mask_prob: 0.15 noise_mean: 0 noise_std: 0.1mask_length: 4每个掩码覆盖的连续帧数。mask_prob: 0.15某帧作为掩码起点的概率。注意compute_mask的实现语义mask_prob 是一帧开启一个掩码的概率而不是被掩码帧的比例。从 speechbrain/lobes/models/BESTRQ.py 的注释与实现看掩码数量为int(mask_prob * min_sample_len random.random())掩码起点通过randperm在最短样本内随机选取并排序若某句长 100 帧、mask_prob0.15、mask_length4则约有 100×0.15×4 60% 的帧被掩码。noise_mean: 0/noise_std: 0.1被掩码区域替换为高斯噪声的均值与标准差。compute_forward中通过torch.normal生成同形状噪声并执行feats[:, mask, :] noise见 train.py这与 BEST-RQ 论文中用随机噪声而非 [MASK] 标记替换的做法一致。流式与 Dynamic Chunk Trainingstreaming: True # controls all Dynamic Chunk Training chunk size left context mechanisms dynchunktrain_config_sampler: !new:speechbrain.utils.dynamic_chunk_training.DynChunkTrainConfigRandomSampler chunkwise_prob: 0.6 chunk_size_min: 8 chunk_size_max: 32 limited_left_context_prob: 0.75 left_context_chunks_min: 2 left_context_chunks_max: 32 valid_config: !new:speechbrain.utils.dynamic_chunk_training.DynChunkTrainConfig chunk_size: 8 left_context_size: 16streaming: True会启用 Dynamic Chunk Training动态分块训练机制训练时以一定概率限制注意力范围并随机采样分块大小使模型在推理时天然支持流式chunk 级解码。各参数含义chunkwise_prob: 0.6一个 batch 中限制注意力并随机采样分块大小的概率。chunk_size_min/max: 8/32训练时随机采样的分块大小范围。limited_left_context_prob: 0.75处于分块训练时进一步限制左侧上下文为随机个 chunk 的概率。left_context_chunks_min/max: 2/32左侧上下文以 chunk 数计的随机范围。valid_config验证阶段固定使用的分块配置chunk 8 左上下文 16。这些配置对象定义于 speechbrain/utils/dynamic_chunk_training.pyDynChunkTrainConfig与DynChunkTrainConfigRandomSampler。YAML 注释特别说明就当前架构在 LibriSpeech 上的实验来看streaming: True与streaming: False的非流式准确率非常接近因此开启流式训练几乎不损失离线性能。train.py中通过self.hparams.dynchunktrain_config_sampler(stage)按阶段采样配置并传入EncoderWrapper的dynchunktrain_config参数见 train.py。模型结构约 94M 参数# Transformer d_model: 576 nhead: 8 num_encoder_layers: 12 num_decoder_layers: 0 d_ffn: 2048 transformer_dropout: 0.1 activation: torch.nn.GELU output_neurons: 5000 encoder_layerdrop: 0.00 # quantizer (codebook cb) parameters p_input: 320 cb_dim: 16 cb_vocab: 8192整体架构为Conformer Encoder Random Projection Quantizer由四个模块串联CNNConvolutionFrontEndspeechbrain.lobes.models.convolution.ConvolutionFrontEnd2 个 block、每 block 1 层卷积输出通道 (128, 32)卷积核 (3, 3)步长 (2, 2)时间维整体 4 倍降采样无残差连接。TransformerTransformerASR 的编码器部分d_model576、nhead8、12 层 Conformer 编码器、0 层解码器、d_ffn2048、GELU 激活、相对位置多头注意力attention_type: RelPosMHAXL、normalize_before: True。通过EncoderWrapper包装以只运行编码器见 hparams/BEST-RQ.yaml。QuantizerRandomProjectionQuantizerinput_dim32080 mel × 4 帧堆叠、cb_dim16、cb_vocab8192。其实现位于 speechbrain/nnet/quantisers.py投影矩阵P用 Xavier 初始化并注册为 buffer对应论文 Section 3.1码本CB用torch.randn生成后做 L2 归一化前向时对输入做F.normalize(x P)后与码本计算距离并argmin得到离散 token 索引——整个过程不涉及梯度回传这就是 BEST-RQ免梯度量化的核心。linear把编码器输出d_model576映射到码本词表大小cb_vocab8192输出 logits 与量化 target 计算交叉熵。训练目标为 masked 区域的交叉熵分类损失。compute_forward的完整流程train.py为读 batch 与 mask → 计算 fbank 并归一化训练阶段可附加增强→ 按 4 倍堆叠后经 Quantizer 得到 target → 用高斯噪声替换掩码帧 → CNN 降采样 → Conformer 编码 → 线性映射 → 只在掩码区域计算 logits 与 targets 的交叉熵。优化器与学习率调度lr: 0.0008 optimizer: torch.optim.AdamW lr: !ref lr betas: (0.9, 0.98) eps: 0.000000001 weight_decay: 0.01 noam_annealing: !new:speechbrain.nnet.schedulers.NoamScheduler lr_initial: !ref lr n_warmup_steps: 25000使用 AdamW 优化器β(0.9, 0.98)、ε1e-9、weight_decay0.01搭配Noam 学习率调度器warmup 25000 步在每次fit_batch后通过noam_annealing(self.optimizer)更新学习率见 train.py。Checkpointer 会保存模型、Noam 调度器、归一化器、epoch counter、量化器与线性层并在每个 epoch 结束时按验证损失保留最近 4 个 checkpoint见 train.py。数据准备脚本的工程细节librilight_prepare.py 的职责是把 VAD 后的音频目录转成 SpeechBrain 标准的 CSV 清单ID, duration, wav三列。几个值得注意的实现细节并行扫描通过parallel_map来自speechbrain.utils.parallel并行读取 FLAC 元数据read_audio_info得到帧数与采样率从而算出时长chunk_size8192以限制主线程 CPU 瓶颈parallel_map保证输出顺序与输入一致。断点续跑skip()检测各 split 的 CSV 是否已存在存在则整体跳过准备阶段create_csv内部对已存在的 CSV 也直接返回避免重复劳动。训练中断后重跑不会重复扫描数万条音频。时长过滤后的动态组批DynamicItemDataset.from_csv加载 CSV 后用duration作为排序与组批依据并通过DynamicBatchSampler(seconds_per_batch400, ...)控制每个 batch 的音频总时长见 train.py。自定义 collatebrq_mask_collate_fn在组 batch 时同步生成 BEST-RQ 掩码speechbrain/lobes/models/BESTRQ.py。它需要知道特征提取后的输出长度由get_output_lengths按input_lengths // (sr * hop_length / 1000) 1估算并基于 batch 内最短样本决定掩码数量——因为掩码起点只能在所有样本都有效的时间范围内随机选取若 batch 内句长差异悬殊实际被掩码的帧占比会受影响这是训练时需要注意的一点。预训练后的微调FinetuningBEST-RQ 预训练产出的 checkpoint 是标准 PyTorch checkpoint可直接用于下游任务微调。README 推荐参考 LibriSpeech ASR/CTC 配方recipes/LibriSpeech/ASR/CTC进行语音识别微调——该配方演示了如何加载此类 checkpoint你也可以仿照它把 BEST-RQ 的编码器权重即插即用到任意感兴趣的任务中只需相应修改 YAML 与 train.py 即可。checkpoint 中保存的 recoverables 包括modelCNN EncoderWrapper、noam_scheduler、normalizer、counterepoch counter、quantizer与linear见 hparams/BEST-RQ.yaml。微调时通常只需取用model中的编码器部分量化器与线性层只在预训练阶段使用。小结本文完整梳理了 SpeechBrain 中 BEST-RQ 预训练配方的全流程从 Libri-Light 下载与 VAD 切分、dev 集选择到单卡/多卡训练命令再到 YAML 中超参数与模型结构的逐项解析并结合train.py、librilight_prepare.py、RandomProjectionQuantizer与brq_mask_collate_fn等源码说明了掩码生成、随机投影量化、动态分块训练与动态组批等关键机制的底层实现。按照本指南你可以从零开始复现约 600 小时small到 60k 小时large数据规模下的 BEST-RQ 自监督预训练并将预训练模型无缝迁移到下游 ASR 任务。【免费下载链接】speechbrainA PyTorch-based Speech Toolkit项目地址: https://gitcode.com/GitHub_Trending/sp/speechbrain创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表