FunASR 训练与微调实战指南:从数据集构建、Smoke Test 到检查点恢复与模型导出

FunASR 训练与微调实战指南:从数据集构建、Smoke Test 到检查点恢复与模型导出 FunASR 训练与微调实战指南从数据集构建、Smoke Test 到检查点恢复与模型导出【免费下载链接】FunASROpen-source speech recognition toolkit for training, inference, streaming ASR, VAD, punctuation, speaker diarization pipelines, and OpenAI-compatible/MCP serving.项目地址: https://gitcode.com/GitHub_Trending/fun/FunASRFunASR 是一个开源语音识别工具包覆盖推理、流式 ASR、VAD、标点、说话人分离等全链路也内置了从零训练Training from scratch、全参微调Fine-tuning与 LoRA 适配的训练体系。本文以仓库内 docs/training.md 为主线完整讲解在 FunASR 仓库中如何把已入库的 Recipe 脚本与数据集、Trainer 实现正确衔接起来包括三种核心数据格式Paraformer 音频-文本 JSONL、SenseVoice 富标签 JSONL、FunASRNano ChatML JSONL的构建命令工业级finetune.sh的参数逐项解析小规模 Smoke Test 的最小可运行模板非 DeepSpeed 路径下model.pt检查点的恢复语义以及评估与导出环节的注意事项。读完本文你将具备把自有语音数据接入 FunASR 训练管线并安全跑通数据校验 → 冒烟训练 → 断点续训 → 评估导出全流程的实操能力。前置说明文中所有命令均假定位于仓库根目录执行且当前环境已安装本仓库及所选 Recipe 的依赖。文档中的脚本是面向你自有数据与已审核模型资产的模板不代表仓库作者已完成全量训练、收敛性、GPU 显存或导出流程的实测。一、先选对任务推理、微调还是从零训练在动手前需要明确你的目标属于哪一类工作因为它们的起点、改动范围与约束完全不同任务类型改动内容起点推理Inference不改变任何权重仅对已有音频解码推理教程适配/微调Adaptation从预训练权重出发微调选定参数、全部参数或受支持的 LoRA 适配器下方各 Recipe开始前先记录一个留出集held-out基线从零训练Training from scratch不加载预训练权重直接按配置初始化指定架构需自行准备 tokenizer、特征与训练计划AISHELL Paraformer Recipe 及其 配置需要特别警惕两个容易踩坑的认知全参微调不等于从零训练。历史版本的 AISHELL 脚本内含作者本地路径并且通过init_param注入初始权重如果你想用它跑一次从零训练必须先替换其中的路径并刻意配置初始化方式而不是直接复用。industrial_data_pretraining下的脚本并不能复现原始工业预训练语料与流程。这些脚本只是可运行的模板不构成对原始预训练过程的重现证据。各模型家族的可用 Recipe 与关键边界如下表模型家族真实 Recipe 与配套材料重要边界SenseVoicefinetune.sh、英文 README、持续微调指南富标签与 tokenizer 特殊 token 至关重要。脚本期望用户自行准备data/train_example.jsonl与data/val_example.jsonl它不会替你生成。FunASRNanofinetune.sh、LoRA 脚本、微调指南默认脚本冻结音频编码器/适配器、仅解冻 LLM并非全参 Recipe。纯 LoRA 还需同时设置llm_conf.use_loratrue、lora_onlytrue、llm_conf.freezetrue。训练前务必审计可训练参数包括任何 CTC 组件。Paraformerfinetune.sh、README、LoRA 指南工业 Recipe 显式选用AudioDataset/IndexDSJsonl。Paraformer 的 LoRA 是独立 Recipe不是 Nano 那套适配器配置。MOSS-Transcribe-DiarizeFunASR 适配器源码第三方 OpenMOSS 模型。该适配器的forward会抛出仅推理错误MOSS 的训练不在本文讨论范围内。此外请注意许可证边界FunASR 软件本体是 MIT 许可但模型权重、上游代码、数据集与派生 checkpoint 可能采用不同许可。训练或再分发前务必核查每份资产的条款与数据使用同意data consent要求。二、准备数据集质量优先三种格式各就各位无论选择哪个家族数据准备都应遵循同一条底线训练集、验证集、最终测试集必须分离最好按说话人/会话维度切分而不只是按语句切分。逐条检查重复 ID、音频与转写 ID 是否一一对应、文件是否可读、解码后的时长/采样率、转写文本规范化以及语言覆盖度。音频相对路径是相对进程工作目录解析的而不是隐式相对 JSONL 文件所在目录当可复现性或隐私重要时优先使用稳定的本地绝对音频路径。2.1 Paraformer音频与文本 JSONLParaformer 家族使用的转换器是 scp2jsonl.py它按 utterance ID 将wav.scp与文本文件连接起来。输入文件每一行的格式都是utterance_id value其中转写文本可以包含空格。以一条两秒录音为例生成的结构如下{key:utt001,source:data/audio/utt001.wav,source_len:200,target:hello world,target_len:2}字段语义必须精确理解否则后续长度过滤会失真key、source、target是字符串source_len、target_len是整数。source_len的计算式为int(samples_at_16kHz / 160)即约 10ms 为单位的数值而不是秒数。该逻辑在 scp2jsonl.py 的parse_context_length中实现先以 16kHz 采样率读取音频context_len int(sample_num * 1000 / 16000 / 10)。target_len在文本含空格时按空白分词数统计否则按字符数统计见 scp2jsonl.py它并不普遍等于 tokenizer 的 token 数。从源码结构看JSONL 生成后的数据流是IndexDSJsonl索引读取器index_ds.py按配置的max/min_source_length、max/min_target_length、max_token_length对样本做过滤index_ds.py随后 datasets.py 中的AudioDataset注册名即AudioDataset完成特征提取与 tokenization。也就是说你写入的source_len/target_len会直接影响哪些样本被过滤掉写错单位会导致样本被误杀或漏网。准备好data/list/train_wav.scp、train_text.txt、val_wav.scp、val_text.txt后从仓库根目录执行python -m funasr.datasets.audio_datasets.scp2jsonl \ scp_file_list[data/list/train_wav.scp, data/list/train_text.txt] \ data_type_list[source, target] \ jsonl_file_outdata/list/train.jsonl python -m funasr.datasets.audio_datasets.scp2jsonl \ scp_file_list[data/list/val_wav.scp, data/list/val_text.txt] \ data_type_list[source, target] \ jsonl_file_outdata/list/val.jsonl两点重要提醒转换器会静默丢数据音频缺失的行会被continue跳过scp2jsonl.py转写缺失时也可能产出不完整记录。因此必须对比输入/输出条数并剔除不完整行——进程正常退出并不代表数据完整。只使用可信的 CLI 配置方式这个历史转换器对字符串形式的列表存在eval回退scp2jsonl.py请通过覆盖传入经过审查的参数不要引入不受控的字符串输入。2.2 SenseVoice保留富标签走SenseVoiceCTCDataset路径时需要在音频/文本 schema 中显式增加监督字段{key:utt001,source:data/audio/utt001.wav,source_len:200,target:你好,target_len:2,text_language:|zh|,emo_target:|NEUTRAL|,event_target:|Speech|,with_or_wo_itn:|woitn|}这些字符串必须是对应录音的真实标签绝不能不加区分地全局套用占位值。从 SenseVoice CTC 数据集实现 看缺失字段时会默认补成上述值但默认值不等于经校验的真值。同时注意更早的SenseVoiceDataset是另一套数据集实现务必保持数据集类与所选模型配置一致。若你手头没有对齐好的语言/情感/事件标注sensevoice2jsonl.py 支持通过scp_file_list与data_type_list接收对齐的 source/target/language/emotion/event 文件当语言、情感或事件标签缺失时它会调用 SenseVoice 生成伪标签这会下载/运行模型其 ITN 标志则基于标点启发式。训练前务必人工复核标签与规范化结果。另外不要凭空发明新的语言标签——那需要 tokenizer 与模型侧的协同修改请先参阅持续微调指南。2.3 FunASRNanoChatML JSONLNano 家族在其提供的 Recipe 中不消费Paraformer 那种平面 schema而是使用 ChatML 结构。真实样例见 train_example.jsonl 与 val_example.jsonl。以下结构示例中的长度字段必须针对真实数据重新计算{messages:[{role:system,content:You are a helpful assistant.},{role:user,content:语音转写|startofspeech|!data/audio/utt001.wav|endofspeech|},{role:assistant,content:你好}],speech_length:198,text_length:1}字段约定messages是 role/content 字典的列表assistant的content即目标转写。Recipe 自带转换器 scp2jsonl.py 按顺序配对 SCP 行与转写行要求 ID 一致并计算speech_length int((duration * 1000 - 25) // 10 1)见 scp2jsonl.py。text_length取自Qwen/Qwen3-0.6B的 tokenizationscp2jsonl.py。这意味着运行转换器可能拉取该 tokenizer若 wav 路径是 URL还会联网下载音频。行数不匹配时脚本只打 Warningscp2jsonl.py坏配对会被直接跳过——所以同样要检查输出条数与每一条报错。使用你自己的输入/输出文件而不是覆盖仓库自带的示例数据python examples/industrial_data_pretraining/fun_asr_nano/tools/scp2jsonl.py \ scp_filedata/list/train_wav.scp \ transcript_filedata/list/train_text.txt \ jsonl_filedata/list/nano_train.jsonl python examples/industrial_data_pretraining/fun_asr_nano/tools/scp2jsonl.py \ scp_filedata/list/val_wav.scp \ transcript_filedata/list/val_text.txt \ jsonl_filedata/list/nano_val.jsonl三、先小规模验证再启动大规模训练3.1 启动前的三项检查锁定环境固定 checkout 与模型资产版本记录依赖、tokenizer/frontend 配置、GPU 配置、数据哈希与随机种子。凡涉及trust_remote_code先人工审查所有下载的 Python 代码与 requirements。构建微小且互斥的冒烟集从已校验的记录中切出data/list/train_smoke.jsonl与data/list/val_smoke.jsonl。真正加载它们的音频、真正 tokenize 它们的 target确认长度过滤后 batch 非空、loss 有限、可训练参数名符合预期。先跑一个短训练/验证/存盘点周期再放大。不要盲目运行历史 shell 脚本它们内部写死了 GPU ID、输出路径和依赖工作目录的路径通常不会透传你在命令行末尾追加的覆盖参数。3.2 根目录相对路径的 Paraformer Smoke Test 模板以下模板脱胎于工业 Recipe适用于兼容 GPU 已安装训练依赖 两份已备好的 JSONL 一个已审核的完整模型目录models/paraformerCUDA_VISIBLE_DEVICES0 torchrun --nnodes1 --nproc_per_node1 \ --master_addr127.0.0.1 --master_port29619 \ funasr/bin/train_ds.py \ model./models/paraformer \ train_data_set_listdata/list/train_smoke.jsonl \ valid_data_set_listdata/list/val_smoke.jsonl \ datasetAudioDataset dataset_conf.index_dsIndexDSJsonl \ dataset_conf.data_split_num1 dataset_conf.batch_samplerBatchSampler \ dataset_conf.batch_typetoken dataset_conf.batch_size2000 \ dataset_conf.sort_size16 dataset_conf.num_workers0 \ train_conf.max_epoch1 train_conf.log_interval1 \ train_conf.resumefalse train_conf.use_deepspeedfalse \ train_conf.validate_interval1 train_conf.save_checkpoint_interval1 \ train_conf.keep_nbest_models1 train_conf.avg_nbest_model1 \ optim_conf.lr0.0002 output_dir./outputs/paraformer-smoke各关键参数的含义与取值建议参数说明datasetAudioDataset、dataset_conf.index_dsIndexDSJsonl数据链路与工业 Recipe 保持一致IndexDSJsonl在 index_ds.py 注册负责 JSONL 解析与长度过滤dataset_conf.batch_typetoken、dataset_conf.batch_size2000按 token 数切 batch。2000只是短音频的起步值不是显存保证只有在确认单样本仍能放下的前提下才可调低dataset_conf.sort_size16、dataset_conf.num_workers0排序窗口与 worker 数冒烟阶段设 0 便于串行排障train_conf.max_epoch1只对小数据集才是小的输入数据集大时 1 个 epoch 依然不小train_conf.resumefalse全新实验必须关闭续训语义见第四节train_conf.use_deepspeedfalse非 DeepSpeed 路径便于单卡冒烟train_conf.validate_interval1、save_checkpoint_interval1每个 epoch 都验证并落盘冒烟期最大化反馈train_conf.keep_nbest_models1、avg_nbest_model1只保留/平均最优模型控制冒烟产物规模optim_conf.lr0.0002与工业 Recipe 一致的初始学习率每个新实验都要使用全新的输出目录并确保 rendezvous 端口可用。若跑 SenseVoice 或 Nano请从各自家族的 Recipe/配置与 schema 出发不要把该命令里的AudioDataset直接替换到别的家族上。另外注意Nano 的脚本通过PATH查找funasr-train-ds请确认它指向你预期的安装SenseVoice 与 Paraformer 的脚本即使在use_deepspeedfalse时仍含有 DeepSpeed 配置路径参见 paraformer finetune.sh 与train_conf.deepspeed_config${deepspeed_config}启用 DeepSpeed 前务必核对真实配置。完整分布式训练与资源规划需要另行验证。四、检查点与断点续训resume的精确语义4.1 入口与恢复逻辑训练入口是 funasr/bin/train_ds.pyHydra 包装的main_hydra它会调用 Trainer.resume_checkpoint。分布式模式由_resolve_distributed_config决定train_ds.pyuse_deepspeed与use_fsdp互斥world_size 1 且两者都关时自动回退为 DDP。在非 DeepSpeed 路径下train_conf.resumetrue只会恢复output_dir/model.pt这一固定文件包含模型、优化器、调度器以及可用的 scaler/进度状态trainer_ds.py。要点它是布尔开关不是任意 checkpoint 路径。想续跑哪个实验就复用那个实验的output_dir。若该文件不存在Trainer 会打印No checkpoint found ... does not resume status!并继续训练trainer_ds.py而不是报错中断——所以必须在日志中确认恢复确实发生。加载时还受excludes键过滤影响trainer_ds.py且会处理module.前缀差异缺失的键会打印Miss key in ckpt。4.2 续跑与初始化权重的区别继续冒烟训练重跑原命令保持相同输出目录与配置追加train_conf.resumetrue并把train_conf.max_epoch2。注意max_epoch 是累计总数不是追加的额外 epoch 数。加载初始权重init_param...只加载初始权重不恢复优化器/调度器/进度状态。因此进入一个新的适配阶段时应使用全新输出目录 resumefalse并显式指定选定的初始化 checkpoint。4.3 保存产物形态非 DeepSpeed保存model.pt、model.pt.ep{epoch}或model.pt.ep{epoch}.{step}model.pt.best依据验证排名产生。训练结束时入口会调用average_checkpoints对avg_nbest_model个最佳模型做平均train_ds.py。DeepSpeed保存为 checkpoint 目录/标签形式需要走 DeepSpeed 对应的恢复/转换路径。不要把上述目录或残缺的 adaptor-only 状态当作普通独立权重。请保留配置、tokenizer/frontend 资产与基础模型出处provenance检查保存排除项与 LoRA 设置——一个 checkpoint 文件本身未必是可直接加载的模型目录。五、评估与导出用留出集说话5.1 单文件健全性检查加载一个备好的 Paraformer 模型目录与一个真实选中的 checkpoint做一次单文件健全性检查from pathlib import Path from funasr import AutoModel checkpoint Path(outputs/paraformer-smoke/model.pt) assert checkpoint.is_file(), checkpoint model AutoModel( model./models/paraformer, hubms, init_paramstr(checkpoint), devicecpu, disable_updateTrue, ) print(model.generate(inputdata/audio/heldout.wav))5.2 评估口径随后用未触碰过的留出集解码基线与适配后权重必须使用同一套文本规范化与 CER/WER 单位定义。报告时既要给聚合分数也要给按领域/语言拆分的结果、保留任务retained-task回退情况、数据条数与 checkpoint 身份标识。务必记住训练 loss 或 Trainer 的验证 accuracy 并不自动等于转写 CER/WER。Nano 家族可参考其 微调指南 中的解码/规范化/计分引用decode.py 使用了 VAD 且带remote_code./model.py因此它假定在 Recipe 工作目录下运行。那个 legacy 本地类 可以替换内置 Nano 类但不要假设它保留内置 LoRA 支持——评估前务必核对当前激活的类、适配器注入方式与已加载的键。5.3 导出是独立的兼容性任务导出不等于训练成功。以下都是入口点而非普适支持承诺SenseVoice ONNX 示例Paraformer 导出示例导出工具注意 Paraformer 导出示例自身会选定一个 contextual checkpoint使用时必须仔细核对并主动选择你的模型。模型专属导出钩子、tokenizer/frontend 资产、动态形状与运行时解码都需要逐一验证部署前请在留出输入上对比导出运行时与 Python 结果。六、全文关键结论速览先定位任务类型推理 / 微调 / 从零训练不同家族SenseVoice、FunASRNano、Paraformer各有独立 Recipe 与数据 schema 边界不可混用。三种 JSONL 格式中source_len以约 10ms 为单位、target_len是空白分词数或字符数Nano 的speech_length另有专门公式且转换器可能联网拉取 tokenizer 与音频。数据转换器会静默跳行必须核对输入/输出条数先构建微小 smoke 集跑通非空 batch → 有限 loss → 预期可训练参数再放大。resumetrue只恢复固定文件output_dir/model.pt含 optimizer/scheduler/scaler/进度是布尔开关而非任意路径init_param仅加载权重。续跑时max_epoch为累计总数。训练 loss/验证 accuracy ≠ CER/WER评估必须用统一规范化的留出集并报告领域级分数导出ONNX 等是独立的兼容性任务部署前必须对比运行时输出。所有脚本都是针对自有数据与已审核资产的模板FunASR 软件为 MIT 许可但权重、数据集与派生 checkpoint 的许可需单独核查。本文全部命令与代码均可直接在仓库根目录执行所有引用文件路径均为仓库内真实相对路径可继续深入阅读 docs/training.md 原文及其余配套文档。【免费下载链接】FunASROpen-source speech recognition toolkit for training, inference, streaming ASR, VAD, punctuation, speaker diarization pipelines, and OpenAI-compatible/MCP serving.项目地址: https://gitcode.com/GitHub_Trending/fun/FunASR创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考