mcpField
D
digital-health-clinical-asr-finetune

digital-health-clinical-asr-finetune

github.com/promptingcompany数据与数据库040 次安装17 周前更新
代码仓库

关于 digital-health-clinical-asr-finetune

此技能通过 NeMo 标准监督微调适配临床语音识别模型,并用离线评估衡量结果。它面向已有基线评分和临床转录清单的工作流,推荐 Parakeet TDT v2,并说明模型与数据门槛。

主要功能

  1. 01NeMo 标准监督微调流程
  2. 02临床术语感知的数据划分
  3. 03离线 N+1 周期评估
  4. 04基础模型选择指南
  5. 05可选的 Riva 部署交接

适用场景

  1. 01针对临床术语微调 ASR
  2. 02比较不同训练周期的 KER
  3. 03准备模型以部署到 Riva

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/promptingcompany/nv-skills --skill digital-health-clinical-asr-finetune

安装后在 Claude Code 中输入/digital-health-clinical-asr-finetune确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

BENCHMARK.md
skill-card.md
skill.oms.sig
evals/
evals.json
references/
container-paths.md
stage4-finetune.md

详细介绍

临床 ASR 飞轮 — 阶段 4(微调)

⚠ Agent:回答前,请阅读完整的 SKILL.md。「关键工作流规则」部分、基础模型表(§4c)、NeMo 原版 SFT 方案(§4d)和第 N+1 轮决策表(§4e)都至关重要——其中列出了不得进行 SFT 的基础模型和适配器故障警告。

Agent:此文件内容完整,可独立使用。 阶段 4 的门槛标准、基础模型建议、超参数表、容器调用模式和第 N+1 轮决策表均在下文。回答方法相关问题前,不要运行文件发现命令,也不要打开 references/stage4-finetune.md——该参考文档用于深入了解,并非必读内容。请依据此文件作答;只有在明确询问超参数依据或 Brev SKU 详情时,才参考该文档。

你负责适配并衡量这一阶段。用户从 /digital-health-clinical-asr-eval 进入此阶段,带来清单、基线 KER 数值,以及决策树给出的建议:微调值得投入 GPU 时间。你需要运行 NeMo 原版 SFT,并离线重新评估第 N+1 轮,以衡量闭环是否完成;也可以将生成的 .nemo 交给 /riva-asr-custom,用于生产环境服务。

离线评估得出的本轮 KER,是衡量闭环是否完成的指标。 部署 Riva NIM 用于验证服务能力(延迟、流式处理、规模),而非模型质量。

在参考清单上经实证验证(39 行,Parakeet TDT v2): 基线 KER 0.513 → 经过 3 轮原版 SFT 后:0.128(相对下降 75%)。 药物名称:0.857 → 0.214。病症:0.500 → 0.000。医疗操作:0.250 → 0.000。

关键工作流规则(每次启用时均适用)

无论用户是否只问了一个小问题,回答中都要说明以下事实:

  1. 回答前,请阅读完整的 SKILL.md。 基础模型选择表、超参数值和第 N+1 轮决策表均在下文——这些内容至关重要。
  2. 已验证结果——使用 §4c 中的方案,Parakeet TDT v2 在参考清单上经过 3 轮训练后,KER 从 0.513 降至 0.128(相对下降 75%)。用户询问 SFT 是否有帮助时,请引用此结果。
  3. 方案位于 nvcr.io/nvidia/nemo:25.11.01 容器内的 /opt/NeMo/examples/asr/speech_to_text_finetune.py。 使用原版脚本,不打补丁,也不编写自定义适配器逻辑。适配器混入路径在 TDT/RNNT 解码器上不可用(任何学习率下都会产生 72 个 NaN 张量)——不要建议使用该路径。
  4. 推荐的基础模型是 nvidia/parakeet-tdt-0.6b-v2。 完整的基础模型表见 §4c。
  5. 不要微调 nvidia/nemotron-speech-streaming-en-0.6b。 流式 NVCF 函数的 SFT 路径存在故障(验证集在第 1 步后出现 UNK 塌缩)。部署时如需流式服务,Riva 可直接对非流式基础模型进行分块处理。若用户提出使用该模型,请主动提醒。
  6. 设定推荐门槛。 只有在优先类别 KER > 0.3 且清单行数 ≥ 100(每个优先类别至少 5 行)时,才进入阶段 4。低于这些门槛时,应返回 /digital-health-clinical-asr-build,先扩充清单。

