十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

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

MedicalGPT 医疗大模型实战:基于 Qwen-7B 的增量预训练与监督微调全流程

MedicalGPT 医疗大模型实战:基于 Qwen-7B 的增量预训练与监督微调全流程 医疗大模型这两年从论文里的概念快速变成了工程落地的刚需尤其是中文医疗场景通用大模型直接拿来问诊、答病历、做分诊十有八九会翻车——要么答得太泛要么一本正经地胡说。MedicalGPT 这套开源方案之所以被反复提起就是因为它把领域适配这件事拆成了一条可复现的流水线增量预训练、监督微调、奖励建模、强化学习对齐一层层把通用底座往医疗领域拽。我前后用 Qwen-7B 作为底座完整跑过一遍中间踩的坑比想象中多从数据清洗到显存爆掉再到微调后模型变傻每一步都有讲究。这篇就把整个流程摊开讲清楚包括每一步为什么这么做、参数怎么定、哪些地方最容易出问题适合想自己动手训一个医疗领域模型、又不想被各种教程带偏的开发者参考。1. 先想清楚 MedicalGPT 到底在解决什么问题很多人一上来就急着 clone 仓库、下数据、开跑脚本结果跑到一半发现方向就不对。在动手之前得先弄明白一件事通用大模型和医疗领域模型之间的差距到底差在哪。1.1 通用模型的三个不达标我用 Qwen-7B 原始权重直接测过一批医疗问题问题集中在三个地方。第一是术语密度不够问社区获得性肺炎的经验性抗感染方案它会给你一段听起来很对但缺乏具体药物和剂量层次的回答因为它训练语料里这类高密度专业表达占比太低。第二是格式不规范医疗场景很多时候要的是结构化输出比如病历摘要、诊断依据、鉴别诊断列表通用模型习惯写成散文。第三是边界感缺失你问它一个超出能力范围的问题它不会说建议就医而是硬编一个答案这在医疗场景里是致命的。这三个问题对应到训练流程上就是三个不同的阶段去解决增量预训练补术语和领域知识监督微调补格式和对话能力对齐阶段补安全边界。MedicalGPT 的整个流水线设计本质上就是围绕这三点展开的。1.2 四个训练阶段的定位差异MedicalGPT 把训练拆成四个阶段每个阶段的目标和数据类型都不一样这点必须先理清楚否则很容易把数据喂错阶段。阶段目标数据形态典型数据量增量预训练注入医疗领域知识纯文本语料百万到千万级 token监督微调学会问答格式与指令跟随指令-回答对几万到几十万条奖励建模学会判断回答好坏偏好对比数据几千到几万条强化学习对齐人类偏好与安全偏好数据奖励模型同上这里有个常见的误解以为增量预训练可以跳过直接做监督微调就行。我实测过跳过增量预训练直接用几万条指令数据微调 Qwen-7B模型确实学会了医疗问答的腔调但一遇到需要具体知识的问题就露馅因为它只是学会了说话方式没真正吸收领域知识。所以如果算力允许增量预训练这一步别省。1.3 什么情况下可以裁剪流程不是所有人都需要跑完四个阶段。如果你的目标只是做一个医疗问答助手数据量在几万条量级那么增量预训练 监督微调两阶段基本够用奖励建模和强化学习可以跳过。强化学习那一套PPO/DPO对数据和算力要求都高而且调不好容易让模型输出变得保守、啰嗦。我个人的经验是先把前两阶段做扎实效果不满意再考虑对齐阶段别一上来就追求全流程。2. 环境与底座选型为什么是 Qwen-7B底座选型决定了后面所有工作的上限这一步选错后面再怎么调都是事倍功半。2.1 中文医疗场景下的底座对比我对比过几个常见底座在中文医疗语料上的表现结论比较明确。Qwen-7B中文原生训练充分词表对中文友好7B 参数量在单卡 24G 显存下可以做 LoRA 微调全量微调需要多卡。医疗术语的分词表现好这是它最大的优势。Baichuan 系列中文能力也不错但部分版本对商用有额外限制选之前要看清楚许可。LLaMA 系列英文强中文需要额外扩充词表或做大量中文增量预训练医疗中文场景下性价比不高。ChatGLM 系列中文对话能力好生态成熟但 6B 版本在知识密度上略逊于 Qwen-7B。综合下来Qwen-7B 是中文医疗场景下比较稳妥的选择词表对中文医疗术语的切分合理这一点在增量预训练阶段会直接影响知识注入效率。2.2 显存与硬件的现实约束这里必须说点实在的。7B 模型全量微调FP16 下光模型权重就要 14G 左右加上优化器状态、梯度、激活值单卡 24G 根本不够至少需要 2 张 24G 卡做 ZeRO-2 或 3。如果只有单卡那就走 LoRA 或 QLoRA 路线。我自己的配置是单张 24G 卡走的是 QLoRA4bit 量化 LoRA增量预训练阶段用 8bit 量化加载底座实测下来显存占用能压到 12G 左右batch size 设 1梯度累积 16勉强能跑。代价是训练速度慢一个 epoch 要跑十几个小时。如果预算允许多卡全量微调的效果确实比 LoRA 好尤其是增量预训练阶段LoRA 对知识注入的效果有限因为它只更新低秩矩阵底座权重冻结。提示增量预训练阶段如果只能用 LoRA建议把 rank 调大64 或 128target modules 覆盖所有线性层否则知识注入效果会打折扣。2.3 依赖环境的关键版本环境这块坑不少主要是 transformers、peft、bitsandbytes 这几个库的版本兼容问题。我踩过的坑是 bitsandbytes 版本和 CUDA 版本不匹配导致 4bit 量化加载直接报错。建议锁定一套经过验证的版本组合pip install torch2.1.0 transformers4.36.0 peft0.7.0 pip install bitsandbytes0.41.3 accelerate0.25.0 pip install datasets2.16.0 trl0.7.1CUDA 版本建议 11.8 或 12.1和 torch 版本对应上。别用最新的库医疗大模型训练流程里稳定比新特性重要得多。3. 增量预训练把医疗知识灌进底座增量预训练是整个流程里最重的一步也是最容易被低估的一步。很多人以为就是拿医疗文本继续训语言模型其实数据处理和训练策略都有讲究。3.1 医疗语料的来源与清洗语料质量直接决定知识注入效果。我用的语料主要来自几个方向公开的医学教材、临床指南、药品说明书、医学百科条目。这些数据的特点是专业密度高但格式杂乱清洗工作量很大。清洗流程我总结成四步去重用 MinHash 或 SimHash 做近似去重医疗语料里重复内容特别多不去重会导致模型对某些内容过拟合。去噪去掉 HTML 标签、页眉页脚、参考文献编号、乱码字符。这一步用正则加规则过滤别指望模型自己处理。长度过滤太短的片段少于 50 字信息量不足太长的超过 2048 token要切分。我一般保留 100 到 1500 字之间的段落。敏感信息脱敏如果语料里包含真实病例必须去掉姓名、身份证号、联系方式等个人信息这是底线。清洗完之后语料最好统一成纯文本每行一个段落方便后续 tokenize。3.2 训练目标与超参设置增量预训练用的是标准的因果语言建模目标也就是预测下一个 token。这里的关键是学习率要小因为底座已经训练得很充分了学习率太大会导致灾难性遗忘模型把通用能力丢掉。我的参数设置供参考学习率1e-5 到 2e-5比监督微调小一个量级训练轮数1 到 2 个 epoch多了容易过拟合序列长度2048医疗文本段落一般不会太长batch size根据显存尽量大配合梯度累积warmup总步数的 3% 到 5%权重衰减0.01这里有个经验增量预训练后一定要做通用能力回归测试。我遇到过训完医疗语料后模型连简单的常识问答都答不利索了这就是学习率太大导致的遗忘。解决办法是降低学习率或者在语料里混入 10% 到 20% 的通用语料做 rehearse让模型别忘了老本行。3.3 灾难性遗忘的监测方法监测遗忘不能只看训练 loss那个指标在增量预训练里参考价值有限。我的做法是准备一个小型评测集包含两部分一部分是医疗知识问答一部分是通用常识问答。每训完一个 checkpoint就在这个评测集上跑一遍看两部分的得分变化。如果医疗得分涨了但通用得分掉得厉害说明遗忘严重需要调小学习率或增加通用语料比例。如果两部分都没怎么涨说明学习率太小或者语料质量不行。这个监测流程虽然麻烦但能帮你及时止损避免白跑几十个小时。4. 监督微调让模型学会好好说话增量预训练解决的是知不知道监督微调解决的是会不会说。这一步的数据质量和格式设计直接决定模型最终好不好用。4.1 指令数据的构造逻辑医疗指令数据不是随便找些问答对就行得覆盖实际使用场景。我把指令数据分成几类知识问答直接问医学知识比如高血压的一线用药有哪些病历处理给一段病历让模型做摘要、提取诊断、生成出院小结分诊导诊根据症状描述判断该挂什么科用药咨询药物相互作用、剂量、禁忌安全拒答超出能力范围的问题模型应该引导就医每类数据的比例要平衡不能全是知识问答否则模型遇到病历处理就懵。我的经验比例是知识问答 40%、病历处理 25%、分诊导诊 15%、用药咨询 15%、安全拒答 5%。数据格式上MedicalGPT 用的是标准的指令模板把 system、instruction、input、output 拼成一条序列。这里要注意的是loss 只计算 output 部分instruction 和 input 部分要 mask 掉否则模型会学会复述问题而不是回答问题。4.2 LoRA 微调的参数取舍如果显存有限走 LoRA 路线参数设置有几个关键点rank8 到 64 之间医疗场景建议 32 起步任务越复杂 rank 越大alpha一般设为 rank 的 2 倍比如 rank32 时 alpha64dropout0.05 到 0.1防止过拟合target modules覆盖 q_proj、k_proj、v_proj、o_proj、gate_proj、up_proj、down_proj别只调 q 和 v我试过只调 q_proj 和 v_proj效果明显不如全线性层都调。原因是医疗任务需要模型在多个维度上调整只调注意力部分不够。学习率方面LoRA 可以用大一点1e-4 到 2e-4 都行因为只更新少量参数不容易破坏底座。训练轮数 2 到 3 个 epoch多了会过拟合表现为模型开始复读训练数据里的句子。4.3 微调后变傻的排查思路微调后模型变傻是高频问题表现是通用能力下降、回答变得机械、或者开始胡言乱语。排查思路我整理成一个顺序先看数据检查指令数据里有没有大量低质量、重复、格式错误的内容。数据脏是变傻最常见的原因。再看 loss 曲线如果训练 loss 降得很低但验证 loss 上升是过拟合减少 epoch 或加 dropout。检查 mask确认 loss 是不是只算在 output 上如果 instruction 部分没 mask模型会学歪。看学习率学习率太大也会导致变傻尤其是全量微调时。对比底座拿微调后的模型和底座在通用评测集上对比确认是微调导致的还是底座本身的问题。我踩过最坑的一次是数据里混进了一批格式错误的样本instruction 和 output 字段错位导致模型学会了答非所问。所以数据构造完之后一定要抽样人工检查别全信自动脚本。5. 奖励建模与强化学习对齐阶段的取舍对齐阶段是 MedicalGPT 流程里最高级的部分但也是最容易做无用功的部分。我的建议是前两阶段没做扎实之前别碰这一步。5.1 偏好数据的获取难点奖励建模需要偏好对比数据也就是同一个问题下的两个回答标注哪个更好。医疗场景下这种数据获取难度很大因为需要专业医生标注成本高、周期长。常见的替代方案是用强模型比如更大的模型或闭源模型生成回答然后用规则或弱模型做初筛人工只做抽检。但这样做的风险是偏好数据本身质量不高训出来的奖励模型学到的可能是像强模型而不是医学上正确。如果实在没有高质量偏好数据我建议跳过奖励建模直接用 DPODirect Preference Optimization做轻量对齐它对数据量的要求比 PPO 低训练也更稳定。5.2 PPO 与 DPO 的实操差异PPO 是经典方案但工程复杂度高需要同时加载策略模型、参考模型、奖励模型、价值模型显存占用大训练不稳定超参敏感。我跑 PPO 的时候光是调 KL 系数就花了好几天稍微大一点模型就输出退化小一点又没效果。DPO 相对简单不需要单独的奖励模型直接用偏好数据优化策略训练稳定得多。代价是对偏好数据的质量要求更高因为它是直接学偏好没有奖励模型做缓冲。维度PPODPO显存占用高4个模型中2个模型训练稳定性差超参敏感好数据要求偏好数据奖励模型高质量偏好数据调参难度高低我的建议是除非有充足算力和调参经验否则优先选 DPO。5.3 对齐阶段的收益边界对齐阶段能提升的是模型的表达偏好和安全边界比如让模型更倾向于给出结构化的、谨慎的回答遇到不确定的问题主动建议就医。但它不能提升模型的知识上限如果增量预训练和监督微调没做好对齐阶段再怎么调也救不回来。我见过有人把大量精力花在对齐上结果模型知识问答还是错漏百出这就是本末倒置。正确的顺序是先把知识和格式做扎实再用对齐阶段做锦上添花。6. 效果评估别只看 loss训练跑完不代表结束评估才是决定模型能不能用的关键。医疗场景的评估比通用场景更严格因为错误代价高。6.1 自动评估指标的局限自动评估常用 BLEU、ROUGE 这类指标但在医疗问答上参考价值有限。原因是医疗回答往往有多种正确表述字面匹配度低不代表回答错。我试过用 ROUGE 评估模型给出一个更简洁准确的回答得分反而比一个啰嗦但字面重合度高的回答低。更靠谱的做法是构建一个领域评测集包含标准问题和参考答案用强模型或人工做打分。评测集要覆盖前面提到的各类场景每个场景至少几十条才能看出模型在不同任务上的表现差异。6.2 人工评估的维度设计人工评估我设计了几个维度每个维度 1 到 5 分准确性医学知识是否正确有没有事实错误完整性是否覆盖了问题的关键点安全性有没有给出危险建议边界处理是否得当格式输出是否结构化、易读流畅度语言是否自然有没有复读或断裂评估时至少两人独立打分取平均减少主观偏差。如果条件允许找有医学背景的人参与普通标注员很难判断医学准确性。6.3 上线前的安全兜底医疗模型上线前必须做安全兜底这是底线。我的做法是在推理层加一层规则过滤涉及具体用药剂量的问题强制附带请遵医嘱提示涉及急症症状如胸痛、呼吸困难的问题强制引导立即就医模型输出置信度低或触发敏感词时走兜底话术这层规则不能替代模型本身的安全对齐但能作为最后一道防线。我见过模型在微调后偶尔输出不当建议的情况有了这层过滤至少不会造成直接风险。7. 我踩过的几个典型坑与应对最后分享几个实操中印象最深的坑都是文档里不会写、但实际一定会遇到的。7.1 数据格式错位导致的隐性故障前面提过一次这里再强调。指令数据的字段错位不会让训练报错loss 曲线看起来也正常但模型学出来的行为是错的。我的应对方法是写一个数据校验脚本检查每条样本的字段是否完整、instruction 和 output 是否为空、长度是否在合理范围。这个脚本花半小时写能省掉后面几天的排查时间。7.2 显存碎片导致的训练中断长时间训练时显存碎片会累积跑到一半突然 OOM。解决办法是设置PYTORCH_CUDA_ALLOC_CONFmax_split_size_mb:128减少碎片。另外 checkpoint 保存频率别太高保存本身也占显存。7.3 学习率调度器的选择增量预训练和监督微调用的调度器不一样。增量预训练建议用 cosine 加 warmup监督微调用 linear 加 warmup 也行。我试过用 constant 学习率效果明显差一截尤其是训练后期 loss 震荡。7.4 模型合并的注意事项LoRA 训完之后要合并回底座才能部署。合并时注意精度用 FP16 合并别用 4bit否则精度损失明显。合并后一定要重新跑一遍评测确认效果和合并前一致我遇到过合并后效果下降的情况原因是 peft 版本和 transformers 版本不兼容。这套流程我完整跑下来从数据准备到模型可用大概花了三周时间其中数据处理占了一半。医疗大模型的门槛不在训练脚本而在数据质量和流程理解。把每一步的为什么想清楚比盲目跑通脚本重要得多。后续如果要做多轮对话或者接入知识库可以在监督微调阶段加入多轮样本或者用 RAG 做知识增强这两条路我都试过各有适用场景有机会再展开聊。
返回列表