首页
/ SpeechBrain 端到端语音识别模板实战:Tokenizer + RNNLM + CRDNN/GRU 三步训练完整指南

SpeechBrain 端到端语音识别模板实战:Tokenizer + RNNLM + CRDNN/GRU 三步训练完整指南

2026-09-14 23:53:25作者:郦嵘贵Just

本指南以 SpeechBrain 仓库中的 templates/speech_recognition 模板为主体,系统讲解如何从零构建一个离线端到端(E2E)注意力式语音识别系统:先基于 mini-Librispeech 训练 SentencePiece 子词 Tokenizer,再训练 RNN 语言模型,最后训练 CRDNN 编码器 + GRU 注意力解码器,并通过束搜索(Beam Search)耦合语言模型完成解码。读完本文,你将掌握 SpeechBrain 中 ASR 三阶段训练的标准流程、关键 YAML 配置项的含义与调参方法,以及将模板迁移到真实大数据集(如 LibriSpeech)的路径。

一、模板总览:一个完整的三步训练流水线

templates/speech_recognition 目录实现了一个基于 mini-librispeech 的简单语音识别器,它是一个离线端到端注意力式语音识别系统。整个训练流程被刻意拆解为三个相互依赖的阶段:

  1. 训练 Tokenizer:基于训练集转录文本,决定用哪些词片(word piece)作为识别单元。大多数情况下,介于字符(char)与完整单词(word)之间的子词单元最为实用。
  2. 训练语言模型(LM):在 Tokenizer 产出的 token 序列之上训练 RNN 语言模型,为后续束搜索提供语言学先验。
  3. 训练语音识别器(ASR):训练 CRDNN 编码器与自回归 GRU 解码器,解码阶段使用耦合 RNN LM 的束搜索。

模板目录结构如下(均在仓库根目录下的 templates/speech_recognition 中):

