ESPnet 中文普通话 ASR 实战:在 aidatatang_200zh 上复现 E-Branchformer 与 Conformer 实验

原创2026-09-24 23:32:12240 阅读
文章标签:人工智能语音音频深度学习NLP

ESPnet 中文普通话 ASR 实战:在 aidatatang_200zh 上复现 E-Branchformer 与 Conformer 实验

本指南围绕 ESPnet 仓库中 egs2/aidatatang_200zh/asr1 的中文普通话(Mandarin)语音识别实验,完整解读其中 E-Branchformer(12 层与 16 层两个版本)和 Conformer 三种编码器架构的配置文件、训练参数、语言模型与解码策略,并结合源码说明 E-Branchformer 的双分支结构原理。读者读完后,可以独立复现该数据集的 CER 评测结果,掌握如何在 ESPnet 的 egs2 配方框架下调整编码器深度、批大小、学习率与 SpecAugment 策略。

实验概述与数据集背景

aidatatang_200zh 是 AISHELL 团队发布的开源中文普通话语料库,原始数据托管于 OpenSLR(编号 62,www.openslr.org/resources/62),包含约 200 小时的标注语音,划分出 train、dev、test 三个子集。在 local/data.sh 中可以看到其下载与预处理逻辑:

  • 通过 data_url=www.openslr.org/resources/62 下载并解压 aidatatang_200zh 压缩包,目标目录由 db.sh 中的 AIDATATANG_200ZH 变量指定;
  • 调用 local/download_and_untar.sh 与 local/data_prep.sh 生成 Kaldi 风格的 data/{train,dev,test} 数据目录;
  • 预处理脚本对标注文本做了去空格归一化:paste -d " " <(cut -f 1 -d" " text.org) <(cut -f 2- -d" " text.org | tr -d " "),将转写中的空格删除,使中文文本以连续字符序列进入训练管线。

本实验以字符(char)为建模单元(--token_type char)、原始波形(raw waveform)为输入特征(--feats_type raw),是 ESPnet2 标准的中文 ASR 配置形态。

三种模型的配置与评测结果

该 README 记录了同一数据集上的三组实验:E-Branchformer(16 层)、E-Branchformer(12 层)与Conformer(12 层),三者共享 Transformer 解码器、相同的混合 CTC/Attention 训练框架与同一 Transformer 语言模型。原始 README 给出的环境与结果如下,必须原样继承:

环境信息(原文记录)

  • E-Branchformer 16 层实验:espnet 202301、pytorch 1.13.1、Python 3.9.15,Git hash 232a317a66eda6c5caee094db4b714bc912dce95(2023-02-22);
  • E-Branchformer 12 层实验:espnet 202211、pytorch 1.12.1、Python 3.9.15,Git hash 7a203d55543df02f0369d5608cd6f3033119a135(2022-12-23);
  • Conformer 实验:espnet 0.10.5a1、pytorch 1.7.1、Python 3.8.5,Git hash a5bacd349a47889aef795f999563018cf201ae64(2021-12-22)。

注意:上述环境记录于各自实验完成时的版本快照,直接复现时建议使用当前仓库版本并自行验证兼容性。

模型配置与参数量

实验 编码器配置 参数量 语言模型配置
E-Branchformer 16 层 conf/tuning/train_asr_e_branchformer_e16_linear1024_lr1e-3.yaml 45.43M conf/train_lm_transformer.yaml
E-Branchformer 12 层 conf/tuning/train_asr_e_branchformer_linear1024.yaml 37.66M 同上
Conformer 12 层 conf/train_asr_conformer.yaml 45.98M 同上

可以看出:16 层 E-Branchformer(45.43M)与 12 层 Conformer(45.98M)参数量相当,是同一参数量级下的公平对比;12 层 E-Branchformer 参数最少(37.66M)。

CER 评测结果(原文表格,逐字保留)

