用 SpeechBrain 在 VoiceBank 上训练音素级 CTC 声学模型(CRDNN 实战指南)
2026/9/15 19:47:04 网站建设 项目流程

用 SpeechBrain 在 VoiceBank 上训练音素级 CTC 声学模型(CRDNN 实战指南)

【免费下载链接】speechbrainA PyTorch-based Speech Toolkit项目地址: https://gitcode.com/GitHub_Trending/sp/speechbrain

本篇技术指南围绕 SpeechBrain 仓库中的recipes/Voicebank/ASR/CTC配方展开,系统讲解如何基于 VoiceBank(Noisy-VCTK) 语料训练一个以音素为建模单元、CTC 为训练准则的声学模型,并配套完整的超参数配置、数据准备与训练脚本分析。读完本文后,你将掌握从数据下载、JSON 标注生成、CRDNN 模型配置到--jit加速训练与 PER(Phoneme Error Rate,音素错误率)评估的完整闭环,可以直接在本仓库中复现并改造这一基线配方。

一、配方概述:音素 + CTC 的 ASR 基线

recipes/Voicebank/ASR/CTC是 SpeechBrain 中一个轻量而完整的 ASR 基线:它使用 VoiceBank 数据集的干净语音训练一个 CTC 声学模型,输出单元是音素(phoneme)而非字符,因此最终的评估指标是音素错误率(PER)而非词错误率(WER)。

该配方由三个核心文件组成:

文件作用
voicebank_prepare.py数据集下载(download_vctk)、重采样、词表/音素词典构建与 train/valid/test JSON 标注生成(prepare_voicebank
train.py基于sb.Brain定义前向计算、CTC 损失、PER 统计与训练/验证/测试流程
hparams/train.yaml全部超参数:特征、模型结构(VGG2 + LiGRU + DNN,即 CRDNN)、数据增强、优化器、调度器与 Checkpoint 策略

VoiceBank 数据集本身是「含噪语音」语料(Noisy-VCTK,来自爱丁堡数据共享平台的 10283/2791 条目),包含 28 位说话人的干净/噪声平行语音;本配方默认用**干净波形(clean_wav)**训练音素识别模型,但也允许通过一个开关直接切到噪声输入(见后文input_type说明)。

二、数据准备:download_vctk 与 prepare_voicebank

2.1 一键下载与重采样:download_vctk

README 明确要求使用 voicebank_prepare.py 中的download_vctk()函数完成数据集的下载与重采样。该函数的核心行为如下:

  • https://datashare.ed.ac.uk/bitstream/handle/10283/2791/依次下载 6 个 zip 包:clean_testset_wav.zipnoisy_testset_wav.ziptestset_txt.zipclean_trainset_28spk_wav.zipnoisy_trainset_28spk_wav.ziptrainset_28spk_txt.zip
  • 解压后统一重采样:通过torchaudio.transforms.Resample(orig_freq=48000, new_freq=16000)将 48 kHz 原始音频降到 16 kHz,输出目录名带_16k后缀;
  • 最终打包为noisy-vctk-16k.zip并移动到destination

函数签名download_vctk(destination, tmp_dir=None, device="cpu")中的device参数会直接传给 PyTorch 的.to(),用于控制重采样计算的运行设备。

2.2 标注生成流程:prepare_voicebank

prepare_voicebank(data_folder, save_folder, valid_speaker_count=2, skip_prep=False)(见 voicebank_prepare.py)负责把原始音频整理成 SpeechBrain 训练所需的 JSON 标注,主要步骤:

  1. 划分说话人:训练集 28 位说话人定义在TRAIN_SPEAKERS列表中(p226/p287/p227/…/p286),前valid_speaker_count(默认 2)位被划出作为验证集,剩余 26 位用于训练,测试集使用独立的 testset;
  2. 构建音素词典create_lexicon()(voicebank_prepare.py)从http://www.openslr.org/resources/11/librispeech-lexicon.txt下载 LibriSpeech 词典,并合并脚本内置的MISSING_LEXICON补充条目(如 "CRUCIALLY"、"MR"、"BBC" 等 90 余个词条),以覆盖 VoiceBank 文本中词典缺失的单词;
  3. 生成 JSONcreate_json()(voicebank_prepare.py)遍历 wav 列表,为每个句子写入noisy_wavclean_wavlength(由read_audio读出的采样点数除以 16 kHz 计算)、wordsphones五个字段;其中文本会先去除标点、转大写,再查词典转成音素串,并去除相邻重复音素(CTC 训练中重复音素会被折叠,提前去重有助于对齐稳定)。

三个输出文件train.jsonvalid.jsontest.json默认写入训练输出目录,其相对路径以{data_root}占位符开头,运行时由DynamicItemDataset.from_jsonreplacements={"data_root": hparams["data_folder"]}替换。

skip_prep=True时整个准备阶段会被跳过(已生成 JSON 时skip()函数也会自动识别并跳过),这对在已有标注上反复调试训练参数非常有用。

三、训练超参数详解:hparams/train.yaml

train.yaml 是配方的「灵魂」,全部训练行为都由它驱动。下面按模块逐一拆解。

3.1 输入与路径配置

seed: 1236 __set_seed: !apply:speechbrain.utils.seed_everything [!ref <seed>] input_type: clean_wav output_folder: !ref results/<input_type>/phn/<seed> per_file: !ref <output_folder>/per.txt save_folder: !ref <output_folder>/save data_folder: !PLACEHOLDER train_annotation: !ref <output_folder>/train.json valid_annotation: !ref <output_folder>/valid.json test_annotation: !ref <output_folder>/test.json skip_prep: False
  • input_type关键开关:它决定音频管线读取哪个字段。默认clean_wav;train.py 顶部注释明确指出,改成noisy_wav即可训练噪声语音输入。输出目录会随input_type自动区分(results/clean_wav/phn/1236results/noisy_wav/phn/1236);
  • data_folder!PLACEHOLDER占位,运行时通过命令行--data_folder=...填充;
  • JSON 标注默认放在输出目录中,由数据准备阶段生成。

3.2 训练与特征参数

number_of_epochs: 50 batch_size: 8 sorting: ascending lr: 0.5 max_grad_norm: 5.0 sample_rate: 16000 n_fft: 400 n_mels: 40
  • 50 个 epoch、batch size 8、学习率 0.5、梯度裁剪阈值 5.0;
  • sorting: ascending表示训练集按时长升序排序并配合dataloader_options.shuffle: False使用,可显著提升同 batch 内序列长度的整齐度(dataio_prep中对应实现见 train.py);也可改为descendingrandom,其他取值会直接抛出NotImplementedError
  • 特征为 40 维 FBank(n_fft=400n_mels=40,16 kHz 采样率下对应约 25 ms 窗长)。

3.3 模型结构:VGG2 + LiGRU + DNN(CRDNN)

activation: !name:torch.nn.LeakyReLU dropout: 0.15 cnn_blocks: 2 cnn_channels: (128, 256) cnn_kernelsize: (3, 3) rnn_layers: 4 rnn_neurons: 512 rnn_bidirectional: True dnn_blocks: 2 dnn_neurons: 512 output_neurons: 42 blank_index: !ref <output_neurons> - 1

模型使用 speechbrain/lobes/models/CRDNN.py 中的CRDNN类,它是一个sb.nnet.containers.Sequential容器,按顺序堆叠:

  • 2 个 VGG 风格 CNN Block(128、256 通道,3×3 卷积核),随后是一个时间轴最大池化time_pooling: TruePooling1d沿时间轴池化,kernel 为 2),有效压缩序列长度;
  • 4 层 512 神经元双向 LiGRUrnn_class=sb.nnet.RNN.LiGRU,这是 SpeechBrain 自研的轻量门控循环单元);
  • 2 层 512 神经元 DNN