目录/文件 作用
Tokenizer/ SentencePiece 子词 Tokenizer 训练(train.py + tokenizer.yaml
LM/ RNN/Transformer 语言模型训练(train.py + RNNLM.yaml),依赖 HuggingFace datasets
ASR/ CTC + seq2seq 语音识别器训练与推理(train.py + train.yaml + inference.yaml + transcribe_file.py
mini_librispeech_prepare.py 三个子目录共用的小型数据准备脚本,负责下载并生成 JSON manifest

从源码看,这三个阶段之间存在强依赖关系:ASR 的 train.py 在注释中明确要求"先训练 Tokenizer(见 ../Tokenizer),再训练语言模型(见 ../LM),最后训练识别器";更重要的是,LM 与 ASR 必须使用同一个 Tokenizer,否则 AM/LM token 不匹配会导致束搜索结果严重劣化。

二、Step 1:训练 Tokenizer(SentencePiece 子词单元)

Token 的选择直接决定识别单元粒度:最原子的单元是字符(char),最粗的单元是完整单词。SpeechBrain 依赖流行的 SentencePiece 库完成分词。训练命令非常简单:

cd templates/speech_recognition/Tokenizer
python train.py tokenizer.yaml

2.1 配置解析:tokenizer.yaml

# 路径配置
data_folder: ../data
output_folder: ./save

skip_prep: False
train_annotation: ../train.json
valid_annotation: ../valid.json
test_annotation: ../test.json

# Tokenizer 参数
token_type: unigram  # ["unigram", "bpe", "char"]
token_output: 1000   # 词表大小;index(blank/eos/bos/unk) = 0
character_coverage: 1.0
annotation_read: words  # 从 manifest 中读取的字段

tokenizer: !name:speechbrain.tokenizers.SentencePiece.SentencePiece
   model_dir: !ref <output_folder>
   vocab_size: !ref <token_output>
   annotation_train: !ref <train_annotation>
   annotation_read: !ref <annotation_read>
   model_type: !ref <token_type>
   character_coverage: !ref <character_coverage>
   annotation_list_to_check: [!ref <train_annotation>, !ref <valid_annotation>]
   annotation_format: json

关键参数含义:

  • token_type:可选 unigrambpechar。模板默认 unigram(1K 词表);char 对应字符级识别(最原子单元),bpe 为字节对编码。注意 token_output: 1000 表示词表大小为 1000,且索引 0 预留给 blank/eos/bos/unk 特殊符号。
  • character_coverage: 1.0:字符覆盖率,对纯英文语料设为 1.0 即可;若语料包含稀有字符或 CJK 文本,通常需要降低该值(如 0.9995)以避免词表被罕见字符占满。
  • annotation_read: words:指明从 JSON manifest 的 words 字段读取转录文本用于训练。

2.2 训练入口:Tokenizer/train.py

脚本的执行逻辑清晰地对应了 SpeechBrain 的标准范式:

  1. sb.parse_arguments 解析命令行参数(支持在命令行以 key:value 形式覆盖 YAML 中的任意超参数);
  2. load_hyperpyyaml 加载 YAML,YAML 中的 !name:speechbrain.tokenizers.SentencePiece.SentencePiece!ref 语法会被解析为真实对象引用;
  3. skip_prep: False,调用 prepare_mini_librispeech 下载/准备数据并生成 train.jsonvalid.jsontest.json
  4. 最后执行 hparams<a href="https://link.gitcode.com/i/85c915d01fcef05afd04e3b955e0ad6c" target="_blank">"tokenizer"]() 触发 [speechbrain.tokenizers.SentencePiece 的 __call__,完成子词模型训练,模型文件保存在 Tokenizer/save/ 下,例如 1000_unigram.model

三、Step 2:训练语言模型(RNNLM)

拿到目标 token 后,需要在 token 序列之上训练语言模型。理想情况下应使用大规模文本语料(且语料领域与目标应用一致)。本模板为了演示,直接在 mini-librispeech 的训练转录文本上训练 LM:

cd templates/speech_recognition/LM
python train.py RNNLM.yaml

先决条件:需要安装 HuggingFace datasets 库:

pip install datasets

LM 目录的 README.md 指出,该模板同时支持 RNN-based LMTransformer-based LM(通过替换 YAML 中的模型定义实现),脚本的数据读取由 HuggingFace datasets 管理。

3.1 配置解析:RNNLM.yaml

seed: 2602
__set_seed: !apply:speechbrain.utils.seed_everything [!ref <seed>]

lm_train_data: !ref <data_folder>/train.txt
lm_valid_data: !ref <data_folder>/valid.txt
lm_test_data: !ref <data_folder>/test.txt

# 必须与 ASR 使用同一个 tokenizer
tokenizer_file: ../Tokenizer/save/1000_unigram.model

# 训练参数
number_of_epochs: 20
batch_size: 80
lr: 0.001
grad_accumulation_factor: 1  # 梯度累积,用于模拟大 batch 训练
ckpt_interval_minutes: 15    # 每 N 分钟保存一次 checkpoint

# 模型参数
emb_dim: 256   # embedding 维度
rnn_size: 512  # 隐层维度
layers: 2      # 隐层层数

# 特殊符号
bos_index: 0
eos_index: 0

model: !new:custom_model.CustomModel
    embedding_dim: !ref <emb_dim>
    rnn_size: !ref <rnn_size>
    layers: !ref <layers>

compute_cost: !name:speechbrain.nnet.losses.nll_loss

optimizer: !name:torch.optim.Adam
    lr: !ref <lr>
    betas: (0.9, 0.98)
    eps: 0.000000001

lr_annealing: !new:speechbrain.nnet.schedulers.NewBobScheduler
    initial_value: !ref <lr>
    improvement_threshold: 0.0025
    annealing_factor: 0.8
    patient: 0

要点说明:

  • tokenizer_file 指向 ../Tokenizer/save/1000_unigram.model,通过 pretrainer 加载到 sentencepiece.SentencePieceProcessor——这正是保证 LM 与 ASR token 一致的关键机制。
  • custom_model.CustomModel 定义在同目录的 custom_model.py 中,用户可以直接编辑该类,或在 YAML 中替换 !new 指向自定义模型文件。
  • 学习率调度采用 NewBob 算法:当连续两个 epoch 的改善低于 improvement_threshold: 0.0025 时,将学习率乘以 annealing_factor: 0.8
  • 训练目标为负对数似然(NLL);数据管线(见 LM/train.pydataio_prepare)用 tokenizer 将文本编码为 tokens_bos(前插 bos,喂给网络)与 tokens_eos(后接 eos,用于计算损失)。

3.2 训练逻辑:LM/train.py

该脚本定义了一个继承 sb.core.BrainLM 类,核心方法包括:

  • compute_forward:取 tokens_bos 输入 self.hparams.model,输出下一 token 的后验概率;
  • compute_objectives:用 nll_loss 计算预测与 tokens_eos 之间的损失;
  • on_stage_end:在验证阶段调用 lr_annealing 更新学习率、记录统计并 save_and_keep_only(meta=stats, min_keys=["loss"]) 保存最优 checkpoint。

数据读取方面,load_dataset("text", data_files={...}) 加载三个纯文本文件,再经 DynamicItemDataset.from_arrow_dataset 转为 SpeechBrain 的动态数据集,并通过 add_dynamic_item + set_output_keys 注册文本处理管线。

3.3 关于大规模 LM 训练的重要提醒

原模板文档特别强调:真实场景下训练 LM 的计算代价极其高昂,在大型语料上训练甚至可能耗费数周乃至数月(即使使用现代 GPU)。因此实践中更推荐的做法是:

  • 复用现有 LM:从 HuggingFace 等平台加载已训练好的语言模型;
  • 对现有 LM 做微调(fine-tune):仅用目标领域语料微调,成本远低于从零训练。

四、Step 3:训练语音识别器(CRDNN + GRU + Beam Search)

至此可以训练语音识别器本体。模板采用 CRDNN 模型(CNN + RNN + DNN 级联的编码器)+ 自回归 GRU 解码器,编码器与解码器之间使用注意力机制,最终词序列通过耦合 RNN LM 的束搜索获得:

cd templates/speech_recognition/ASR
python train.py train.yaml

4.1 训练配置全景:ASR/train.yaml

该 YAML 是模板中最完整的配置文件,覆盖数据、特征、增强、模型、解码五个层面。

(1)数据与数据准备

data_folder: ../data        # 数据将自动下载到此处
data_folder_noise: !ref <data_folder>/noise  # 增强用噪声
data_folder_rir: !ref <data_folder>/rir      # 增强用房间冲激响应

pretrained_path: speechbrain/asr-crdnn-rnnlm-librispeech

pretrainer(见 YAML 末尾)会从 pretrained_path 加载三样东西:lm.ckpt(预训练 RNNLM)、tokenizer.ckptasr.ckpt在 LibriSpeech 960h 上预训练的 ASR 权重)。模板注释明确说明:mini-librispeech 数据量太小,无法支撑端到端模型从零训练收敛,因此用更大的模型预训练来保证收敛;真实场景下用大数据集可以从零开始训练并跳过预训练。你也可以把 pretrained_path 改为本地路径,指向自己训练好的 LM 与 Tokenizer。

(2)特征参数

sample_rate: 16000
n_fft: 400
n_mels: 40

compute_features 使用 speechbrain.lobes.features.Fbank 提取 40 维 Fbank 特征,normalize 使用全局均值-方差归一化(norm_type: global)。

(3)训练超参数

number_of_epochs: 15
number_of_ctc_epochs: 5   # 前 5 个 epoch 使用 CTC 目标
batch_size: 8
lr: 1.0
ctc_weight: 0.5           # CTC 与 seq2seq 损失融合权重
sorting: ascending
label_smoothing: 0.1

模型采用 CTC + NLL 多任务训练:前 number_of_ctc_epochs 个 epoch 同时激活 CTC 与 seq2seq 损失(ctc_weight: 0.5),之后只保留 seq2seq 注意力损失——这是 SpeechBrain 中"先 CTC 预热、后注意力精调"的经典收敛策略,对应 ASR/train.py 中的 is_ctc_active(stage) 判断逻辑。优化器使用 Adadelta(lr: 1.0, rho: 0.95),学习率调度同样为 NewBob。

(4)模型结构

# 编码器:CRDNN
cnn_blocks: 2
cnn_channels: (128, 256)
rnn_class: !name:speechbrain.nnet.RNN.LSTM
rnn_layers: 4
rnn_neurons: 1024
rnn_bidirectional: True
dnn_blocks: 2
dnn_neurons: 512

# 解码器:注意力 GRU
emb_size: 128
dec_neurons: 1024
output_neurons: 1000   # token 数,必须与 LM 一致
blank_index: 0
bos_index: 0
eos_index: 0

编码器为 speechbrain.lobes.models.CRDNN(2 层 CNN 卷积块 + 4 层双向 LSTM + 2 层 DNN);解码器为 speechbrain.nnet.RNN.AttentionalRNNDecoderrnn_type: gruattn_type: location 位置注意力);顶部还有 ctc_linseq_lin 两个线性层分别输出 CTC 与 seq2seq 的 log 概率。整个模型通过 torch.nn.ModuleList 组装,RNNLM 单独作为 lm_modelspeechbrain.lobes.models.RNNLM.RNNLMreturn_hidden: True 供推理使用)。

