- 人工智能
- 语音
- 音频
- 深度学习
- NLP
【免费下载链接】espnet
End-to-End Speech Processing Toolkit
MyST(My Science Tutor)是首个大规模儿童会话语音语料库,其儿童语音的声学特性(音高偏高、发音不稳定、词汇量有限)与成人语音差异显著,是 ASR 领域公认的高难度评测场景。本文以 egs2/myst/asr1 这一 ESPnet 官方 Recipe 为主体,完整讲解从 LDC 数据集获取、目录配置、FLAC 转 WAV、Kaldi 风格数据准备,到基于 WavLM 自监督前端 + Transformer 编码器的模型训练、解码配置与 WER/CER/TER 评测结果的完整技术链路。读完本文,你将掌握如何在 ESPnet2 框架下复现儿童语音识别模型myst_wavlm_aed_transformer,并能根据 run.sh 与 conf/tuning 下的配置模板改造出属于自己的儿童语音 ASR 系统。
一、MyST 数据集与 Recipe 概述
My Science Tutor (MyST) 是一套大规模儿童会话语音语料库,由 Pradhan、Cole 与 Ward 等人在 LREC-COLING 2024 上正式发布(详见 README.md 的参考文献)。该语料库收录了儿童与虚拟科学导师进行开放式对话的语音,覆盖真实课堂教学场景,其内容包含大量口语化表达、儿童特有的发音偏差以及会话性语音特征,因而成为评估儿童语音识别能力的代表性基准。
egs2/myst/asr1/README.md 即 ESPnet 官方为 MyST 提供的完整 Recipe,包含数据准备、训练配置与评测结果三大部分。其核心技术路线可以概括为:
- 前端:使用 S3PRL 接入 WavLM-Large 自监督模型,提取多层融合特征;
- 编码器:Transformer(18 层),并配套提供 Conformer(12 层)备选配置;
- 解码器:标准 Transformer 解码器,采用 CTC 与注意力机制联合解码;
- 分词:英文 BPE(unigram 模式,词表 5000);
- 训练数据:配合 0.9/1.0/1.1 三倍速扰动扩充训练集。
该 Recipe 的目录结构包含数据准备脚本 local/data.sh、数据集路径配置 db.sh、环境配置 path.sh 与 cmd.sh、训练入口 run.sh,以及完整的一组 conf 配置文件。
二、数据获取与路径配置
2.1 从 LDC 下载数据集
MyST 数据集由 LDC(Linguistic Data Consortium)发行,目录编号为LDC2021S05。Recipe 本身不会自动下载该数据(db.sh 中MYST=downloads仅为占位约定),需要用户自行从 LDC 目录获取并解压到本地。
# 下载并解压后,编辑 db.sh 指定数据集根目录 $ vim db.sh MYST=/path/to/myst解压后的数据集目录结构应如下(对应 README.md 的检查清单):
/path/to/myst └── myst_child_conv_speech ├── data ├── docs └── index.htmlRecipe 的数据准备阶段依赖myst_child_conv_speech这一子目录,其中data目录存放按train/development/test划分的音频与转写文件,docs目录存放语料说明文档。
2.2 数据集路径校验
local/data.sh 在 stage 1 会执行路径校验:
if [ -z "${MYST}" ]; then log "Fill the value of 'MYST' of db.sh" exit 1 fi if [ ! -d "${MYST}/myst_child_conv_speech" ]; then echo "stage 1: Please download data from https://catalog.ldc.upenn.edu/LDC2021S05 and save to ${MYST}" exit 1 fi从源码可以看出,MYST变量为空或myst_child_conv_speech目录缺失时,Recipe 会直接终止并给出提示,这是避免后续阶段误操作的重要保护逻辑。
三、数据准备:FLAC 转 WAV 与 Kaldi 风格目录构建
3.1 音频格式转换(stage 2)
MyST 原始音频为 FLAC 格式。Recipe 通过 local/flac_to_wav.py 调用 ffmpeg 完成格式转换,并支持多进程并行加速:
def flac2wav(filepath): assert filepath.endswith(".flac") outfilepath = filepath[:-5] + ".wav" cmd = f"ffmpeg -hide_banner -loglevel error -y -i {filepath} {outfilepath}" _ = os.system(cmd) if os.path.isfile(outfilepath): os.remove(filepath)转换完成后,原始的.flac文件会被删除以释放磁盘空间。该转换由data.sh的 stage 2 调度执行:
${cmd} "JOB=1:1" "${logdir}/flac_to_wav.JOB.log" \ python local/flac_to_wav.py \ --multiprocessing \ --njobs ${nj} \ --myst_dir ${original_dir}其中nj默认值为 32(见 data.sh 的nj=32),可以通过--njobs控制并行度。
需要特别说明的是:FLAC 转换是可选的。在 run.sh 中,作者给出了两种路径的注释说明:
# if your sox supports flac file, set local_data_opts and audio_format as below. #local_data_opts="" #audio_format=flac # if your sox does not support flac file, set local_data_opts and audio_format as below. local_data_opts="--flac2wav true" audio_format=wav也就是说:若本机 sox 支持 FLAC 解码,可以保持audio_format=flac并跳过转换;否则启用--flac2wav true,将audio_format设为wav。当前 Recipe 默认采用后者(WAV 格式)。
3.2 数据准备(stage 3)
local/prepare_data.py 负责将原始 MyST 目录转换为 ESPnet2 所需的 Kaldi 风格数据目录。其核心逻辑为:
- 将原始分区
train/development/test映射为train/dev/test(注意development→dev的命名映射); - 递归扫描各分区下的全部
.wav(或.flac)文件; - 对每个音频文件,在相同目录下寻找同名
.trn转写文件(audio_base + ".trn"); - 生成四个标准文件:
text:音频ID 转写文本utt2spk:音频ID 学生ID(说话人 ID 取自路径中的学生目录)spk2utt:由utt2spk派生wav.scp:音频ID 音频绝对路径
for audio_file in tqdm(audio_files): student_id = audio_file.split("/")[-3] session_dir = os.path.dirname(audio_file) audio_base = os.path.splitext(os.path.basename(audio_file))[0] transcription_file = os.path.join(session_dir, audio_base + ".trn") if os.path.isfile(transcription_file): with open(transcription_file, "r") as trn: transcription = trn.read().strip() text_data += f"{audio_base} {transcription}\n" utt2spk_data += f"{audio_base} {student_id}\n" wav_scp_data += f"{audio_base} {audio_file}\n"从代码可见,该脚本以 10000 条(cache_size = 10000)为缓冲阈值批量写入文件,避免海量语音文件导致的内存压力;只有存在对应.trn转写文件的音频才会进入数据集,保证了 text 与音频的一一对应。
data.sh在调用prepare_data.py之后还会执行一系列后处理:
for dset in $partitions; do # 对 text / utt2spk / wav.scp 排序 sort "$f" -o "$f" # 由 utt2spk 生成 spk2utt utils/utt2spk_to_spk2utt.pl "$utt2spk_file" > "$spk2utt_file" # 移除 UTF-8 空白字符(转为 ASCII 转写) iconv -f utf-8 -t ascii//TRANSLIT "$text_file" > "${text_file}.ascii" # 校验数据目录完整性 utils/validate_data_dir.sh --no-feats "$data_partition" done这里有两处值得注意的工程细节:
- 转写文本 ASCII 化:
iconv -f utf-8 -t ascii//TRANSLIT将转写中的 UTF-8 字符(如智能引号、连字符变体)转换为 ASCII 等价形式,规避后续分词与编码阶段可能出现的 Unicode 异常; - 目录校验:调用 ESPnet 通用脚本 validate_data_dir.sh 检查
text、utt2spk、spk2utt、wav.scp的一致性(如 ID 是否对齐、格式是否合法),确保数据质量。
完成 stage 3 后,data/{train,dev,test}三个标准数据目录即就绪,可进入特征与训练阶段。
四、训练配置:WavLM 前端 + Transformer 编码器
4.1 run.sh 顶层参数
run.sh 是整个训练流程的入口脚本,它通过 ESPnet2 通用的 asr.sh 驱动完整训练管线。其关键参数如下:
train_set="train" valid_set="dev" test_sets="test" encoder=transformer frontend=wavlm asr_config=conf/tuning/train_asr_${frontend}_${encoder}.yaml inference_config=conf/decode_asr.yaml nbpe=5000 bpemode=unigram local_data_opts="--flac2wav true" audio_format=wav min_wav_duration=0.3 ./asr.sh \ --lang en \ --gpu_inference true \ --token_type bpe \ --bpemode "${bpemode}" \ --nbpe "${nbpe}" \ --max_wav_duration 30 \ --speed_perturb_factors "0.9 1.0 1.1" \ --use_lm false \ --feats_normalize utt_mvn \ --feats_type raw \ --asr_config "${asr_config}" \ --inference_config "${inference_config}" \ --inference_asr_model "valid.acc.best.pth" \ --train_set "${train_set}" \ --valid_set "${valid_set}" \ --test_sets "${test_sets}" \ --lm_train_text "data/${train_set}/text" \ --bpe_train_text "data/${train_set}/text" \ --local_data_opts "${local_data_opts}" \ --audio_format ${audio_format} \ --min_wav_duration ${min_wav_duration} \ "$@"逐项解读这些参数的作用(默认值可对照 asr.sh 模板):
| 参数 | 本 Recipe 取值 | 说明 |
|---|---|---|
--token_type bpe | bpe | 子词切分方式为 BPE |
--bpemode unigram | unigram | BPE 训练算法为 unigram |
--nbpe 5000 | 5000 | BPE 词表规模为 5000 |
--speed_perturb_factors "0.9 1.0 1.1" | 三倍速扰动 | 对训练语音做 0.9 / 1.0 / 1.1 倍速扰动以扩充数据、增强鲁棒性 |
--use_lm false | 关闭 | 不使用外部语言模型,解码纯靠 AM + CTC |
--feats_normalize utt_mvn | 逐句 MVN | 每句话独立做均值方差归一化(无全局 CMVN 统计) |
--feats_type raw | 原始波形 | 直接输入原始音频,由前端模型提取特征 |
--max_wav_duration 30 | 30 秒 | 过滤超长音频 |
--min_wav_duration 0.3 | 0.3 秒 | 过滤过短音频,作者注释说明这是为了规避 stage 11 的TooShortUttError |
--inference_asr_model valid.acc.best.pth | 最优模型 | 以验证集准确率最高的 checkpoint 用于解码 |
--gpu_inference true | GPU 解码 | 解码阶段使用 GPU 加速 |
其中--min_wav_duration 0.3是一个值得注意的调参细节:ESPnet 的数据准备阶段会对过短音频抛出TooShortUttError,将该阈值从模板默认值(0.1 秒)提高到 0.3 秒,可以在儿童语音(存在大量极短的口头回应,如 "yeah"、"okay")场景下显著减少训练中断。
4.2 WavLM 前端与特征下采样
核心训练配置 train_asr_wavlm_transformer.yaml 定义了模型架构。前端部分采用 S3PRL 接入自监督预训练模型 WavLM-Large,并将上游参数全部冻结:
freeze_param: [ "frontend.upstream" ] frontend: s3prl frontend_conf: frontend_conf: upstream: wavlm_large download_dir: ./hub multilayer_feature: True preencoder: linear preencoder_conf: input_size: 1024 output_size: 80关键设计点:
frontend: s3prl:ESPnet2 的 S3PRL 前端会从指定download_dir(此处为./hub)加载预训练上游模型,首次运行会自动下载 WavLM-Large 权重;multilayer_feature: True:融合 WavLM-Large 多层 Transformer 的输出特征而非仅取最后一层,可提供更丰富的声学表征;freeze_param: ["frontend.upstream"]:冻结上游 WavLM 的全部参数,训练时只更新下游模块。这样既保留了大规模预训练知识,又大幅降低了显存占用与训练开销;preencoder: linear:线性投影层将 WavLM 的 1024 维多层融合特征下采样到 80 维,与经典 FBank 特征维度对齐,供编码器消费。
4.3 Transformer 编码器 / 解码器
encoder: transformer encoder_conf: output_size: 256 attention_heads: 4 linear_units: 1024 num_blocks: 18 dropout_rate: 0.1 positional_dropout_rate: 0.1 attention_dropout_rate: 0.1 input_layer: conv2d2 normalize_before: true decoder: transformer decoder_conf: attention_heads: 4 linear_units: 2048 num_blocks: 6 dropout_rate: 0.1 positional_dropout_rate: 0.1 self_attention_dropout_rate: 0.1 src_attention_dropout_rate: 0.1编码器为 18 层 Transformer(隐藏维度 256、4 注意力头、FFN 隐层 1024),输入层使用两层卷积(conv2d2)对 80 维特征做时间与频率维度的下采样;解码器为 6 层 Transformer(FFN 隐层 2048)。各 dropout 均设置为 0.1,normalize_before: true采用 Pre-LN 结构(LayerNorm 置于残差之前),这一配置在现代 Transformer 训练中收敛更稳定。
4.4 训练目标与正则
model_conf: ctc_weight: 0.3 lsm_weight: 0.1 length_normalized_loss: false extract_feats_in_collect_stats: falsectc_weight: 0.3:CTC 损失与注意力损失的加权系数。损失函数为L = ctc_weight * L_ctc + (1 - ctc_weight) * L_att,0.3 是 ESPnet 常见的混合训练取值,与解码配置中的ctc_weight保持一致;lsm_weight: 0.1:标签平滑系数 0.1,抑制模型过度自信、提升泛化;extract_feats_in_collect_stats: false:由于采用utt_mvn逐句归一化,无需在统计收集阶段提取特征(与之配套的feats_normalize utt_mvn在 run.sh 中设置)。
4.5 批处理、优化器与数据增强
batch_type: numel batch_bins: 16000000 accum_grad: 4 max_epoch: 20 best_model_criterion: - - valid - acc - max keep_nbest_models: 4 use_amp: true optim: adam optim_conf: lr: 0.002 weight_decay: 0.000001 scheduler: warmuplr scheduler_conf: warmup_steps: 15000 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.05] num_time_mask: 5batch_type: numel+batch_bins: 16000000:以元素总数(numel)为粒度动态组批,将每个 batch 的张量元素数控制在约 1600 万。这也解释了结果目录名exp/asr_asr_train_asr_wavlm_transformer_raw_en_bpe5000_sp_bs16000000中bs16000000的来历;accum_grad: 4:每 4 个 batch 累积一次梯度更新,等效扩大 batch size;max_epoch: 20:训练上限 20 个 epoch;use_amp: true:启用自动混合精度训练,显著降低显存与训练时间;- 优化器:Adam(lr=0.002,weight_decay=1e-6)+ WarmupLR 调度器(warmup 15000 步),这是 Transformer 类模型的标准配置;
- SpecAugment:时间扭曲(窗口 5)、频域掩码(2 个,宽度 0–27)、时域掩码(5 个,宽度比例 0–0.05),用于增强声学特征鲁棒性。
4.6 Conformer 备选配置
除 Transformer 外,Recipe 还提供了 train_asr_wavlm_conformer.yaml 作为备选。其前端、preencoder、解码器与训练超参完全一致,仅编码器替换为 12 层 Conformer:
encoder: conformer encoder_conf: output_size: 256 attention_heads: 4 linear_units: 1024 num_blocks: 12 macaron_style: true rel_pos_type: latest pos_enc_layer_type: rel_pos selfattention_layer_type: rel_selfattn activation_type: swish use_cnn_module: true cnn_module_kernel: 31Conformer 在 Transformer 注意力基础上引入了卷积模块(cnn_module_kernel: 31)、相对位置编码(rel_pos+rel_selfattn)与 Macaron 式前馈结构,activation_type: swish使用 Swish 激活。该配置训练上限放宽到max_epoch: 70,并保留keep_nbest_models: 10个最优模型。想要实验不同编码器,只需修改 run.sh 中的encoder=transformer为conformer(配置文件路径由conf/tuning/train_asr_${frontend}_${encoder}.yaml自动拼出)。
五、解码与评测
5.1 解码配置
decode_asr.yaml 定义推理阶段参数:
beam_size: 20 ctc_weight: 0.3 lm_weight: 0.0 maxlenratio: 0.0 minlenratio: 0.0 penalty: 0.0beam_size: 20:束搜索宽度;ctc_weight: 0.3:与训练目标一致,推理时在 CTC 前缀得分与注意力得分之间以 0.3 / 0.7 加权联合打分;lm_weight: 0.0:由于--use_lm false,语言模型权重置零;maxlenratio / minlenratio均为 0.0:长度由模型自回归预测,不施加外部长度约束。
解码由--gpu_inference true在 GPU 上执行,模型选择验证集准确率最优的valid.acc.best.pth(由 run.sh 的--inference_asr_model指定)。
5.2 官方评测结果
README.md 的 RESULTS 章节 记录了基于 WavLM + Transformer(训练目录exp/asr_asr_train_asr_wavlm_transformer_raw_en_bpe5000_sp_bs16000000)在测试集上的完整评测,包含字级(CER)、词级(WER)与句级(TER)三个维度的指标:
WER(测试集)
| dataset | Snt | Wrd | Corr | Sub | Del | Ins | Err | S.Err |
|---|---|---|---|---|---|---|---|---|
| decode_asr_asr_model_valid.acc.best/test | 13180 | 202306 | 88.4 | 7.6 | 4.0 | 3.4 | 15.0 | 61.9 |
CER(测试集)
| dataset | Snt | Wrd | Corr | Sub | Del | Ins | Err | S.Err |
|---|---|---|---|---|---|---|---|---|
| decode_asr_asr_model_valid.acc.best/test | 13180 | 1016043 | 93.2 | 2.1 | 4.7 | 3.6 | 10.4 | 61.9 |
TER(测试集)
| dataset | Snt | Wrd | Corr | Sub | Del | Ins | Err | S.Err |
|---|---|---|---|---|---|---|---|---|
| decode_asr_asr_model_valid.acc.best/test | 13180 | 228240 | 86.4 | 6.7 | 6.8 | 4.0 | 17.6 | 61.9 |
解读这些数字:
- 测试集共 13180 句(Snt),其中WER 15.0%、CER 10.4%、TER 17.6%;
- WER 的误差构成中,替换错误(Sub 7.6%)占比最高,删除(Del 4.0%)与插入(Ins 3.4%)相对较低;
- CER(字符级)显著低于 WER,说明儿童口语中高频出现的多词短语错误主要源于词边界与功能词层面;
- S.Err(句子错误率)高达 61.9%,即在约六成的句子上模型产生了至少一个词错误,这直观反映了儿童会话语音(语音重叠、自发言语、不完整句)的整体难度。
这些评测结果来自 Recipe 作者在 2024 年 11 月的实际训练与解码,可作为复现时的对照基线。评测过程本身由 ESPnet 通用脚本 show_asr_result.sh 等工具完成,读者可在自己的exp/目录下运行同一脚本生成报告。
六、复现环境与模型发布
6.1 实验环境快照
README.md 的 Environments 章节 记录了生成上述结果时的精确软件环境,复现时可作为版本对齐依据:
| 项目 | 版本 |
|---|---|
| 日期 | 2024-11-25(CST) |
| Python | 3.12.3(Anaconda) |
| ESPnet | espnet 202409 |
| PyTorch | 2.4.0 |
| Git commit | 6b5c6230a794aa4a5df872be69e417a3fbfe821b(2024-11-24) |
6.2 预训练模型
训练好的最优模型以myst_wavlm_aed_transformer为名对外发布(托管于 Hugging Face 的 espnet 组织,详见 README.md)。该模型可直接用于推理或微调,例如通过 ESPnet 标准的模型加载接口按名称拉取,无需重新训练即可对儿童语音进行识别。
七、从零运行 Recipe 的完整步骤
综合前述各章节,在具备 ESPnet 环境(Python 3.12、PyTorch 2.4、espnet 202409 及以上版本)与 GPU 的前提下,完整运行该 Recipe 的步骤如下:
# 1. 进入 recipe 目录 cd egs2/myst/asr1 # 2. 编辑 db.sh,填入数据集路径 vim db.sh # MYST=/path/to/myst # 3. 按需选择调度后端(默认 local,单机直接跑) vim cmd.sh # cmd_backend='local' # 4. 依次执行数据准备(stage 1-3) ./run.sh --stage 1 --stop_stage 3 # 5. 执行训练(默认全套流程,从 stage 开始自动衔接) ./run.sh --stage 4 --stop_stage 12 # 6. 或一次性从零跑到评测 ./run.sh其中run.sh末尾的"$@"允许将命令行参数透传给 asr.sh(如--stage、--stop_stage、--ngpu等),实现灵活的断点续跑。需要注意:
- 首次训练 WavLM 前端会从
./hub目录下载 WavLM-Large 权重(由 train_asr_wavlm_transformer.yaml 的download_dir: ./hub指定); - 数据准备阶段若 sox 支持 FLAC,可保持 FLAC 管线;否则按 run.sh 默认的
--flac2wav true+audio_format=wav执行; - 训练与解码所需的算力较高(18 层 Transformer + 6 层解码器、numel 组批、AMP 混合精度),建议在配备多卡 GPU 的节点上运行,并通过 cmd.sh 切换至 Slurm / PBS / SGE 等集群后端。
八、总结与扩展方向
MyST Recipe 是 ESPnet2 中"预训练自监督前端 + 下游轻量 ASR"范式的典型案例:通过冻结 WavLM-Large 并叠加 80 维线性投影,将大规模预训练表征与可训练的 Transformer 编码器高效结合;配合速度扰动、SpecAugment、混合精度与 numel 动态组批,在 20 个 epoch 内即在儿童会话语音上取得 WER 15.0% 的成绩。
若要在该 Recipe 基础上继续探索,仓库内已有现成路径可供参考:
- 更换编码器:将 run.sh 的
encoder改为conformer,即可切换至 train_asr_wavlm_conformer.yaml(12 层 Conformer + 相对位置编码); - 更换上游模型:修改配置中的
upstream: wavlm_large为其他 S3PRL 支持的预训练模型(如 HuBERT、Wav2Vec2 等),对比不同自监督表征在儿童语音上的表现; - 引入语言模型:将
--use_lm false改为启用 LM 训练,或接入外部语言模型降低替换错误; - 数据规模实验:调整
--speed_perturb_factors、--min_wav_duration等参数,研究数据增强与时长过滤对儿童语音识别的影响。
参考文献
[1] Pradhan, Sameer, Ronald Cole, and Wayne Ward. "My Science Tutor (MyST)–a Large Corpus of Children's Conversational Speech." Proceedings of the 2024 Joint International Conference on Computational Linguistics, Language Resources and Evaluation (LREC-COLING 2024). 2024.
- 人工智能
- 语音
- 音频
- 深度学习
- NLP
【免费下载链接】espnet
End-to-End Speech Processing Toolkit
相关推荐
ESPnet 儿童语音识别实战:CMU Kids 数据集的 WavLM 特征 + Transformer/Conformer ASR Recipe 全解析
ESPnet 儿童语音识别实战:CMU Kids 数据集的 WavLM 特征 + Transformer/Conformer ASR Recipe 全解析 导读
人工智能语音音频深度学习NLPESPnet OGI Kids Speech ASR 实战:Branchformer-Transformer 儿童语音识别 Recipe 全解析
ESPnet OGI Kids Speech ASR 实战:Branchformer Transformer 儿童语音识别 Recipe 全解析 本文基于 ES
人工智能语音音频深度学习NLPespnet 端到端语音意图识别实战:HarperValley 数据集 ASR Recipe 完整解析
espnet 端到端语音意图识别实战:HarperValley 数据集 ASR Recipe 完整解析 导读 本文围绕 espnet 仓库中 egs2/harp
人工智能语音音频深度学习NLP
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考