输出侧是speechbrain.nnet.linear.Linear(42 个输出神经元)加 log-Softmax。output_neurons: 42对应「40 个音素 + blank + 未知符号」的编码规模,blank_index = 42 - 1 = 41作为 CTC 的 blank 标签索引,直接传给 speechbrain/nnet/losses.py 中的ctc_loss

3.4 波形域数据增强

与许多先提特征再在特征域增强的做法不同,本配方在波形域做增强(speechbrain.augment.time_domain),由Augmenter统一调度:

speed_perturb: !new:speechbrain.augment.time_domain.SpeedPerturb orig_freq: !ref <sample_rate> speeds: [95, 100, 105] drop_freq: !new:speechbrain.augment.time_domain.DropFreq drop_freq_low: 0 drop_freq_high: 1 drop_freq_count_low: 1 drop_freq_count_high: 3 drop_freq_width: 0.05 drop_chunk: !new:speechbrain.augment.time_domain.DropChunk drop_length_low: 1000 drop_length_high: 2000 drop_count_low: 1 drop_count_high: 5 wav_augment: !new:speechbrain.augment.augmenter.Augmenter concat_original: True min_augmentations: 3 max_augmentations: 3 augment_prob: 1.0 augmentations: [speed_perturb, drop_freq, drop_chunk]
  • 速度扰动:以 95%/100%/105% 三档速度重采样,模拟语速变化;
  • 频率丢弃:随机把 0~1 归一化频率区间中的若干频带置零(1~3 个频带,宽度 0.05);
  • 时间块丢弃:随机抹掉若干段 1000~2000 采样点的时域片段(1~5 段);
  • concat_original: True意味着每 batch 会拼接原始样本,增强样本与原始样本各占一半;
  • 因为波形被改动,音素标签必须同步做标签复制,这正是 train.py 中replicate_labels的作用。