(5)解码配置与 Scorer 体系

valid_beam_size: 8
test_beam_size: 80
eos_threshold: 1.5
max_attn_shift: 240
lm_weight: 0.50
ctc_weight_decode: 0.0
coverage_penalty: 1.5
temperature: 1.25
temperature_lm: 1.25

模板构建了完整的束搜索 scorer 组合,全部来自 speechbrain.decoders.scorer

  • ctc_scorerCTCScorer):CTC + 注意力联合束搜索,可提升性能但拖慢解码;
  • coverage_scorerCoverageScorer):根据束搜索中累积的注意力权重施加覆盖惩罚;
  • rnnlm_scorerRNNLMScorer):以 lm_weight: 0.5 加权应用语言模型概率;
  • ScorerBuilder:区分 full_scorers(对全词表打分,如 LM、coverage)与 partial_scorers(对剪枝后的 token 打分,如 CTC),scorer_beam_scale: 1.5 控制剪枝规模。

验证阶段使用较轻量的 valid_search(beam=8,仅 coverage scorer),测试阶段使用 test_search(beam=80,叠加 LM + CTC scorer)。这些搜索器均实例化为 speechbrain.decoders.S2SRNNBeamSearcher

(6)数据增强配置

train.yaml 中同时展示了波形域与特征域两大增强体系(统一由 speechbrain.augment.augmenter.Augmenter 编排):

  • 波形域wav_augment):加混响(AddReverb,RIR 数据自动下载)、加噪(AddNoise,SNR 0–15 dB)、语速扰动(SpeedPerturb,[85, 90, 95, 105, 110, 115]%)、频带丢弃(DropFreq)、时间片段丢弃(DropChunk)、削波(DoClip)、随机幅度(RandAmp)、语噪声(sum_batch 求和模拟 babble)、位深降低(DropBitResolution)、编解码器增强(CodecAugment);
  • 特征域fea_augment):时间/频率平移(RandomShift)、时间/频率片段丢弃(SpectrogramDrop)、时间/频率弯曲(Warping,SpecAugment 风格);
  • 每个增强均配有 enable_* 布尔开关,便于超参搜索时灵活启停;concat_original: True 保证每个 batch 中保留未增强的原始样本。