评价指标为字符错误率 CER(Char Error Rate),评测时使用 LM(解码目录 decode_asr_lm_lm_train_lm_transformer_zh_char_valid.loss.ave_asr_model_valid.acc.ave),模型选择策略为 ASR 取 valid acc 最优(.acc.ave 为最佳平均模型),LM 取 valid loss 最优。

E-Branchformer 16 层 + LM:

dataset Snt Wrd Corr Sub Del Ins Err S.Err
dev 24216 234524 96.7 2.9 0.4 0.2 3.4 17.6
test 48144 468933 96.1 3.5 0.4 0.2 4.1 20.1

E-Branchformer 12 层 + LM:

dataset Snt Wrd Corr Sub Del Ins Err S.Err
dev 24216 234524 96.6 3.0 0.4 0.1 3.6 18.4
test 48144 468933 95.9 3.6 0.4 0.2 4.2 20.8

Conformer 12 层 + LM:

dataset Snt Wrd Corr Sub Del Ins Err S.Err
dev 24216 234524 96.6 3.0 0.5 0.1 3.6 18.5
test 48144 468933 95.9 3.6 0.4 0.2 4.3 21.0

从 CER 看,16 层 E-Branchformer 在 dev/test 上取得最低错误率(3.4% / 4.1%),12 层 E-Branchformer 与 12 层 Conformer 表现基本持平(test 均为 4.2% / 4.3% 量级)。需要说明:各实验的数据划分、解码设置基本一致,但训练环境与超参不同(见下文配置对比),以上数字仅用于说明当前仓库记录的实验现象。

编码器架构配置详解

E-Branchformer 16 层(主实验配置)

conf/tuning/train_asr_e_branchformer_e16_linear1024_lr1e-3.yaml 是 README 标题对应的核心配置,其编码器关键项:

encoder: e_branchformer
encoder_conf:
    output_size: 256          # 模型维度
    attention_heads: 4        # 多头注意力头数
    attention_layer_type: rel_selfattn  # 相对位置自注意力
    pos_enc_layer_type: rel_pos
    rel_pos_type: latest      # 相对位置编码实现版本
    cgmlp_linear_units: 1024  # CGMLP 中 FFN 隐层维度
    cgmlp_conv_kernel: 31     # CGMLP 深度卷积核大小
    use_linear_after_conv: false
    gate_activation: identity # 门控激活函数
    num_blocks: 16            # 编码器层数(本实验的核心变量)
    dropout_rate: 0.1
    positional_dropout_rate: 0.1
    attention_dropout_rate: 0.1
    input_layer: conv2d       # 前端下采样:2 维卷积
    layer_drop_rate: 0.0
    linear_units: 1024        # FFN 隐层维度
    positionwise_layer_type: linear
    use_ffn: true             # 启用标准 FFN
    macaron_ffn: true         # 启用 macaron 风格 FFN
    merge_conv_kernel: 31     # 双分支融合模块的深度卷积核

E-Branchformer 12 层(tuning 变体)

conf/tuning/train_asr_e_branchformer_linear1024.yaml 与 16 层版本的主要差异:

  • num_blocks: 12(层数减少 4 层);
  • 优化器学习率 lr: 0.0005(16 层版为 0.001),warmup_steps: 30000(16 层版为 35000);
  • 训练轮数 max_epoch: 50(16 层版为 60);
  • SpecAugment 时间掩码使用绝对宽度 time_mask_width_range: [0, 40]、num_time_mask: 2,而 16 层版使用相对宽度 time_mask_width_ratio_range: [0.0, 0.05]、num_time_mask: 10;频率掩码宽度 16 层版为 [0, 27]、12 层版为 [0, 30]。

Conformer 12 层(基线)

conf/train_asr_conformer.yaml 展示了 Conformer 的经典配置,与 E-Branchformer 形成结构对照:

encoder: conformer
encoder_conf:
    output_size: 256
    attention_heads: 4
    linear_units: 2048        # FFN 隐层维度(Conformer 更大)
    num_blocks: 12
    dropout_rate: 0.1
    positional_dropout_rate: 0.1
    attention_dropout_rate: 0.0
    input_layer: conv2d
    normalize_before: true
    pos_enc_layer_type: rel_pos
    selfattention_layer_type: rel_selfattn
    activation_type: swish     # Swish 激活
    macaron_style: true        # macaron 风格
    use_cnn_module: true
    cnn_module_kernel: 15      # 卷积模块核大小 15

Conformer 采用"标准 MHSA + CNN 模块 + macaron FFN"的串联式块结构,而 E-Branchformer 则改为"MHSA 与 CGMLP 双分支并行、再经融合卷积合并"的结构(原理见下文源码解析)。

解码器、混合 CTC/Attention 与训练超参

三个 ASR 配置共享完全相同的解码器与模型损失配置:

decoder: transformer
decoder_conf:
    attention_heads: 4
    linear_units: 2048
    num_blocks: 6             # 6 层 Transformer 解码器
    dropout_rate: 0.1
    positional_dropout_rate: 0.1
    self_attention_dropout_rate: 0.0
    src_attention_dropout_rate: 0.0

model_conf:
    ctc_weight: 0.3           # 混合 CTC/Attention 的 CTC 权重
    lsm_weight: 0.1           # 标签平滑
    length_normalized_loss: false

其中 ctc_weight: 0.3 表示训练损失按 0.3 * CTC 损失 + 0.7 * Attention 损失 加权;lsm_weight: 0.1 为标签平滑系数,有助于缓解过拟合并提升泛化。

训练/优化相关差异(E-Branchformer 16 层 vs 12 层 vs Conformer):

超参 E-Branchformer 16 层 E-Branchformer 12 层 Conformer
batch_type / batch_bins numel / 16000000 numel / 16000000 numel / 4000000
accum_grad 1 1 4
grad_clip 5 5 5
max_epoch 60 50 50
use_amp true — —
num_workers 6 4 —
optim adam adam adam
lr 0.001(weight_decay 1e-6) 0.0005 0.0005
scheduler warmuplr / 35000 warmuplr / 30000 warmuplr / 30000

说明:

  • batch_type: numel 表示按张量元素总数(batch_bins)动态组批,而非固定句数,这样长短不一的中文音频能被更高效地打包;
  • Conformer 配置的 batch_bins 较小(4000000)但 accum_grad: 4,有效批大小与 16 层 E-Branchformer 相当;
  • 三份配置的模型选择策略一致:best_model_criterion: valid acc max,并保留 keep_nbest_models: 10 个最优模型用于后续平均;
  • 16 层 E-Branchformer 启用了 use_amp: true(自动混合精度),并带 weight_decay: 0.000001。

SpecAugment 数据增强配置

SpecAugment 是本实验提升泛化能力的关键增强手段,16 层 E-Branchformer 配置如下:

specaug: specaug
specaug_conf:
    apply_time_warp: true      # 时间弯曲
    time_warp_window: 5
    time_warp_mode: bicubic    # 双三次插值
    apply_freq_mask: true      # 频率掩码
    freq_mask_width_range: [0, 27]
    num_freq_mask: 2
    apply_time_mask: true      # 时间掩码
    time_mask_width_ratio_range: [0.0, 0.05]  # 相对帧长比例
    num_time_mask: 10

而 12 层 E-Branchformer 与 Conformer 采用绝对宽度的时间掩码(time_mask_width_range: [0, 40],num_time_mask: 2)。两种表述等价:ratio_range 按输入帧长比例计算掩码宽度,更适合超长音频;width_range 直接以帧数为单位。复现时可按数据长度灵活选择。

Transformer 语言模型(LM)配置

conf/train_lm_transformer.yaml 定义了实验共用的中文 char 级 Transformer LM:

lm: transformer
lm_conf:
    pos_enc: null              # 不单独使用位置编码(模型内置相对位置)
    embed_unit: 128            # 词嵌入维度
    att_unit: 512              # 注意力维度
    head: 8                    # 注意力头数
    unit: 2048                 # FFN 隐层维度
    layer: 16                  # 16 层
    dropout_rate: 0.1

grad_clip: 5.0
batch_type: numel
batch_bins: 2000000
accum_grad: 1
max_epoch: 15                  # 15 轮即收敛
optim: adam
optim_conf:
   lr: 0.001
scheduler: warmuplr
scheduler_conf:
   warmup_steps: 25000
best_model_criterion:          # LM 按 valid loss 选优
-   - valid
    - loss
    - min
keep_nbest_models: 10

LM 训练文本直接取自训练集标注:--lm_train_text "data/${train_set}/text"(见 run.sh)。

解码(推理)配置

conf/decode_asr.yaml 控制推理行为:

beam_size: 20        # 束搜索宽度
penalty: 0.0         # 长度惩罚
maxlenratio: 0.0     # 最大解码长度 = maxlenratio * 输入长度
minlenratio: 0.0
ctc_weight: 0.4      # 解码时 CTC 权重(与训练 0.3 不同)
lm_weight: 0.3       # 语言模型权重

注意解码阶段 ctc_weight: 0.4 高于训练时的 0.3,这是 ESPnet 混合 CTC/Attention 模型常用的"训练轻 CTC、解码重 CTC"策略;lm_weight: 0.3 表示解码打分中融合 LM 概率。评测结果表格中的目录名 decode_asr_lm_lm_train_lm_transformer_zh_char_valid.loss.ave_asr_model_valid.acc.ave 即对应"带 LM、ASR 取 valid acc 平均模型、LM 取 valid loss 平均模型"的解码产物。

一键训练脚本 run.sh 与参数说明

egs2/aidatatang_200zh/asr1/run.sh 是该配方的入口脚本,核心参数如下:

train_set=train
valid_set=dev
test_sets="dev test"

asr_config=conf/train_asr_e_branchformer.yaml      # 默认 16 层 E-Branchformer
inference_config=conf/decode_asr.yaml
lm_config=conf/train_lm_transformer.yaml
use_lm=true
speed_perturb_factors="0.9 1.0 1.1"                # 速度扰动(3 倍数据扩充)

./asr.sh \
    --ngpu 2 \
    --lang zh \
    --audio_format wav \
    --feats_type raw \
    --token_type char \
    --use_lm ${use_lm} \
    --lm_config "${lm_config}" \
    --asr_config "${asr_config}" \
    --inference_config "${inference_config}" \
    --train_set "${train_set}" \
    --valid_set "${valid_set}" \
    --test_sets "${test_sets}" \
    --speed_perturb_factors "${speed_perturb_factors}" \
    --asr_speech_fold_length 512 \
    --asr_text_fold_length 150 \
    --lm_fold_length 150 \
    --lm_train_text "data/${train_set}/text" "$@"

要点说明:

  • --speed_perturb_factors "0.9 1.0 1.1" 会对训练集做 0.9/1.0/1.1 倍速扰动,扩充后训练集名为 train_sp;
  • --asr_speech_fold_length 512 与 --asr_text_fold_length 150 控制训练时语音/文本按 512/150 的倍数截断,避免单 batch 内元素过多,配合 batch_type: numel 使用;
  • "$@" 允许在命令行追加覆盖参数,例如替换编码器配置:./run.sh --asr_config conf/tuning/train_asr_e_branchformer_linear1024.yaml 即可切换到 12 层版本;
  • 若切换实验配置,可参考各 tuning 配置文件中的差异(num_blocks、lr、warmup_steps、SpecAugment 参数)自行编写新配置。

环境与任务调度

