ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

FunASR Fun-ASR-Nano 微调实战指南:ChatML 数据准备、finetune.sh 全参/部分微调与 LoRA 微调、WER 评测全流程

FunASR Fun-ASR-Nano 微调实战指南:ChatML 数据准备、finetune.sh 全参/部分微调与 LoRA 微调、WER 评测全流程 FunASR Fun-ASR-Nano 微调实战指南ChatML 数据准备、finetune.sh 全参/部分微调与 LoRA 微调、WER 评测全流程【免费下载链接】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本文是 FunASR 仓库中 Fun-ASR-Nano 微调文档对应英文版 finetune.md的完整实战展开。文章以该文档为骨架围绕数据准备 → 启动训练 → LoRA 微调 → 模型评测四条主线并结合仓库内的finetune.sh、lora_finetune.sh、tools/scp2jsonl.py、decode.py等脚本的源码实现做纵深解读。读完本文你将能够在自己的领域数据上把通义实验室的 8 亿参数端到端语音识别大模型 Fun-ASR-Nano 微调成符合行业需求的专属 ASR 模型并给出可复现的 WER 评测流程。微调对象Fun-ASR-Nano 模型简介在动手微调之前先明确我们要微调的对象。根据仓库内 README_zh.md 的介绍Fun-ASR-Nano模型名FunAudioLLM/Fun-ASR-Nano-2512是通义实验室推出的端到端语音识别大模型参数量约 8 亿基于数千万小时真实语音数据训练支持中文、英文、日文其中中文覆盖 7 种方言吴语、粤语、闽语、客家话、赣语、湘语、晋语和 26 种地域口音独立的 Fun-ASR-MLT-Nano checkpoint 则覆盖 31 个语种。该模型的架构为「音频编码器audio_encoder→ 音频适配器audio_adaptor→ LLMQwen3-0.6B→ CTC 解码器ctc_decoder」的组合式结构因此微调时可以通过freeze开关精确控制微调哪些模块这也是本文后续参数讲解的核心。微调脚本默认从模型库拉取FunAudioLLM/Fun-ASR-Nano-2512作为基座权重见 finetune.sh。安装训练环境微调所需的训练工具链由 FunASR 主库提供直接安装即可pip install funasr1.3.26安装完成后可以通过which funasr-train-ds确认训练入口是否可用——finetune.sh与lora_finetune.sh中正是通过这一命令定位 FunASR 的 DeepSpeed 训练器见 finetune.sh。仓库示例目录下还提供了 requirements.txt可按需安装依赖。数据准备ChatML 对话格式详解Fun-ASR-Nano 的微调数据采用 ChatML对话格式每一行是一个 JSON 对象写入扩展名为.jsonl的文件中。官方文档给出了示例仓库内可直接查看 data/train_example.jsonlhead -n1 data/train_example.jsonl | jq输出示例{ messages: [ { role: system, content: You are a helpful assistant. }, { role: user, content: 语音转写|startofspeech|!https://modelscope.cn/datasets/FunAudioLLM/funasr-demo/resolve/master/audios/IT0011W0002.wav|endofspeech| }, { role: assistant, content: 几点了 } ], speech_length: 145, text_length: 3 }字段语义字段含义说明messages[0]system系统提示词content 固定为You are a helpful assistant.messages[1]user用户输入content 由 prompt 和音频路径组成音频路径必须包裹在|startofspeech|!与|endofspeech|之间messages[2]assistant标注文本content 对应音频文件的转写文本speech_length音频的 fbank 帧数一帧对应 10ms 音频text_length标注文本的 token 数使用Qwen/Qwen3-0.6B分词器编码得到prompt 的三种写法user 消息中的 prompt 前缀可按场景选择默认转写语音转写中文/Speech transcription:英文指定目标语种当需要把音频转写成特定语言时可以组合语种描述例如语音转写成英文/Transcribe speech into Chinese:不做文本规整当标注文本中不含阿拉伯数字或标点符号即文本本身就是规整后的纯文字时使用语音转写不进行文本规整/Speech transcription without text normalization:可避免模型把123误规整为一百二十三之类的歧义。两个长度字段的作用speech_length对应音频经过 fbank 特征提取后的帧数10ms/帧。它用于训练时与音频特征长度对齐属于训练时的长度约束字段text_length用 Qwen3-0.6B 分词器对标注文本编码后的 token 数。它与speech_length共同参与训练时的批次长度组织与 loss mask 计算。数据格式转换工具 scp2jsonl.py手工构造 ChatML JSON 比较繁琐官方提供了转换工具 tools/scp2jsonl.py可以把语音识别领域最常见的wav.scp text数据格式一键转换为上述 ChatML jsonl 格式。输入格式一train_wav.scp左侧为数据唯一 ID需与 text 文件中的 ID 一一对应右侧为音频文件路径支持本地路径或 HTTP 链接BAC009S0764W0121 https://isv-data.oss-cn-hangzhou.aliyuncs.com/ics/MaaS/ASR/test_audio/BAC009S0764W0121.wav BAC009S0916W0489 https://isv-data.oss-cn-hangzhou.aliyuncs.com/ics/MaaS/ASR/test_audio/BAC009S0916W0489.wav输入格式二train_text.txt左侧为数据唯一 ID需与 wav.scp 中的 ID 一一对应右侧为该音频的标注文本BAC009S0764W0121 甚至出现交易几乎停滞的情况 BAC009S0916W0489 湖北一公司以员工名义贷款数十员工负债千万转换命令python tools/scp2jsonl.py \ scp_filedata/train_wav.scp \ transcript_filedata/train_text.txt \ jsonl_filedata/train_example.jsonl转换脚本的实现细节源码级解读阅读 scp2jsonl.py 源码可以发现几个对使用者有实际影响的实现细节严格校验 ID 对齐脚本按行 zip 两个文件逐行校验utt1 utt2ID 不一致会记录为错误UTT mismatch并跳过该条数据L32-L36speech_length的精确计算不是简单地取duration * 100而是使用公式int((duration * 1000 - 25) // 10 1)L59这与 fbank 特征的帧移10ms和首帧偏移对齐方式有关体现了帧数语义的严谨性text_length使用真实 Qwen3-0.6B 分词器脚本加载AutoTokenizer.from_pretrained(Qwen/Qwen3-0.6B)对文本编码计数L91与训练时 LLM 的分词完全一致保证长度字段准确多线程并发处理使用ThreadPoolExecutor并发读取音频时长本地路径用soundfileHTTP 路径用urlopen下载后读取max_workers默认取os.cpu_count()L101处理大批量数据时速度更快错误统计与排查脚本结尾会输出成功/失败条数失败原因如 WAV 不存在、网络 404会打印前 10 条便于快速定位脏数据L120-L133。需要注意由于脚本需要读取每个音频的时长信息数据量很大时建议保证网络路径可访问或改用本地音频路径。启动训练finetune.sh 参数逐项解读数据准备好后直接运行官方微调脚本bash finetune.sh在运行前需要理解 finetune.sh 中的关键配置。该脚本的核心逻辑是通过CUDA_VISIBLE_DEVICES指定使用的 GPU并按逗号数量推断进程数L7-L8通过torchrun拉起分布式训练支持WORLD_SIZE、RANK、MASTER_ADDR、MASTER_PORT环境变量覆盖默认单机单卡L26-L32调用funasr-train-dsFunASR 的 DeepSpeed 训练器以前缀的 Hydra 参数覆盖模型默认配置L39-L65。核心参数说明参数finetune.sh 中的默认值说明modelFunAudioLLM/Fun-ASR-Nano-2512基座模型名ModelScope/HF hub或本地模型目录trust_remote_codetrue允许执行仓库内 model.py 等远程代码train_data_set_list/valid_data_set_listdata/train_example.jsonl/data/val_example.jsonl训练/验证集的 jsonl 路径dataset_conf.batch_size6000配合batch_typetoken使用表示每个 batch 按 token 数切分6000 为 token 上限dataset_conf.batch_samplerBatchSampler批次采样器dataset_conf.sort_size1024排序桶大小用于相似长度样本聚类减少 padding 浪费dataset_conf.num_workers4数据加载子进程数train_conf.max_epoch50最大训练轮数train_conf.validate_interval2000每 2000 步做一次验证train_conf.save_checkpoint_interval2000每 2000 步保存一次 checkpointtrain_conf.keep_nbest_models20保留最优的 20 个 checkpointtrain_conf.avg_nbest_model10训练结束后对最优 10 个 checkpoint 做平均得到最终模型train_conf.use_deepspeedfalse是否启用 DeepSpeed脚本仍传入deepspeed_config以备启用optim_conf.lr0.0002学习率output_dir./outputs输出目录日志写入outputs/log.txtfreeze 开关控制微调哪些模块脚本中与微调哪些模块直接相关的三个参数是audio_encoder_conf.freezetrue \ audio_adaptor_conf.freezetrue \ llm_conf.freezefalse \含义需要微调的模块把freeze设为false冻结的模块保持true。上述默认配置表示只微调 LLMQwen3-0.6B冻结音频编码器与音频适配器。官方推荐的按数据量选择微调范围的配置如下训练数据规模推荐微调范围少于 1000 小时微调audio_adaptor音频适配器少于 5000 小时微调audio_encoder和audio_adaptor编码器 适配器大于 10000 小时全量参数微调三个模块freeze均置false其背后的逻辑是数据量小时只动参数量小的适配器防止过拟合且收敛快数据量足够大时放开编码器乃至全量参数让模型充分适配领域声学特征。LoRA 微调轻量替代方案作为全量/部分微调的替代方案可以对 Qwen3-0.6B LLM 做 LoRA 微调在其q_proj/v_proj线性层上挂适配器训练成本显著更低。直接运行bash lora_finetune.sh关键参数说明阅读 lora_finetune.shL77-L81LoRA 微调涉及以下关键参数llm_conf.use_loratrue在 LLM 目标层注入LoRALinear适配器。基座权重共享并冻结新增可训练的lora_A/lora_B矩阵lora_onlytrue冻结所有非 LoRA 参数音频编码器、适配器、CTC 解码器只训练适配器。checkpoint 仍保存完整 state dict基座权重不变 适配器参数因此用相同的use_loratrue配置即可续训或解码llm_conf.freezetrue保持 LLM 基座权重冻结与lora_only语义重复但更显式学习率在 LoRA 脚本中调整为optim_conf.lr0.0001比全量微调的 0.0002 更保守因为适配器参数少、更易震荡。LoRA 超参数LoRA 超参数位于llm_conf.lora_conf下模型配置自带默认值脚本注释中标注的默认值与模型配置一致r16、lora_alpha32、lora_dropout0.05、target_modules[q_proj, v_proj]。可在命令行覆盖例如把秩提高到 32llm_conf.lora_conf.r32混合微调策略LLM 做 LoRA 编码器可训练如果希望在只对 LLM 做 LoRA 的同时保持音频编码器/适配器可训练对数百小时领域数据是个不错的折中方案可以这样设置lora_onlyfalse \ audio_encoder_conf.freezefalse \ audio_adaptor_conf.freezefalse \ llm_conf.freezetrue此时 LLM 基座权重仍通过llm_conf.freezetrue保持冻结只训练注入的 LoRA 适配器而音频编码器与适配器作为普通参数参与训练兼顾了领域声学适配与LLM 轻量训练。解码与部署LoRA 适配器的两种使用方式方式一直接解码无需合并微调后的 checkpoint 可直接用下文的decode.py解码无需合并步骤——前向时在基座输出上叠加适配器输出。方式二合并进基座权重独立部署若要把适配器折叠进基座权重以得到独立部署的 checkpoint对每个目标模块计算W W (lora_alpha / r) * lora_B lora_A然后从 state dict 中删除lora_A/lora_B键即可。合并后得到的是与 LoRA 推理等价的常规权重可脱离 LoRA 框架直接加载部署。模型评测解码与 WER 计算微调结束后使用 decode.py 对模型进行解码评测。解码命令python decode.py \ model_dir/path/to/finetuned \ scp_filedata/val_wav.scp \ output_fileoutput.txt参数说明model_dir微调后 checkpoint 所在目录默认回退到FunAudioLLM/Fun-ASR-Nano-2512见 decode.pyscp_file验证集 wav.scp仓库示例为 data/val_wav.scpoutput_file识别结果输出路径。decode.py 的实现细节源码级解读从 decode.py 源码可以看到几个关键设计自动选择设备优先cuda:0其次 Apple Silicon 的mps最后回退cpuL24-L28内置 VAD 前处理通过AutoModel加载时挂载vad_modelfsmn-vad并设置vad_kwargs{max_single_segment_time: 30000}单段音频最长 30 秒长音频会被 VAD 自动切段后识别避免超长输入导致性能劣化L35-L36加载本地远程代码remote_code./model.py指向仓库内模型定义配合trust_remote_codeTrue使用L37输出格式逐行读取 scp输出ID\t文本TAB 分隔到output_fileL47-L54与 kaldi 风格的compute-wer工具输入格式兼容。文本逆归一化与 WER 计算解码结束后需要对标注和识别结果做文本逆归一化把一二三还原为123、恢复标点等然后计算 WER字符错误率。完整流程如下python tools/whisper_mix_normalize.py data/val_text.txt data/val_norm.txt python tools/whisper_mix_normalize.py output.txt output_norm.txt compute-wer data/val_norm.txt output_norm.txt cer.txt tail -n8 cer.txt前两行调用 tools/whisper_mix_normalize.py配合 cn_tn.py分别对参考标注与识别结果做逆归一化得到val_norm.txt与output_norm.txtcompute-wer是 kaldi 工具计算归一化后两者间的 CER输出到cer.txttail -n8 cer.txt查看汇总统计总字数、错误数、CER 百分比等。注意compute-wer属于 kaldi 工具链若环境中未安装 kaldi可使用 FunASR 内置的 WER 计算实现仓库 funasr/metrics/wer.py 提供了等价的计算逻辑或自行按编辑距离/总字数计算 CER。常见问题与注意事项结合上述源码与文档梳理几条实战中容易踩坑的点ID 对齐是硬约束train_wav.scp与train_text.txt必须行数相同、ID 一一对应且顺序一致否则scp2jsonl.py会报UTT mismatch并丢弃数据speech_length 依赖真实音频转换工具会实际读取音频时长来计算帧数因此转换阶段必须保证音频文件可访问本地存在或网络可达切勿在转换后再移动/删除音频batch_size6000 是 token 维度batch_typetoken下 batch 按 token 数切分显存紧张时可调小该值而不是调batch_size的条数语义freeze 与 LoRA 的搭配lora_onlytrue会冻结除 LoRA 适配器以外的全部参数如果只想冻结 LLM 基座而保持编码器可训练请使用lora_onlyfalse 显式设置各模块freezeLoRA checkpoint 的复用一致性LoRA 微调的 checkpoint 保存的是完整 state dict基座 适配器续训或解码时必须保持use_loratrue配置一致否则适配器参数无法被正确加载评测前务必逆归一化直接对原始输出计算 CER 会因数字/标点写法差异产生虚高错误率先过whisper_mix_normalize.py再算 WER 才是文档口径下的公平对比。至此从安装环境、ChatML 数据准备、scp2jsonl.py格式转换到finetune.sh全量/部分微调、lora_finetune.shLoRA 微调再到decode.py解码与 WER 评测Fun-ASR-Nano 的完整微调闭环已经打通。你可以基于上述流程把 Fun-ASR-Nano 快速适配到自己的垂直领域教育、金融、方言口音、专业术语等语音数据上。【免费下载链接】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),仅供参考
返回列表