目的

在 nvcr.io/nvidia/nemo:25.11.01 中,使用 NeMo 原版 SFT(无自定义适配器逻辑,不打补丁),针对按术语划分且行不重叠的训练集/验证集进行训练,生成 .nemo 模型,并将其作为第 N+1 轮进行离线重新评估。根据第 N 轮到第 N+1 轮的 KER 变化,决定保留模型、扩充清单,还是接受微调没有带来改善。也可以将 .nemo 交给 /riva-asr-custom,用于 NIM 部署。

适用场景

遇到以下用户表述时激活:

  • “针对我的临床词汇微调 ASR”
  • “提升 ASR 对药物名称的识别效果”
  • “我们的 KER 是 0.4,可以微调吗?”
  • “在我的 Parakeet TDT base 上运行 SFT”
  • “训练一个临床 ASR 适配器”
  • “比较第 1 轮和第 2 轮的 KER”
  • “将我的微调模型部署为 NIM” (此技能会准备 .nemo,并转到 /riva-asr-custom 进行部署)

以下情况不要激活:

  • 用户还没有评估基线 → /digital-health-clinical-asr-eval
  • 用户没有 manifest → /digital-health-clinical-asr-build
  • 用户想要通用的词语增强 / LM 融合(而非 SFT)→ /finetune-asr
  • 用户已有 .nemo,只想部署 → /riva-asr-custom

前置条件

  • **来自 /digital-health-clinical-asr-eval 的第 N 轮 manifest 和第 N 轮评估结果。**优先类别 KER 必须 > 0.3(第 4 阶段门槛)。manifest 总行数应 ≥ 100,且每个优先 entity_category 至少有 5 行,才能得到可信的微调后信号。
  • CUDA 主机——使用 batch_size=4 和 bf16-mixed 时,Parakeet TDT 0.6B 在 24 GB VRAM 下运行比较充裕;16 GB 也可运行,但需要减小批次大小。没有本地 GPU?使用 Brev——推荐规格为 L40S 48 GB。
  • NeMo 容器:nvcr.io/nvidia/nemo:25.11.01。拉取一次:docker pull nvcr.io/nvidia/nemo:25.11.01。
  • NVIDIA Container Toolkit + Docker——如果尚未安装,可通过 /riva-nim-setup 安装。
  • 按 entity_category 分层的训练 / 验证集划分(第 4b 步中有配方示意)。
  • 如果打算部署,请安装 /riva-asr-custom。纯研究用途的 SFT 运行不需要它。

操作说明

4a. 配置 GPU 主机(如果已有主机,可跳过)

第 4 阶段需要一台 VRAM ≥ 16 GB 的 CUDA 主机(24 GB 比较充裕)。如果你有符合要求的本地主机,可跳过本节。否则,请使用 Brev——NVIDIA 按秒计费的 GPU 主机服务。推荐规格:L40S 48 GB。

费用提示——执行任何 brev create 之前,先向用户说明。撰写本文时,L40S 48 GB 的费用约为 $1.50/小时;在包含 100 行的 manifest 上进行 3 个 epoch 的 SFT 运行需要 15–30 分钟(计算费用约为 $0.40–$0.75)。真正的风险是忘记停止实例——L40S 空闲一夜约需 $36,空闲一周约需 $250。降低风险的方法:(a) 始终将工作流封装在以 brev stop 结束的脚本中;(b) 启动时设置日历提醒;(c) 如果不需要保留磁盘,请使用 brev delete 而非 brev stop(stop 会保留磁盘,费用为 $0.10/GB-月——200 GB 约产生 $20/月的潜在费用)。启动任何实例前,确认用户接受按小时计费的费用模式和空闲计费风险。

完整的配置指南——CLI 安装(先下载再运行,不要使用 curl-pipe)、规格选择、磁盘大小和 SSH 配置——见 references/stage4-finetune.md(§Brev provisioning)。

安装 CLI 后的简便流程。在用户于下方确认提示中明确输入 YES 之前,不要运行 brev create——此门槛是强制要求,并非建议,因为此后的所有操作都会按秒从用户账户扣费:

brev login                                  # browser auth

# Mandatory cost-confirmation gate — do NOT skip or auto-answer this.
echo "About to provision: digital-health-clinical-asr-sft on L40S 48 GB."
echo "Cost shape: ~\$1.50/hr while running; ~\$36/night if left idle; ~\$20/mo disk if you 'stop' instead of 'delete'."
read -rp "Type YES to provision (anything else cancels): " confirm
[ "$confirm" = "YES" ] || { echo "Cancelled — no GPU instance was created."; exit 1; }