3.5 优化器、调度器与 Checkpoint

opt_class: !name:torch.optim.Adadelta lr: !ref <lr> rho: 0.95 eps: 1.e-8 lr_annealing: !new:speechbrain.nnet.schedulers.NewBobScheduler initial_value: !ref <lr> improvement_threshold: 0.0025 annealing_factor: 0.8 patient: 0
  • 优化器为Adadelta(lr=0.5,rho=0.95),该优化器自带自适应学习率,适合 CTC 这类收敛较慢的任务;
  • 调度器为NewBob:验证集 PER 提升不足 0.0025 时,学习率乘以 0.8 退火;patient: 0表示立即退火不等待;
  • Checkpointer 会把modeloutputepoch_counterschedulernormalizer都注册为可恢复对象,并按验证 PER 最小的原则保存(见 train.py 的save_and_keep_only(meta={"PER": per}, min_keys=["PER"]))。

3.6 损失、统计与日志

compute_cost: !name:speechbrain.nnet.losses.ctc_loss blank_index: !ref <blank_index> ctc_stats: !name:speechbrain.utils.metric_stats.MetricStats metric: !name:speechbrain.nnet.losses.ctc_loss blank_index: !ref <blank_index> reduction: batch per_stats: !name:speechbrain.utils.metric_stats.ErrorRateStats
  • 训练损失compute_costctc_loss(blank_index=41);
  • ctc_stats以 batch 粒度 reduction 记录每个 batch 的 CTC 损失,便于最终输出逐条统计;
  • per_stats使用ErrorRateStats统计音素错误率,其输入来自验证/测试阶段的 CTC 贪心解码结果。

四、训练脚本源码剖析:train.py

4.1 ASR_Brain 的前向与损失

train.py 中定义了ASR_Brain(sb.Brain)

  • compute_forward:读取波形 →(训练阶段可选)波形增强 →Fbank提特征 →InputNormalization(全局归一化)→ CRDNN 模型 → 线性输出层 → log-Softmax,返回音素概率pout与长度wav_lens
  • compute_objectives:调用ctc_loss(pout, phns, pout_lens, phn_lens)计算损失并追加到ctc_metrics;在验证/测试阶段还会用 speechbrain/decoders/ctc.py 的ctc_greedy_decode(blank_id=41)做 CTC 贪心解码,再交给per_metrics计算 PER;
  • on_stage_end:验证阶段根据 PER 触发 NewBob 退火并保存最优 checkpoint;测试阶段把 CTC 损失与 PER 统计写入per.txt(由per_file指定)。

4.2 数据管线与标签编码

dataio_prep(train.py)负责构建三个DynamicItemDataset

  1. 音频管线@takes(hparams["input_type"])动态决定读取clean_wav还是noisy_wavread_audio后产出sig
  2. 文本管线:把phones字符串按空格拆成音素列表phn_list,再用CTCTextEncoder(speechbrain/dataio/encoder.py,支持 CTC blank 特殊符号)编码为phn_encoded
  3. 通过label_encoder.load_or_create(path=..., from_didatasets=[data["train"]], output_key="phn_list", special_labels={"blank_label": 41}, sequence_input=True)在训练集上拟合标签编码器,结果缓存为save/label_encoder.txt,训练集长度排序逻辑也在此完成。

4.3 主流程

主流程(train.py)依次执行:sb.parse_arguments解析超参文件与命令行覆盖 →ddp_init_group初始化多卡 DDP →sb.create_experiment_directory创建实验目录 →run_on_main(prepare_voicebank, ...)在单进程上完成数据准备 →dataio_prep建数据集 → 若 hparams 中含pretrained字段则加载预训练权重 → 构造ASR_Brainfit(50 个 epoch,训练/验证共用dataloader_options)→ 最后evaluate加载验证集上 PER 最低的 checkpoint 在测试集上评测。

五、如何运行

5.1 标准训练命令

按照 README 中的说明,在recipes/Voicebank/ASR/CTC目录下执行:

python train.py hparams/train.yaml --data_folder=your/data/folder --jit

其中your/data/folderdownload_vctk()产出的数据集根目录(包含clean_trainset_28spk_wav_16knoisy_trainset_28spk_wav_16k等子目录)。首次运行时prepare_voicebank会生成 train/valid/test 三个 JSON;若已准备过,可加--skip_prep=True直接进入训练。

