NeMo TopIPL 实践指南:基于迭代伪标签(IPL)的半监督 ASR 自训练流水线 📅 发布时间:2026/9/14 8:01:50 👁 浏览次数: NeMo TopIPL 实践指南基于迭代伪标签IPL的半监督 ASR 自训练流水线【免费下载链接】SpeechA scalable generative AI framework built for researchers and developers working on Large Language Models, Multimodal, and Speech AI (Automatic Speech Recognition and Text-to-Speech)项目地址: https://gitcode.com/GitHub_Trending/nem/SpeechTopIPLTop-N Pseudo-Label Averaging for Iterative ASR Training是 NeMo 内置的一种迭代伪标签Iterative Pseudo-Labeling, IPL算法用于同时利用有标注与无标注语音数据训练 ASR 模型。本文基于 scripts/pseudo_labeling/README.md 展开结合 nemo/utils/exp_manager.py、nemo/collections/common/callbacks/ipl_epoch_stopper.py 以及 scripts/pseudo_labeling/ 下的配套脚本讲解 TopIPL 的流水线组成、配置方式与核心实现原理。读完本文你将掌握如何在 NeMo ASR 训练中启用训练 → 生成伪标签 → 更新训练配置 → 再训练的迭代自训练闭环。什么是 TopIPL面向 ASR 的迭代伪标签算法TopIPL 是一种将有监督训练与**无监督/半监督自训练self-training**结合起来的迭代算法。其基本思路是使用当前模型对无标注语音批量生成伪标签pseudo-label再把带伪标签的数据并入训练集进行下一轮微调如此循环往复让模型在打标签—学习的循环中逐步提升识别能力。整个过程按 epoch 周期性触发、动态刷新伪标签人工介入极少。在 NeMo 中TopIPL 被设计为与现有 ASR 训练管线无缝集成主要具备以下能力源自文档 Key Features半监督 ASR 训练支持在训练过程中动态、迭代地精细化伪标签dynamic iterative pseudo-label refinement面向大规模训练可同时利用有标注与无标注语音数据支撑大规模语料上的自训练自动化闭环自动写入伪标签并在迭代之间自动更新训练配置Automatically writes pseudo-labels and updates training configs between iterations。从源码注释可以确认该算法对应论文TopIPL: Unified Semi-Supervised Pipeline for Automatic Speech Recognition详见 ipl_epoch_stopper.py 与 exp_manager.py 中的引用其核心思想即周期性停止训练 → 生成伪标签 → 在伪标签上微调。流水线总体流程结合文档与 scripts/pseudo_labeling/ 目录下的两个辅助脚本TopIPL 一个完整迭代周期的数据流大致为训练阶段ASR 模型在有标注数据可能混入上一轮伪标签数据上训练触发停止IPLEpochStopperCallback在设定的 epoch 数结束后让 Trainer 优雅停止trainer.should_stop True推理生成伪标签对无标注数据的 manifest 运行 ASR 推理产出predictions_all.json伪标签落盘由 write_transcribed_files.py 把推理结果写回 manifestpred_text→text原text存为orig_text更新推理配置由 update_inference_config.py 依据伪标签缓存比例p_cache、GPU 数量等重新计算trainer.limit_predict_batches控制下一轮只对无标签数据做部分转写partial transcription以实现伪标签的动态更新进入下一轮训练加载更新后的 manifest 与配置从新周期继续训练。其中步骤 35 的命令生成与提交由SDPNeMoRunIPLProcessor基于 SDP processors 与 NeMo-Run完成见下一节。两大必需组件文档明确指出 TopIPL 依赖以下两个组件。1. SDPNeMoRunIPLProcessor迭代命令的生成与提交SDPNeMoRunIPLProcessor负责为每一轮 IPL 生成并提交训练/推理命令。它基于 SDPNeMo 语音数据处理框架的 processor 机制并通过NeMo-Run执行任务调度。整个 IPL 流水线推理生成伪标签、转换 manifest、更新配置、重启训练都以该处理器为编排入口。说明该处理器定义在 NeMo Speech Data Processor 项目中原文档中链接到其sdp/processors/ipl/README.md本文仅介绍其在当前仓库中的使用位置与职责边界。当前仓库侧的配合脚本见 scripts/pseudo_labeling/。2. IPLEpochStopperCallback按 epoch 停止训练的训练回调该回调需要添加到训练配置的exp_manager段下作用是在每个 epoch 结束时停止训练为伪标签更新腾出时机。文档给出的最小配置如下exp_manager: create_ipl_epoch_stopper_callback: True ipl_epoch_stopper_callback_params: stop_every_n_epochs: n # Stop training after every n epochs (default: 1)其中stop_every_n_epochs表示每训练 n 个 epoch 停止一次默认值为 1即每个 epoch 结束后都停止。配置的底层实现这两个配置项并非虚构而是 ExpManagerConfig 中真实存在的字段create_ipl_epoch_stopper_callback: Optional[bool] False——是否创建该回调的开关默认关闭ipl_epoch_stopper_callback_params: Optional[IPLEpochStopperParams]——回调参数默认值为IPLEpochStopperParams()。当开关为True时exp_manager 在初始化回调列表时会实例化并挂载该回调# nemo/utils/exp_manager.py L710-L712 if cfg.create_ipl_epoch_stopper_callback: ipl_epoch_stopper_callback IPLEpochStopper(**cfg.ipl_epoch_stopper_callback_params) trainer.callbacks.append(ipl_epoch_stopper_callback)IPLEpochStopperParams是一个 dataclass字段与默认值如下字段类型默认值含义enable_stopboolTrue是否启用停止行为见下方实现差异stop_every_n_epochsint1每训练多少个 epoch 停止一次定义见 exp_manager.py回调的停止机制IPLEpochStopper本身定义在 nemo/collections/common/callbacks/ipl_epoch_stopper.py继承自 PyTorch Lightning 的Callback。其核心逻辑在on_train_epoch_end钩子中class IPLEpochStopper(Callback): def __init__(self, enable_stop: bool False, stop_every_n_epochs: int 1) - None: super().__init__() self.enable_stop bool(enable_stop) self.stop_every_n_epochs stop_every_n_epochs def on_train_epoch_end(self, trainer: Trainer, pl_module: LightningModule) - None: super().__init__() if self.stop_every_n_epochs ! 0: self.stop_every_n_epochs - 1 if self.stop_every_n_epochs 0: trainer.should_stop True两点值得注意的实现细节停止时机在 epoch 末尾而非训练中途on_train_epoch_end保证当前 epoch 完整跑完才发出停止信号避免打断正在进行的学习过程计数器递减语义每次on_train_epoch_end触发时stop_every_n_epochs自减 1减到 0 才置trainer.should_stop True从而实现每 n 个 epoch 停一次。注意该对象一旦触发停止计数器会停留在 0因此下一轮训练需要以新启动的训练进程重新加载 checkpoint继续这也与 IPL停止 → 生成伪标签 → 重新初始化/重启训练的循环语义一致enable_stop字段的取值差异回调类的默认值为False惰性而IPLEpochStopperParams的默认值为True启用因此只要通过exp_manager打开create_ipl_epoch_stopper_callback停止行为即默认生效若直接手动实例化回调则需要显式传入enable_stopTrue。配套脚本一动态更新推理批次数update_inference_config.pyupdate_inference_config.py 的作用是根据无标注数据规模、伪标签缓存比例与 GPU 数量重写推理配置中的trainer.limit_predict_batches从而强制对无标签数据集进行部分转写partial transcription实现伪标签的动态更新。命令行参数参数类型必填说明--inference_configsstr可多个nargs是一个或多个推理配置 YAML 文件路径--p_cachefloat是伪标签缓存比例pseudo-label cache fraction用于缩放批次数量--num_gpusint是可用于推理的 GPU 数量典型调用示意python scripts/pseudo_labeling/update_inference_config.py \ --inference_configs conf/infer_unlabeled.yaml \ --p_cache 0.1 \ --num_gpus 8批次数计算公式脚本会区分tarred与非 tarred 两种数据集分别统计条目数tarred 场景调用count_files_for_tarred_pseudo_labeling按 manifest 文件名的前缀prefix_[0-9]*.jsonglob 出所有 shard 并逐行计数非 tarred 场景调用count_files_for_pseudo_labeling直接统计单个 manifest 的行数。随后依据推理数据集的类型计算limit_predict_batches推理数据集配置计算公式使用batch_sizelimit_predict_batches ceil(num_files * p_cache / (batch_size * num_gpus))使用batch_duration秒limit_predict_batches ceil(num_files * 10 * p_cache / (batch_duration * num_gpus))其中 10 为脚本内置的平均音频时长估计秒两者皆无兜底按默认batch_size 32代入上式计算完成后通过OmegaConf.update(config, trainer.limit_predict_batches, ...)写回原配置文件并保存。多进程安全设计脚本在main()中读取环境变量RANK默认 0并借助filelock的FileLock与rank 0判断确保分布式多进程场景下只有一个进程执行配置重写其余进程等待锁释放后继续避免并发写同一 YAML 造成损坏见 update_inference_config.py。配套脚本二把推理结果写回训练 manifestwrite_transcribed_files.pywrite_transcribed_files.py 负责把上一轮推理产出的predictions_all.json转换成可供下一轮训练使用的transcribed_manifest.json。其核心字段变换逻辑为pred_text→text模型预测文本升级为伪标签文本原text→orig_text保留原始标注/旧标签便于对比与回滚仅处理以.wav结尾的音频条目并对重复条目*dup做去重保护。命令行参数参数类型说明--is_tarredflag处理 tarred 格式的 shard manifest--full_passflag全量转写模式否则为采样/部分模式--prediction_filepathsstr可多个存放predictions_all.json的推理输出目录两个 flag 组合决定四种处理函数见 write_transcribed_files.py--is_tarred--full_pass调用函数产物否否write_sampled_transcriptionstranscribed_manifest.json合并预测与旧 manifest否是create_transcribed_manifeststranscribed_manifest.json全新生成是否write_sampled_shard_transcriptions按 shard 拆分的transcribed_manifest_{shard_id}.json并汇总transcribed_manifest__OP_0..N_CL_.json是是create_transcribed_shard_manifests按 shard 拆分后汇总的合并 manifest该脚本同样采用FileLockrank 0的多进程安全模式保证分布式推理环境下只由主进程执行 manifest 重写。端到端编排思路如何搭建一个 IPL 自训练闭环将上述组件串起来一个可落地的 TopIPL 迭代周期如下训练配置在训练 YAML 的exp_manager段加入create_ipl_epoch_stopper_callback: True并设置stop_every_n_epochs例如 1启动首轮训练使用有标注数据正常训练训练将在每个 epoch 结束后自动停止生成伪标签由SDPNeMoRunIPLProcessor调度 NeMo-Run对无标注数据 manifest 执行 ASR 推理输出predictions_all.json写回伪标签运行 write_transcribed_files.py将推理结果转换为新的transcribed_manifest.jsontarred 场景传--is_tarred刷新推理预算运行 update_inference_config.py按--p_cache与--num_gpus重算limit_predict_batches控制下一轮推理覆盖的数据比例重启训练以更新后的 manifest、伪标签与推理配置开启新一轮训练重复 25直到收敛或达到预设轮数。使用前提与注意事项依赖外部编排组件命令的生成与提交依赖 SDP processorSDPNeMoRunIPLProcessor与 NeMo-Run当前仓库仅提供训练侧回调与两个配套脚本完整流水线需要与 SDP 环境配合使用回调默认不创建create_ipl_epoch_stopper_callback默认为False需显式开启stop_every_n_epochs默认 1停止即退出回调通过置位trainer.should_stop结束训练后续轮次需重新拉起训练进程从 checkpoint 恢复配置会被就地改写update_inference_config.py会直接修改并保存传入的推理 YAML 文件建议为每轮迭代保留配置副本计数基于 manifest 行数批次数估算依赖 manifest 条目数与平均音频时长假设10 秒实际批次大小可能因音频长度波动而略有偏差。小结TopIPL 为 NeMo ASR 提供了一条完整的半监督自训练路径训练侧由IPLEpochStopper回调实现按 epoch 停止的节奏控制数据侧由 update_inference_config.py 与 write_transcribed_files.py 完成伪标签写回 推理预算刷新再配合SDPNeMoRunIPLProcessor统一编排迭代命令即可在几乎无需人工干预的前提下让 ASR 模型在有标注与无标注数据上循环自训练、逐步提升。【免费下载链接】SpeechA scalable generative AI framework built for researchers and developers working on Large Language Models, Multimodal, and Speech AI (Automatic Speech Recognition and Text-to-Speech)项目地址: https://gitcode.com/GitHub_Trending/nem/Speech创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考