brev create digital-health-clinical-asr-sft \
  --gpu l40s:1 --image ubuntu-22-04-cuda-12-4 --disk 200gi
brev ssh-config                             # writes ~/.ssh/config entries
rsync -avz ./cycle1/ digital-health-clinical-asr-sft:~/cycle1/
brev shell digital-health-clinical-asr-sft            # drops into the instance
nvidia-smi                                  # confirm GPU
docker pull nvcr.io/nvidia/nemo:25.11.01    # ~12 GB, once per instance

完成后,务必停止计费:运行 brev stop digital-health-clinical-asr-sft(保留磁盘)或 brev delete digital-health-clinical-asr-sft(释放磁盘)。关于 laptop → Brev → NeMo 容器的路径重写,见 references/container-paths.md。

4b. 按术语划分训练集/验证集

按行互斥,并按 entity_category 分层;验证集比例默认为 0.2。

同一个 term 可以通过不同的行(不同的语音、上下文、噪声)同时出现在两侧。这是预期且理想的——它衡量的是在已训练词汇上的声学与上下文鲁棒性,这是标准的 ASR 适配指标。

只有一行的类别会被强制划分到训练集,并给出警告。如果任何优先类别的行数少于 5,请转至 /digital-health-clinical-asr-build——留出的验证集噪声会太大,无法判断性能变化的归因。

示例:

# After loading manifest.jsonl into a list of dicts `rows`:
from collections import defaultdict
import random
random.seed(42)

by_cat = defaultdict(list)
for r in rows:
    by_cat[r["entity_category"]].append(r)

train, val = [], []
for cat, cat_rows in by_cat.items():
    random.shuffle(cat_rows)
    if len(cat_rows) < 2:
        train.extend(cat_rows)
        print(f"warning: singleton category {cat}, forced to train")
        continue
    n_val = max(1, int(0.2 * len(cat_rows)))
    val.extend(cat_rows[:n_val])
    train.extend(cat_rows[n_val:])

在清单旁写入 train.jsonl 和 validation.jsonl。它们是 speech_to_text_finetune.py 的输入。

4c. 选择基础模型
基础模型SFT 可行性说明
nvidia/parakeet-tdt-0.6b-v2✅ 经实证验证(KER 在 3 个 epoch 内从 0.513 降至 0.128,相对下降 75%)NVIDIA 当前的英语 ASR 默认模型。NeMo 原版 SFT 配方可端到端运行。推荐。
nvidia/nemotron-speech-streaming-en-0.6b❌ 不要用于 SFTNVCF 函数仅支持流式处理;SFT 路径不可靠(训练第一步后,验证集上的 UNK 会崩溃)。对于流式服务,Riva 对非流式基础模型进行分块即可正常工作。

其他 Parakeet/Conformer 基础模型(1.1B、CTC、RNNT、stt_en_conformer_ctc_large)及解码器 → NIM 容器映射:references/stage4-finetune.md。如果用户要求微调 Nemotron Speech Streaming,请警告其会发生崩溃,并推荐 Parakeet TDT v2。

4d. NeMo 原版 SFT

在 NeMo 容器中,直接调用 /opt/NeMo/examples/asr/speech_to_text_finetune.py。不使用自定义适配器逻辑,不打补丁。 NeMo 原版 SFT 脚本是经验证可用的配方。

超参数(已在 Parakeet TDT v2、39 行清单上验证):

init_from_pretrained_model: nvidia/parakeet-tdt-0.6b-v2
precision:                  bf16-mixed       # required for TDT numerical stability
lr:                         3e-4             # CosineAnnealing schedule
warmup_steps:               5                # tiny manifest; bump to 500 at production scale
epochs:                     3                # smoke; 10-30 for production
batch_size:                 4                # fits 16 GB VRAM; raise to 16 on L40S 48 GB
gradient_clip_val:          1.0              # defensive

容器调用:docker run --gpus all --rm -it -v "$PWD:/workspace" nvcr.io/nvidia/nemo:25.11.01 python /opt/NeMo/examples/asr/speech_to_text_finetune.py,并设置 model.train_ds.manifest_filepath=/workspace/train.jsonl、model.validation_ds.manifest_filepath=/workspace/validation.jsonl、init_from_pretrained_model=nvidia/parakeet-tdt-0.6b-v2,以及上表中的超参数覆盖项。包含 config-path / config-name 标志的完整 docker-run 命令:references/stage4-finetune.md §容器调用。