执行前需先安装 ESPnet 依赖(参见仓库根目录 README.md 与 tools/README.md),并在 db.sh 中设置 AIDATATANG_200ZH=/path/to/data。任务调度后端由 cmd.sh 的 cmd_backend 变量控制,可选 local(本机并行,默认)、stdout、sge、pbs、slurm、ssh,对应 conf/queue.conf、conf/slurm.conf、conf/pbs.conf 等队列配置;多 GPU 训练时 --ngpu 2 会被传递到 cuda_cmd。GPU 数量、batch_bins、accum_grad 需根据显存实际情况调整。

E-Branchformer 架构原理(源码级解析)

E-Branchformer 编码器实现在 espnet2/asr/encoder/e_branchformer_encoder.py,核心是 EBranchformerEncoderLayer(第 58 行起)。从 forward 方法(第 113 行)可以清晰看到其块结构:

  1. 可选 macaron FFN 前置:若启用 macaron_ffn,先经过 norm_ff_macaron + 尺度为 0.5 的 FFN 残差子层(对应配置中的 macaron_ffn: true);
  2. 双分支并行:
    • 分支 1(注意力):x1 = self.norm_mha(x1) 后进入多头自注意力,rel_selfattn 使用相对位置编码 pos_emb(配置 pos_enc_layer_type: rel_pos);
    • 分支 2(卷积门控 MLP):x2 = self.norm_mlp(x2) 后进入 ConvolutionalGatingMLP(cgmlp),对应配置中的 cgmlp_linear_units: 1024、cgmlp_conv_kernel: 31、gate_activation: identity;
  3. 融合模块:x_concat = torch.cat([x1, x2], dim=-1) 拼接双分支输出,先经过 mask_padded_frames 屏蔽填充帧,再通过 depthwise_conv_fusion(核大小 merge_conv_kernel,深度卷积)沿时间维做局部融合,最后 merge_proj 线性投影回模型维度并残差相加;
  4. 标准 FFN 残差:若 use_ffn: true,再经过 norm_ff + FFN 残差子层;最终 norm_final 输出。

EBranchformerEncoder(第 191 行)的构造参数与 YAML 一一对应,例如 num_blocks、layer_drop_rate(可配合 layer_drop_rate > 0 做层丢弃训练)等。与 Conformer 的"串行堆叠 MHSA、CNN、FFN"不同,E-Branchformer 让全局自注意力与局部卷积门控两条路径并行,再通过可学习的融合卷积合并,从而同时捕获全局与局部依赖——这正是 16 层配置在相同参数量下 CER 略优的结构性原因。

相关实现还可参考 e_branchformer_ctc_encoder.py(CTC 分支版本)以及训练入口脚本 espnet2/bin/asr_train.py(配置解析与训练循环)。

复现步骤总结

  1. 安装 ESPnet 与依赖,激活虚拟环境;
  2. 在 db.sh 中设置 AIDATATANG_200ZH 数据存放路径;
  3. 按需修改 cmd.sh 中的 cmd_backend(单机建议 local)与 conf/queue.conf;
  4. 执行默认 16 层 E-Branchformer 实验:./run.sh;
  5. 复现 12 层变体:./run.sh --asr_config conf/tuning/train_asr_e_branchformer_linear1024.yaml;
  6. 复现 Conformer 基线:./run.sh --asr_config conf/train_asr_conformer.yaml;
  7. 训练完成后查看 exp/ 下各实验目录的 decode_asr_lm_* 结果,CER 通过 show_asr_result.sh 汇总展示(scripts/utils/show_asr_result.sh),或参照 README 中的 CER 表格格式整理报告。

如果只想评测不训练,也可以从 Hugging Face 下载 README 中记录的预训练模型链接(pyf98/aidatatang_200zh_e_branchformer_e16、pyf98/aidatatang_200zh_e_branchformer、sw005320/aidatatang_200zh_conformer),配合 inference 流程 直接对 dev/test 做解码验证。

登录后查看全文
espnet