YAML 注释也提醒:模板刻意演示了全部增强手段的用法,实际项目中应根据任务选择子集以获得更优性能。

4.2 训练入口:ASR/train.py

ASR(sb.Brain) 类的核心流程:

  1. prepare_features 提取 Fbank 特征并归一化;
  2. compute_forward 中:编码器输出 encoded_signal → embedding 嵌入 tokens_bos → 注意力解码器 → seq_lin + log softmax 得到 seq2seq log 概率;CTC 激活时并行计算 ctc_logprobs
  3. 验证/测试阶段调用 valid_search / test_search 做束搜索并返回预测 token;
  4. compute_objectives 中,CTC 损失(speechbrain.nnet.losses.ctc_loss)与 seq2seq 交叉熵损失按 ctc_weight 加权融合。

训练前,pretrainer.collect_files() 会从 pretrained_path 下载 LM、tokenizer 与 ASR 预训练权重(或读取本地路径),随后 checkpointer 管理断点续训与最优模型保存。

五、推理:用训练好的模型转写音频

训练完成后,可使用 ASR/inference.yamltranscribe_file.py 进行单文件转写。inference.yaml 基本复制了 train.yaml 中的模型与解码配置(特征参数、CRDNN/GRU 结构、全部 scorer 参数),保证模型能被完整重载;其 pretrained_path 同样默认指向 speechbrain/asr-crdnn-rnnlm-librispeech,因此也支持直接加载预训练模型做零训练推理。

六、从模板走向真实系统:规模与路径

模板的价值在于展示 SpeechBrain 如何组织一个 e2e 语音识别器,但真实系统必须用远超 mini-librispeech 的数据量训练才能达到可用性能。原文档明确指出:若要更具竞争力的数据规模方案,可参考仓库中的 LibriSpeech 完整食谱(recipes/LibriSpeech/ASR,包含 CTC、seq2seq、transformer、transducer 等多种配置)。此外,模板中 LM 与 ASR 共用同一 tokenizer 的约束、CTC 预热的收敛策略、scorer 组合的解码方式,均与生产级食谱保持一致,可作为将模板扩展到更大数据集的直接起点。

七、总结

templates/speech_recognition 为 SpeechBrain 用户提供了一条从零构建端到端 ASR 的最小可行路径:

  1. Tokenizer(SentencePiece unigram/BPE)定义识别单元;
  2. RNNLM 提供语言学先验(真实场景优先复用或微调);
  3. CRDNN + 注意力 GRU + CTC/NLL 联合训练,束搜索时通过 ScorerBuilder 组合 LM、CTC、coverage 多路打分。

三阶段环环相扣,pretrainer 机制保证 tokenizer 与 LM 的一致性,checkpointer 保证训练可中断续跑。理解这一模板,即可在此基础上替换数据、模型与解码策略,快速搭建属于自己的语音识别系统。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
34
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.21 K
2.81 K
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
945
1.86 K
docsdocs
暂无描述
Markdown
906
5.84 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
537
607
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
864
1.36 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
4.28 K
1.03 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.39 K
1.48 K
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
550
401
flutter_flutterflutter_flutter
本仓库是 Flutter SDK 与 Flutter Engine 的 OpenHarmony 适配版本,由 CPF-Flutter 团队维护。开发者可使用熟悉的 Flutter 技术栈开发 OpenHarmony 应用,3.35.7 及以后的适配版本可基于本仓库源码构建支持 OpenHarmony 的 Flutter Engine。
Dart
1.19 K
347