5.2 关于 JIT 编译加速(重要)

README 特别强调了--jit参数:启用即时编译(JIT)可带来50%–60% 的提速,官方强烈推荐开启。需要说明的前提是:

  • 该速度提升是在使用CRDNN 模型时观察到的;
  • 本配方在 train.yaml 中通过jit_module_keys: [model]显式指定仅对 CRDNN 模型做 JIT 编译(而不是盲目编译全部模块)。对应机制见 speechbrain/core.py:当--jitjit_module_keys同时存在时,只编译列出的模块,未列出的模块不会被编译。

5.3 常用命令行覆盖与变体

  • 切换噪声输入:把train.yamlinput_type改为noisy_wav(输出目录自动变为results/noisy_wav/phn/<seed>);
  • 命令行覆盖超参:SpeechBrain 的 hyperpyyaml 机制支持追加--number_of_epochs=2 --batch_size=16之类的覆盖项,无需改动 yaml;
  • 加载预训练模型继续训练:在 yaml 中取消# pretrained: model_clean_ep3.ckpt注释并填入 checkpoint 路径,train.py会将其 state_dict 载入模型(见 train.py)。

六、结果与训练开销

README 给出的官方基线结果如下(VoiceBank 干净语音、音素级 CTC、CRDNN 模型):

发布版本超参文件输入类型测试集 PER模型下载训练硬件
21-02-09train.yamlclean_wav10.12%未提供1×V100 32GB

训练开销方面:在单张 TESLA V100 上,每个 epoch 约 4 分钟,50 个 epoch 的完整训练约 3 小时量级。训练日志与 checkpoint 输出在results/clean_wav/phn/1236/下,其中save/存放可恢复对象与label_encoder.txtper.txt存放测试阶段逐条 CTC 损失与 PER 统计。

七、工程验证:配方测试与复现要点

该配方被纳入 SpeechBrain 的 recipes 测试矩阵,见 tests/recipes/Voicebank.csv 中的 ASR 行:测试脚本使用--data_folder=tests/samples/separation --train_annotation=... --skip_prep=True --output_neurons=18 --number_of_epochs=2在迷你样例上做冒烟验证,并检查train_log.txtper.txtsave/label_encoder.txt等产物是否生成,同时记录了Test-PER=10.12%作为该配方的性能基线。这意味着你可以用同样的覆盖参数快速验证代码路径是否完好:

python train.py hparams/train.yaml \ --data_folder=../../../../tests/samples/separation \ --train_annotation=../../../../tests/samples/annotation/enhance_train.json \ --valid_annotation=../../../../tests/samples/annotation/enhance_dev.json \ --test_annotation=../../../../tests/samples/annotation/enhance_dev.json \ --skip_prep=True --output_neurons=18 --number_of_epochs=2

(注:上例中标注文件与output_neurons均为测试专用的简化值,完整训练请使用官方 42 音素配置。)

八、小结与扩展方向

recipes/Voicebank/ASR/CTC是一个麻雀虽小、五脏俱全的 CTC-ASR 基线:从download_vctk的数据落盘、create_lexicon的词典构建、create_json的音素化标注,到ASR_Brain的波形增强 + FBank + CRDNN + CTC 损失闭环,再到--jit编译加速与 NewBob 调度、PER 最优 checkpoint 选择,覆盖了 SpeechBrain 配方开发的完整套路。

如果希望进一步延伸,可以在本仓库中对比参照:

  • recipes/Voicebank/MTL/ASR_enhance:在 VoiceBank 上做「增强 + 识别」多任务学习,使用噪声输入与noisy_sig/clean_sig双通道管线;
  • speechbrain/decoders/ctc.py:CTCLanguageModel 与更丰富的 CTC 解码工具;
  • speechbrain/lobes/models/CRDNN.py:CRDNN 各组件(CNN_Block、时间池化、LiGRU、DNN)的详细参数说明。

在复现或改造本配方时,请注意:结果表中的 10.12% PER 是在clean_wav输入、42 音素标签、上述完整增强与调度配置下的官方基线;切换到noisy_wav或修改模型规模、增强策略后,指标会随之变化,应以自己的实验日志为准。


引用说明:若在研究中引用本配方或 SpeechBrain,建议参照 recipes/Voicebank/ASR/CTC/README.md 末尾给出的两篇 BibTeX 条目(SpeechBrain 1.0 论文与 SpeechBrain 原始论文),按学术规范标注。

【免费下载链接】speechbrainA PyTorch-based Speech Toolkit项目地址: https://gitcode.com/GitHub_Trending/sp/speechbrain

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询