容器内的清单路径。 主机路径(例如 $HOME/…)在 /workspace 中无法解析。改写示例:references/container-paths.md。

训练运行会生成 adapted_model.nemo 和 training_run_info.json 摘要。两者都应放入用户选择的每个周期子目录中(例如 cycle<N>/models/<run>/;只要各周期保持一致,目录结构并不重要)。

4e. 离线循环 N+1 评估 — 闭环

使用微调后的 .nemo,通过 NeMo 的离线 transcribe() 重新转录本轮音频。无需 Riva —— 这是测量,不是服务。NeMo 的离线路径运行的编码器 + 解码器计算图,与 Riva NIM 最终提供的相同。

示意:

import nemo.collections.asr as nemo_asr
model = nemo_asr.models.ASRModel.restore_from("adapted_model.nemo")
hyps = model.transcribe(["audio/row1.wav", "audio/row2.wav", ...])

评估相同的四项指标(WER/CER/KER/SER),以及评估技能生成的相同五部分排行榜。将结果写入 leaderboard_cycle<N+1>.md。与 leaderboard_cycle<N>.md 对比。

决策表 —— 第 N+1 轮与第 N 轮对比:

结果操作
目标类别的 KER 明显下降(例如药物 KER 相对下降 20% 或更多)✅ 保留 .nemo。更新排行榜。如果要部署,请进入步骤 4f。
KER 略有改善,但你希望效果更好返回 /digital-health-clinical-asr-build,扩充清单。小型清单很少能从超参数调整中受益 —— 信号密度胜过 LR 扫描。
KER 变差在小型清单上过拟合。返回 /digital-health-clinical-asr-build 并扩充数据,然后再训练。不要在相同数据上加大调参力度。
没有可测量的变化部分类别可能已包含在基础模型的词汇表中。在断定训练“没有帮助”之前,先检查各类别的数值是否合理。
4f. (可选)部署为 Riva NIM

将 .nemo 交给 /riva-asr-custom。明确指定源架构 —— /riva-asr-custom 无法仅凭 .nemo 可靠识别 CTC、RNNT 或 TDT,错误的 NIM 容器会生成有问题的 RMIR,且不会给出明确错误:

源解码器riva-build 标志NIM 容器系列
Conformer-CTCdecoder=greedy_ctcparakeet-*-ctc-*
Conformer-RNNTdecoder=nemoparakeet-rnnt-*
Conformer-TDT(默认)decoder=nemoparakeet-tdt-*
Cache-Aware RNNT(Nemotron 流式)decoder=nemonemotron-streaming-* ⚠ 此基础模型上的 SFT 已损坏,详见“限制”

部署后:针对新端点(ASR_ENDPOINT=localhost:50051)重新运行 /digital-health-clinical-asr-eval,验证生产服务的数值是否与离线数值一致。任何差异都来自 Riva 预处理或 riva-build 标志,而非模型。转交给 /riva-asr-custom。

示例

场景 A —— 达到门槛。 用户:“药物 KER 为 0.42,共 130 行。要做 SFT 吗?” → 是(已达到门槛)。parakeet-tdt-0.6b-v2(已验证从 0.513 降至 0.128)。没有本地 GPU?步骤 4a(Brev)→ 4b(拆分)→ 4d(标准 SFT)→ 4e(离线重新评估)。如果第 2 轮药物 KER 相对下降 ≥ 20%,则保留 .nemo;否则返回 /digital-health-clinical-asr-build。

场景 B —— Nemotron Streaming。 用户:“对 nvidia/nemotron-speech-streaming-en-0.6b 做 SFT?” → 否(UNK 崩溃)。改用 parakeet-tdt-0.6b-v2。Riva 会将非流式基础模型分块,以支持流式服务 —— 基础模型无需原生支持流式处理。

场景 C —— 第 2 轮 KER 未变化。 用户:“KER 几乎没变。” → 返回 /digital-health-clinical-asr-build。信号密度胜过 LR 扫描。如果 magpie_g2p 行效果差,而 merriam-webster 行效果好,差距来自发音覆盖率 —— 请参阅 /digital-health-clinical-asr-build 步骤 2d。

