简介llm-medical-data是一套面向大模型微调训练的医疗数据集主要服务需要真实医疗语料进行模型优化的数据科学家、医学研究人员以及处于入门阶段的个人学习者。资源围绕临床诊疗场景整理了患者基本信息、病史、检查结果、治疗过程与药物反应等多维数据覆盖妇产科、外科、儿科、肿瘤科、内科、男科等不同专科并提供中文医疗对话、huatuo-llama、medicalgpt、doctorchat等多个子集可支撑对话生成、医学问答、文本翻译等任务的微调与评估。压缩包共34个文件大小约224.51MB以JSON、CSV格式为主辅以Python脚本如csv2json、对话生成工具、ZIP子包、文本说明与Markdown文档便于数据转换、二次处理与快速上手。目前已有204人学习适合作为个人学习大模型微调技术的实战数据集。通过该数据集读者可获得覆盖多科室的医疗对话语料及配套处理脚本直接用于大模型微调训练既可增强模型在诊断建议、药物反应预测等临床场景的表现也可作为医学数据分析和临床研究的实验样本与基线参考。1. 医疗数据集做微调先别急着跑训练九成问题出在数据本身手里攒了一批医疗问答、病历摘要或者检查报告想拿开源大模型做指令微调结果跑出来的模型要么一本正经胡说八道要么连“空腹血糖正常范围”都能答错。这个 llm-medical-data 方向本质上是把散落的医疗文本整理成模型能学进去的“教材”再通过微调让模型学会医学表达和推理习惯。它解决的是通用模型“什么都懂一点、但医疗场景不敢用”的尴尬——通用模型缺乏领域内的术语体系、剂量判断和诊断逻辑而这些恰恰是医疗数据集能喂进去的东西。适合谁做手头有医疗文本资源、想给大模型做领域化的算法工程师、数据工程师或者医院信息科想落地临床辅助问答的团队。本文不聊大而全的医疗 AI 平台只聚焦一件事把 llm-medical-data 这类数据集从原始文本变成能直接送进 Trainer 的训练语料以及过程中那些让人翻车的细节。2. 医疗数据集的“长相”为什么必须是 JSONL 指令对而不是一堆 PDF2.1 微调真正需要的数据形态指令、输入、输出三段式结构大模型微调无论是全参数微调还是 LoRA吃的不是自然语言文档而是结构化的“问题—答案”对。医疗数据集最常见的标准格式是 JSONL每行一个完整的 JSON 对象包含instruction指令、input可选上下文、output标准答案。这个结构对应的是开源社区里 ChatML 或 Alpaca 格式的对话模板。举个例子一条合格的医疗微调样本长这样{ instruction: 根据患者的症状和既往病史给出初步诊断建议和下一步检查方案。, input: 患者女35岁反复低热两周伴夜间盗汗、体重下降3kg既往有糖尿病病史血糖控制欠佳。, output: 初步考虑结核病可能建议行胸部CT、PPD试验、痰涂片抗酸染色同时查糖化血红蛋白评估血糖控制情况。注意排除糖尿病合并感染。 }这段结构的逻辑是instruction定义任务类型input提供不可省略的临床信息output是医生或权威资料给出的标准回答。训练时模型学到的是“看到这种提问方式和临床描述 → 给出这样结构化的回答”。如果instruction写成“请回答以下问题”input写成“高血压怎么治”output写“吃降压药”那模型学到的就是不对的——医学回答必须带上剂量范围、禁忌症、随访建议而不是一句泛泛的结论。参数上有三个点值得注意每条样本的output建议在 50—500 字之间太短学不到推理过程太长训练成本高且容易让模型学会啰嗦input字段可以为空纯问答对但医疗场景下强烈建议保留上下文因为临床问题几乎都依赖病史信息JSON 里的字段名可以自定义但主流训练框架LLaMA-Factory、transformers 的 SFTTrainer默认读取 instruction/input/output改字段名需要同步改模板配置。2.2 医疗数据的“加餐”从单轮到多轮对话从问答到结构化输出纯单轮问答对只是入门。真正让模型在医疗场景里“能用”的 llm-medical-data 数据集通常包含三类扩展形态。第一类是多轮对话conversation。比如患者连续追问“这个药用多久”“停药后会反弹吗”“孕期能不能用”——每轮对话之间相互依赖模型需要学会指代消解“这个药”指代上一轮提到的药名和追问逻辑。格式上表现为conversations数组每个元素带fromhuman 或 gpt和value。训练时的 attention mask 会区分用户轮和模型轮只对模型回复计算损失这一点在用 LLaMA-Factory 的 ShareGPT 格式时要确认mask_history已开启。第二类是结构化输出样本。医疗场景经常需要模型填表——影像学报告结构化、入院记录抽取、药品说明书关键字段识别。这种样本的output建议用 JSON 或 Markdown 表格格式模型会模仿格式化输出。比如注入检查报告文本要求输出{器官: 肺部, 病灶位置: 右上肺, 大小: 3.2cm×2.8cm}。这类数据很稀缺但微调后模型在信息抽取上的表现提升最明显因为通用模型的 JSON 输出不稳医疗格式的 JSON 更是抖。第三类是“思维链”式样本。给模型看医生的推理过程从主诉→鉴别诊断→辅助检查→初步方案。不需要写严格的 COT 标签直接把推理步骤按段落写在output里就行。实测下来这类样本占比在 10%—20% 时模型回答的条理性最好超过 30% 会让模型过度解释连“多喝水”都要写三百字。3. 从原始医疗文本到干净训练集清洗、脱敏与归一化的完整管线3.1 文本清洗搞定格式噪音、单位错乱和“假段落”真实世界的医疗文本——无论是从 HIS 系统导出的病历、体检中心的 PDF 报告还是医学教材扫描件转出的 OCR 文本——都带着大量噪音。常见的有全角半角混用、药品剂量单位不统一mg 和毫克混写、检查值范围带全角冒号、段落间夹着页眉页脚和“第 X 页共 X 页”。我一般先跑一个清洗脚本分四步处理import re import unicodedata def clean_medical_text(raw: str) - str: # 1. 统一为半角字符中文标点除外 text unicodedata.normalize(NFKC, raw) # 2. 去掉页眉页脚/水印类行 text re.sub(r(第\s*\d\s*页\s*共\s*\d\s*页|医院名称|影像号[:]?\S), , text) # 3. 统一剂量单位全角/半角括号、大小写 mg text re.sub(r[(\[]\s*(mg|ml|g|μg|ug)\s*[)\]], lambda m: m.group(1), text, flagsre.I) # 4. 压缩多余空行和行首行尾空白 text re.sub(r\n\s*\n, \n, text).strip() return textNFKC这一步能顺带把全角数字、字母换成半角对后续模型 tokenizer 更友好。单位正则只是最小集合真正跑之前要统计语料里出现过的所有单位写法常见坑是 “ug” 和 “μg” 混用、 “0.5 ML” 大写、 “mg / kg” 中间带空格。这一步不需要处理语义只需要保证格式一致。清洗完做一次人工抽检。按 1% 比例随机抽样每 1000 条里挑 10 条看有没有把“无”和“无异常”清洗成空有没有把“糖尿病”里的“尿”字被半角转换破坏抽检不是为了完美是为了确认清洗规则没有误伤临床语义。3.2 敏感信息脱敏这不是合规问题是数据能不能出团队的问题医疗数据最大的风险不是模型训歪而是患者隐私。姓名、身份证号、手机号、住院号、社保卡号甚至患者住址都可能躺在病历文本里。脱敏不能简单用正则匹配“姓名两个汉字”这种规则——会误伤医生姓名、药名“阿司匹林”里也带“司”。推荐的做法是规则 模型双保险def deidentify(text: str) - str: # 规则层先干掉显式标识符 patterns { id_card: r\d{17}[\dXx], phone: r1[3-9]\d{9}, hospital_no: r(住院号|病历号)[:]\s*\d{4,}, } for key, pat in patterns.items(): text re.sub(pat, f[{key}], text) # 模型层标注用规则筛不干净的人工看 return text规则层处理能正则覆盖的内容处理完后的文本仍然可能包含“张先生”“李大爷”这类称谓。我的经验是把所有“姓称谓”统一替换成“患者”这个操作要放在清洗之后否则会把“糖皮质激素”这类词里的“激素”拆坏。脱敏的结果必须记录成 pipeline 的一个中间产物不要只保留最终文件——一旦发现脱敏遗漏还能回溯定位是哪个规则没生效。医疗数据集的版本管理不是 git 能完全解决的至少要在目录结构里带上规则版本号和运行日期。3.3 标签归一化与 SNOMED CT 对齐让模型学会“说人话”医疗术语的写法五花八门“冠心病”也叫“冠状动脉粥样硬化性心脏病”“心肌梗死”在病历里可能简写成“心梗”。如果数据集里的术语不归一模型微调后会在回答里混用简称和全称甚至把两个术语当成不同疾病。这也是医疗术语集 SNOMED CT 及相关热词在这个方向被频繁提起的原因——重要的不是让你把每条数据都打上 SNOMED CT 编码而是利用它的层级关系做术语归一。实操中我只对高频术语做归一化。把病历里出现频率 Top 500 的疾病名、药名、检查名拉出来建一张同义映射表{ source: 心梗, target: 急性心肌梗死, category: disease }然后跑一遍替换。这里有个血泪教训替换不能只做完全匹配。病历里写的是“心梗后”“心梗患者”直接替换成“急性心肌梗死后”没问题但如果写成“陈旧性心梗”归一化后“陈旧性急性心肌梗死”就病句了。所以归一化建议只作用于独立词边界且替换后要再过一遍清洗函数。SNOMED CT 的全量编码映射我一般不做成本高且收效有限。实用做法是只对模型最终要面向用户输出的核心术语做编码映射比如模型回答中涉及“高血压”“2型糖尿病”这类高频词在训练样本里统一附上 SNOMED CT 的 preferred term至于诊断编码ICD-10属于另一套体系除非要做 DRG 分组或病案首页相关任务否则不需要塞进微调数据里。4. 用 LLaMA-Factory 跑通 llm-medical-data 微调最小可复现的配置4.1 数据集格式转换从 JSONL 到 LLaMA-Factory 注册表LLaMA-Factory 是目前微调开源 LLM 最省事的中文友好工具。它要求数据集注册在一个 dataset_info.json 里并指定文件路径、格式模板alpaca 或 sharegpt、列名映射。把整理好的医疗 JSONL 注册进去就是微调前的最后一步。假设你的数据文件是medical_qa.jsonl每条长这样{instruction: 请对以下检验结果进行解读, input: 空腹血糖 7.2mmol/L, output: 空腹血糖偏高正常范围为 3.9-6.1mmol/L。结合症状及其他检查结果建议复查并进一步查糖化血红蛋白。}在 LLaMA-Factory 的data/dataset_info.json里追加{ medical_qa: { file_name: medical_qa.jsonl, formatting: alpaca, columns: { prompt: instruction, query: input, response: output } } }这里formatting: alpaca告诉框架把 instruction 当系统提示、input 当用户输入、output 当标准回答。如果用 sharegpt 格式列名就要换成conversations且每条数据内嵌多轮结构。注册完成后用框架自带的llamafactory-cli train启动训练。参数选择是我实际跑过之后确认比较稳的一组llamafactory-cli train \ --model_name_or_path Qwen/Qwen2.5-7B-Instruct \ --dataset medical_qa \ --template qwen \ --finetuning_type lora \ --lora_rank 8 \ --lora_alpha 16 \ --learning_rate 1e-4 \ --num_train_epochs 3 \ --max_samples 100000 \ --per_device_train_batch_size 4 \ --gradient_accumulation_steps 8 \ --max_length 2048 \ --output_dir outputs/medical_loralora_rank取 8 是医疗数据微调的下限偏低时模型学不到术语间的复杂关系往上调到 16、32 效果提升有限但显存占用上涨明显。learning_rate不要超过 2e-4医疗数据量通常不大几万到十几万条学习率过大会让模型直接用数据覆盖掉基座模型的通用能力训完连“请写一首诗”都接不上。max_length按你的样本长度分布来——统计 95 分位长度超过太多就截断不要贪长。医疗问答样本超过 2048 token 的比例很低设 2048 在效果和算力之间最均衡。4.2 训练完先做三类样本验证再决定要不要合并权重LoRA 训练结束后不急着合并。先用 PEFT 加载训练好的 adapter 做推理验证。验证样本分三类训练集内样本看模型是否“记住”了答案、同分布新样本从测试集抽、对抗样本故意改掉患者年龄、性别、用药剂量看模型会不会被带偏。对抗样本尤其值得做医疗模型的鲁棒性问题在“患者性别从男改成女模型仍然给出完全相同的用药建议”这类例子上暴露得最明显。llamafactory-cli chat \ --model_name_or_path Qwen/Qwen2.5-7B-Instruct \ --adapter_name_or_path outputs/medical_lora \ --template qwen进入交互后分别问三个问题训练集里有的原题、换了数字的同题、一个完全不相关的通用问题。第三种决定了模型有没有发生灾难性遗忘。如果通用问题答得逻辑混乱说明训练超参太激进——降低学习率、减少 epoch 或增加通用语料混合比。合并权重用 export 命令合并后再评估一次因为 merge 过程本身偶尔会引入参数数值精度问题极小概率但合并后的推理结果和 adapter 模式不一致时,优先查 merge 步骤。4.3 医疗微调的量化与导出跑得动比跑得对更重要微调完的模型要落地通常得量化。7B 的 LoRA 合并后 FP16 权重接近 15GB单卡推理勉强部署到 CPU 或边缘端就吃力。主流做法是合并后用 llama.cpp 转 GGUF 做 4bit 量化。这个步骤放在 LLM 微调之后、应用对接之前——量化会损失部分精度医疗场景下必须先量化再评估不能用 FP16 的评估结果替代量化后的效果。llama.cpp/convert_hf_to_gguf.py merged_model --outfile medical_qwen.gguf --outtype q4_k_mQ4_K_M 是医疗文本场景下质量/体积比最合适的量化档位。Q2_K 体积更小但术语准确率下降明显实测 SNOMED CT 术语的生成正确率掉了约 4%——在医疗场景里这不可接受。量化完做一轮测试集评估确认掉点后再走 API 封装或接 Ollama 做本地推理验证。如果你的使用场景能上 GPUFP16 能留就留量化始终是最后一步妥协。5. 医疗微调避坑指南五条真实踩过的坑与对应解法5.1 数据泄漏验证集分数虚高上线就现形现象训练时验证集 loss 下降得很漂亮用户问什么都能答得接近标准答案但换一批新患者数据就垮掉。原因很多公开医疗数据集本身是从同一批患者病历里切出来的我把验证集单纯按行随机分割导致同一患者的多条咨询记录同时出现在训练和验证集里——模型相当于做过原题。解决按患者 ID 分组切分。没有 ID 时用文本向量的近邻去重把相似度超过 0.85 的样本归为同一患者组再按组分割。分割后检查验证集里的患者 ID 是否在训练集里出现过保证零交集。这个操作务必放在所有清洗和归一化之前因为归一化后两条记录会变得更容易“看起来不像同一人”。5.2 幻觉剂量模型学会了病名却编造了用药浓度现象数据集里“0.9% 氯化钠注射液”标注规范模型训练后输出“0.9% 氯化钠 500ml 口服”——浓度和给药途径组合出错了。原因清洗阶段的归一化把浓度百分比格式统一了但没做“药品—浓度—给药方式”三元组的有效性校验模型学到了“氯化钠”和“0.9%”共现频率高却不知道“口服”和“500ml”搭配在此语境下不成立。解决在数据集构建阶段增加一组规则校验对每一条包含药品剂量信息的样本做正则检查(体积) (给药途径)组合是否符合常识口服对应的是片剂、胶囊注射对应的是注射液规格。不符合的样本要么人工修正要么直接丢弃。这步会砍掉大约 3%—5% 的数据但值得。宁可数据少一点不能脏一点。5.3 术语冲突同一疾病两种叫法模型来回横跳现象对“心梗”这个问题模型有时答“急性心肌梗死”有时答“心肌梗塞”——而且是在同一轮对话里改口。原因数据集里归一化没做完整训练样本中“心梗”和“心肌梗死”各占一半模型学到的是两种表达可以互换而不是它们是同一个概念的不同表达。解决回到 3.3 节的高频术语归一化把“心肌梗塞/心梗/急性心梗”统一映射到标准目标术语然后重新训练。注意这个重新训练不需要全部重来可以在 LoRA 权重基础上继续训 0.5—1 个 epoch只更换术语相关的训练样本。我试过从零训和继续训两种路径第二次的效果在术语一致性上几乎一样。5.4 过拟合训练 loss 趋近于 0验证集表现踩踏式下跌现象医学数据集的答案往往规范性很高同一诊断标准答案重复出现3 个 epoch 后模型开始“背诵”标准答案遇到稍微换花样的问法就答非所问。原因epoch 数设太高 数据重复度高。医疗标准答案天然是低熵的——“正常值范围”“诊断标准”反反复复就那几句话模型很快就把这些背下来了但这不是泛化。解决把 epoch 降到 2或者把训练集里高度重复的标准答案类样本做近义改写把“血压正常范围是收缩压 90-139mmHg”改写成“正常血压的收缩压范围在 90 到 139 之间”。我一般把重复样本控制在 5% 以内改写交给 GPT-4o人工抽检确认没有新增医学错误后再混入训练集。5.5 灾难性遗忘医疗能力涨了通用能力没了现象微调后模型能完美回答“房颤抗凝方案”但“帮我写个冒泡排序”或者“解释什么是光合作用”这种基础问题反而变得语无伦次。原因训练集全是医疗数据模型在 3 个 epoch 里把原来学到的通用知识覆盖了。这在小学习率 少 epoch 的 LoRA 里不常见但数据量超过 20 万条或者数据集里只有单一任务类型时风险显著上升。解决标准做法是混合通用数据。从开源通用指令集里抽 5%—10% 的数据拼到医疗数据集里比例可以按“医疗数据的损失不再下降时的通用数据占比”来调。我常用的起始比例是 20:1医疗通用效果不够再加。另外把学习率调回 8e-5 到 1e-4 区间给通用知识留一点“不被覆盖”的余地。验证时除了医疗测试集必须保留一个通用能力抽查集20—50 条每次训练完都刷一遍。6. 从数据集到医生认可医学验证的最后一公里模型在测试集上跑出高分不等于医生愿意用。医疗场景的评估必须回到临床视角用真实的病例做盲测。我习惯的做法是拉 100 份不参与训练的门诊病历去掉诊断结论让模型生成初步诊断建议再请两位主治以上医生对“诊断合理性”“检查建议准确性”“用药安全性”三个维度打分1—5 分。三个维度都达到平均 4 分以上模型才具备被医生“勉强看一眼”的资格。单独看诊断准确性最容易自我感觉良好但医生其实最在意用药安全——剂量、相互作用、禁忌症是硬底线。评估过程里最容易被忽略的是模型说“不确定”的能力。医疗 LLM 最难教的不是知识而是知道什么时候该停。数据集中要刻意放入“信息不足无法判断”这一类样本例如{ instruction: 根据现有信息给出诊断建议, input: 患者肚子疼, output: 信息不足。需要补充疼痛部位、性质、持续时间及伴随症状后才能给出初步判断。 }这类样本占比往 5%—8% 做模型在真实问诊里才不会硬编。医学本质是“先排除最危险的可能再考虑常见病”模型如果能学会在信息不足时追问或明确说“无法判断”哪怕准确性没有显著提升医生的信任度也会明显改善。这也是 llm-medical-data 这类数据集的长期价值所在不追求所有问题都答对先做到不该答的不乱答。如果你顺着这个方案把数据管线跑通了下一步可以试试针对特定科室心内科、内分泌科建垂直子集做二次微调或结合最新热词里提到的方言医疗咨询做语音侧微调。我在这条路上踩过的坑大部分都不是模型结构问题而是数据里藏着的临床细节。希望帮到你。本文还有配套的精品资源点击获取