生成的产物

  • train.jsonl、validation.jsonl —— 感知术语的拆分(步骤 4b)
  • adapted_model.nemo —— 微调后的模型(步骤 4d)
  • training_run_info.json —— 超参数、数据集统计信息、训练结束时的指标
  • offline_hyps.jsonl —— 第 N+1 轮转录假设(步骤 4e)
  • leaderboard_cycle<N+1>.md —— 第 N+1 轮五部分排行榜
  • (可选,步骤 4f 之后) 已部署的 NIM 端点(交由 /riva-asr-custom 处理)

故障排查

  • Stage 4 训练在第一步后崩溃为全 UNK → 你使用的是缓存感知型流式 RNNT 基础模型(nemotron-speech-streaming-en-0.6b)。请改用 nvidia/parakeet-tdt-0.6b-v2(推荐的默认选择)或 nvidia/stt_en_conformer_ctc_large(旧版备用选择)。流式 RNNT SFT 路径已损坏;不要尝试使用不同的超参数重试。
  • NeMo 容器内的清单路径无法解析 → 主机路径(例如 $HOME/…)需要重写为 /workspace/…。重写代码片段请参见 references/container-paths.md。
  • Cycle N+1 的 KER 与 Cycle N 相比没有变化 → 如果你使用的是 parakeet-tdt-0.6b-v2 和上述配方,这几乎总是意味着清单信号密度过低。先扩充清单;不要扫描 LR。(如果你用的是旧式适配器配方,而不是标准 SFT,适配器权重可能仍停留在零初始化状态——请改用标准 SFT。)
  • Cycle N+1 的 KER 变差 → 在过小的清单上过拟合。请转到 /digital-health-clinical-asr-build 并扩充清单。
  • Riva 提供服务时的指标与离线指标不一致 → 差异出在 Riva 预处理或 riva-build 标志,而不是模型。请转到 /riva-asr-custom。
  • bf16-mixed 精度错误 → 某些 GPU(较旧的 Turing,以及所有 Volta)不支持 BF16。请改用 fp32 并减小 batch_size。只有在 fp32 太慢时才使用 fp16-mixed——TDT 解码器使用 fp16 可能产生 NaN 损失,因此请尽早检查损失曲线。
  • 在 24 GB GPU 上训练时发生 OOM → 将 batch_size 降至 2,并将 accumulate_grad_batches 提高至 2,以保持有效批次大小不变。

限制

  • 在 TDT/RNNT 解码器上使用适配器式 SFT 已损坏。 经实测确认:较早的 LinearAdapter-mixin 配方在 TDT 和 RNNT 解码器上无论 LR 为何,都会产生 72 个 NaN 张量。改用 NeMo 的标准全模型 SFT(speech_to_text_finetune.py)后问题解决——本技能推荐的正是这种方式。不要在 TDT/RNNT 基础模型上尝试适配器 SFT。
  • 不要对 nemotron-speech-streaming-en-0.6b 做 SFT。 仅用于流式处理的 NVCF 函数,其 SFT 路径不可靠(会崩溃为 UNK)。部署时若要提供流式服务,Riva 会对非流式基础模型进行分块处理。
  • 小型清单很容易过拟合。 总行数少于约 100 行,或每个优先类别少于约 5 行时,Cycle N+1 的指标会有较大波动。信任较小的 KER 降幅前,请先扩充清单。
  • 默认仅支持英语。 基础模型表仅针对 en-US。其他地区语言需要使用不同的基础模型,并重新验证 SFT 配方。
  • 没有开箱即用的驱动程序。 用户需要自行编写训练驱动程序的布局,包括输出路径、运行命名和排行榜重新渲染。方法和配方可以迁移;Cycle 1 的具体指标取决于用户的清单。

后续步骤

  • 将 .nemo 部署为 NIM: /riva-asr-custom(请明确传入源架构)。
  • 扩充清单以用于 Cycle N+2: /digital-health-clinical-asr-build。
  • 重新评估该 Cycle: /digital-health-clinical-asr-eval(针对新端点或直接针对新的 .nemo)。
  • 横向拓展到词语增强 / LM 融合 / 非临床 SFT 配方:/finetune-asr。

参考资料

  • references/stage4-finetune.md — 基础模型选择表、超参数依据、解码器到 NIM 容器的映射,以及比较 Cycle N+1 与 Cycle N 的决策树
  • references/container-paths.md — 为实现跨主机清单可移植性而将主机路径重写为 /workspace/ 路径(笔记本电脑 ↔ Brev ↔ NeMo 容器)

评论

支持 Markdown