资讯动态

InternLM2-Chat-1.8B模型微调入门教程:基于自有数据提升垂直领域表现

发布时间:2026/8/21 1:02:29 来源:尧图企业网站定制
InternLM2-Chat-1.8B模型微调入门教程基于自有数据提升垂直领域表现你是不是也遇到过这种情况用通用的大模型来回答你专业领域的问题结果它要么答非所问要么给出的答案过于宽泛不够精准比如你问一个医疗相关的问题它可能给你一堆从网上搜罗来的、未经验证的常识性信息而不是你想要的、基于最新临床指南或专业文献的答案。这就是通用大模型在垂直领域面临的挑战。它们“知道”的很多但“精通”的很少。好消息是现在我们可以通过一种叫做“微调”的技术让大模型变得更“懂”你的专业。今天我就带你手把手地用你自己的数据给InternLM2-Chat-1.8B这个轻量级模型“开个小灶”让它在你关心的领域里表现得更出色。整个过程并不复杂你不需要是机器学习专家只要会写点Python代码跟着步骤走就能搞定。我们会用到一些高效的微调方法比如QLoRA它能让你用相对较少的计算资源比如在星图GPU平台上租用一张显卡就完成训练。下面我们就从准备数据开始。1. 环境准备与数据格式在开始训练之前我们得先把“厨房”收拾好把“食材”备齐。这里说的厨房就是我们的编程环境食材就是我们要用来训练模型的自有数据。1.1 快速搭建Python环境首先确保你有一个Python环境版本建议在3.8到3.10之间。然后我们需要安装几个核心的库。打开你的终端或命令行执行下面的命令pip install torch transformers datasets peft accelerate bitsandbytes简单解释一下这几个库是干什么的torch: PyTorch深度学习框架是模型训练的基础。transformers: Hugging Face出品的库里面包含了InternLM2等成千上万个预训练模型我们直接调用就行。datasets: 同样是Hugging Face的库方便我们加载和处理数据集。peft: 这个库是实现高效微调如LoRA、QLoRA的关键能大幅减少训练所需的显存。accelerate: 帮助简化分布式训练和混合精度训练的流程。bitsandbytes: 支持8-bit量化是QLoRA技术的重要组成部分能进一步节省显存。安装过程可能会花几分钟取决于你的网络。安装完成后我们的基础环境就准备好了。1.2 准备你的专属数据JSONL格式数据是微调的“燃料”。为了让模型学会你的专业领域知识你需要准备一个问答对形式的数据集。最推荐也最常用的格式是JSONLJSON Lines简单说就是每行都是一个独立的JSON对象。假设你是一个医疗领域的从业者想提升模型在疾病诊断建议方面的能力。你的数据可能长这样我们把它保存为medical_finetune_data.jsonl{instruction: 患者男性45岁突发胸痛伴大汗2小时。心电图显示V1-V4导联ST段弓背向上抬高。最可能的诊断是什么, output: 根据提供的临床表现突发胸痛、大汗及心电图特征V1-V4导联ST段抬高最可能的诊断是急性前壁心肌梗死。需要立即启动胸痛中心流程评估再灌注治疗如急诊PCI或溶栓的指征。} {instruction: 简述2型糖尿病的一线口服降糖药物及其主要作用机制。, output: 2型糖尿病的一线口服降糖药物通常是二甲双胍。其主要作用机制包括1. 抑制肝脏糖异生减少肝糖输出2. 提高外周组织如肌肉对胰岛素的敏感性促进葡萄糖摄取和利用3. 轻度抑制肠道对葡萄糖的吸收。它不刺激胰岛素分泌因此单独使用低血糖风险较低。} {instruction: 解读以下血常规结果白细胞 12.5 x10^9/L中性粒细胞百分比 85%淋巴细胞百分比 10%。, output: 该血常规提示白细胞总数升高正常值通常为4-10 x10^9/L伴中性粒细胞百分比显著增高淋巴细胞百分比相对降低。此模式最常见于急性细菌性感染。需要结合患者发热、咳嗽、咳痰等具体症状和体征进一步明确感染部位。}数据准备的几个关键点字段名通常使用instruction指令/问题和output期望的输出/答案。有些微调脚本也支持input和response等但instruction-output对是最通用和简单的。数据质量答案output要准确、专业最好是你领域内的权威知识。数据量从几百条到几千条都能起到效果质量比数量更重要。多样性问题instruction要覆盖你希望模型掌握的各个子方向。比如医疗领域可以包含诊断、治疗、用药、检查解读、健康咨询等。格式检查确保你的JSONL文件每行都是有效的JSON没有多余的逗号或格式错误。可以用在线的JSON验证工具检查一下。好了环境和数据都准备好了接下来我们看看怎么用高效的方法来训练模型。2. 理解高效微调QLoRA是什么直接对整个拥有18亿参数的大模型进行微调需要巨大的显存成本很高。QLoRAQuantized Low-Rank Adaptation就是一种“四两拨千斤”的技术。你可以把它想象成我们不是去修改模型这本“大百科全书”的每一页内容那工作量太大了而是给它附上一本小小的、针对特定领域的“补充手册”。训练时模型主要参考这本“补充手册”而“大百科全书”本身被压缩量化后保持不变大大节省了空间。具体来说量化Quantization将模型权重从高精度如FP16转换为低精度如INT8/INT4。就像把高清图片压缩成体积更小的文件虽然损失了一点细节但核心信息还在能极大减少显存占用。低秩适配LoRA不在原始模型庞大的权重矩阵上直接动刀而是引入一对小的、可训练的“低秩矩阵”。训练时只更新这两个小矩阵的参数。原本需要训练18亿个参数现在可能只需要训练几百万个效率提升成百上千倍。QLoRA结合了这两者让我们能在消费级显卡如24GB显存的RTX 4090上微调大模型。在星图GPU平台上你可以选择对应显存的实例性价比很高。3. 编写微调脚本理论懂了我们来动手写代码。创建一个Python文件比如叫做finetune_internlm.py。3.1 导入必要的库和加载模型import torch from transformers import AutoTokenizer, AutoModelForCausalLM, TrainingArguments from peft import LoraConfig, get_peft_model, TaskType from datasets import Dataset import json # 1. 加载预训练模型和分词器 model_name “internlm/internlm2-chat-1_8b” # Hugging Face模型ID tokenizer AutoTokenizer.from_pretrained(model_name, trust_remote_codeTrue) model AutoModelForCausalLM.from_pretrained( model_name, trust_remote_codeTrue, torch_dtypetorch.float16, # 使用半精度节省显存 device_map“auto” # 自动分配模型层到可用设备GPU/CPU ) # 设置pad_token如果模型没有的话 if tokenizer.pad_token is None: tokenizer.pad_token tokenizer.eos_token这里我们加载了InternLM2-Chat-1.8B的模型和分词器。torch_dtypetorch.float16使用半精度浮点数是节省显存的常见操作。device_map“auto”让accelerate库帮我们自动把模型放到GPU上。3.2 配置QLoRA参数# 2. 配置QLoRA参数 lora_config LoraConfig( task_typeTaskType.CAUSAL_LM, # 因果语言模型任务 r8, # LoRA的秩rank越小参数量越少通常8-32之间 lora_alpha32, # 缩放参数一般设置为r的2-4倍 lora_dropout0.1, # Dropout率防止过拟合 target_modules[“q_proj”, “k_proj”, “v_proj”, “o_proj”], # 对Transformer的注意力模块应用LoRA bias“none” ) # 将原始模型转换为PEFT参数高效微调模型 model get_peft_model(model, lora_config) model.print_trainable_parameters() # 打印可训练参数量你会看到它变得非常小LoraConfig是核心。r8是LoRA的秩决定了小矩阵的大小。target_modules指定了将LoRA适配器加到模型的哪些层上对于InternLM2这类模型通常加到注意力机制的查询Q、键K、值V和输出O投影层上。运行print_trainable_parameters()后你会发现可训练参数可能只占模型总参数的0.1%左右这就是高效所在。3.3 加载和预处理数据# 3. 加载和预处理数据 def load_data_from_jsonl(file_path): data [] with open(file_path, ‘r’, encoding‘utf-8’) as f: for line in f: data.append(json.loads(line.strip())) return data # 假设你的数据文件叫 ‘medical_finetune_data.jsonl’ train_data load_data_from_jsonl(‘medical_finetune_data.jsonl’) # 将数据转换为Hugging Face Dataset格式 dataset Dataset.from_list(train_data) # 定义数据预处理函数 def preprocess_function(examples): # 将instruction和output组合成模型训练的文本格式 # InternLM2-Chat的对话格式通常为|im_start|user\n{instruction}|im_end|\n|im_start|assistant\n{output}|im_end| texts [] for instr, out in zip(examples[‘instruction’], examples[‘output’]): text f“|im_start|user\n{instr}|im_end|\n|im_start|assistant\n{out}|im_end|” texts.append(text) # 使用分词器进行编码 model_inputs tokenizer(texts, max_length512, truncationTrue, padding“max_length”) # 标签就是输入本身对于因果语言模型目标是预测下一个token model_inputs[“labels”] model_inputs[“input_ids”].copy() return model_inputs # 应用预处理函数 tokenized_dataset dataset.map(preprocess_function, batchedTrue)这里的关键是preprocess_function。我们需要按照InternLM2-Chat模型预期的对话格式来组装文本。不同的模型可能有不同的特殊标记如|im_start|你需要查阅模型的文档。预处理后我们得到了模型可以直接用于训练的input_ids输入token序列和labels训练目标也是同样的token序列。3.4 配置训练参数并开始训练# 4. 配置训练参数 training_args TrainingArguments( output_dir“./internlm2-1.8b-medical-finetuned”, # 输出目录 num_train_epochs3, # 训练轮数根据数据量调整通常3-5轮 per_device_train_batch_size4, # 每个GPU的批次大小根据显存调整 gradient_accumulation_steps4, # 梯度累积步数模拟更大批次 warmup_steps100, # 学习率预热步数 logging_steps10, # 每多少步打印一次日志 save_steps200, # 每多少步保存一次检查点 learning_rate2e-4, # 学习率QLoRA常用范围1e-4到5e-4 fp16True, # 使用混合精度训练节省显存并加速 optim“paged_adamw_8bit”, # 使用8-bit优化器进一步省显存 report_to“none”, # 不向外部平台报告本地运行更简单 ) # 5. 创建训练器并开始训练 from transformers import Trainer trainer Trainer( modelmodel, argstraining_args, train_datasettokenized_dataset, data_collatorlambda data: {‘input_ids’: torch.stack([torch.tensor(d[‘input_ids’]) for d in data]), ‘attention_mask’: torch.stack([torch.tensor(d[‘attention_mask’]) for d in data]), ‘labels’: torch.stack([torch.tensor(d[‘labels’]) for d in data])} ) trainer.train()TrainingArguments里的参数需要根据你的硬件主要是GPU显存和数据量来调整per_device_train_batch_size: 批次大小如果遇到CUDA out of memory错误就调小这个值。gradient_accumulation_steps: 梯度累积。假设你想用批次大小16但显存只够4那么可以设置batch_size4和gradient_accumulation_steps4效果上等同于每4步累积一次梯度再更新模拟了批次大小16。learning_rate: QLoRA训练的学习率通常比全参数微调大一点。fp16和optim“paged_adamw_8bit”都是为了在有限显存下进行训练的重要设置。运行这个脚本训练就开始了。你会在终端看到损失loss逐渐下降的日志。4. 测试微调后的模型训练完成后模型会保存在output_dir指定的目录里。我们来写个简单的测试脚本看看效果。# test_model.py from transformers import AutoTokenizer, AutoModelForCausalLM from peft import PeftModel import torch # 加载基础模型 base_model_name “internlm/internlm2-chat-1_8b” tokenizer AutoTokenizer.from_pretrained(base_model_name, trust_remote_codeTrue) base_model AutoModelForCausalLM.from_pretrained( base_model_name, trust_remote_codeTrue, torch_dtypetorch.float16, device_map“auto” ) # 加载微调后的LoRA权重 model PeftModel.from_pretrained(base_model, “./internlm2-1.8b-medical-finetuned”) model model.merge_and_unload() # 将LoRA权重合并到基础模型中便于后续推理 # 切换到评估模式 model.eval() # 测试问题 test_question “用户高血压患者服用缬沙坦后出现干咳可能的原因是什么如何处理\n助手” inputs tokenizer(test_question, return_tensors“pt”).to(model.device) with torch.no_grad(): outputs model.generate(**inputs, max_new_tokens200, temperature0.7, do_sampleTrue) response tokenizer.decode(outputs[0], skip_special_tokensTrue) print(“模型回答”) print(response)注意我们使用PeftModel.from_pretrained加载的是保存的适配器权重也就是那本“补充手册”。merge_and_unload()方法将LoRA权重合并回基础模型得到一个完整的、微调后的新模型这样推理速度更快。5. 微调实践中的小技巧走完整个流程你可能还想知道怎么做得更好。这里分享几个我实践中的心得数据方面少而精初期不用追求上万条数据。精心准备500-1000条高质量、多样化的数据效果可能比几千条杂乱数据好得多。格式一致确保你的instruction清晰明确。可以模仿你最终希望用户提问的方式。比如法律领域可以用“根据《XX法》第X条...应如何认定”这样的句式。数据增强如果数据量实在有限可以对现有数据进行同义句改写、角色互换如把“医生回答患者”改为“患者询问医生”等方式来扩充。训练方面学习率与轮数learning_rate在1e-4到5e-4之间多尝试。num_train_epochs通常3-5轮可以观察训练损失曲线如果损失不再明显下降就可以停止了防止过拟合。批次大小在显存允许的前提下尽量用大一点的per_device_train_batch_size训练更稳定。不够就用gradient_accumulation_steps来凑。保存检查点save_steps设置一个合理的值定期保存模型。这样如果训练中断可以从最近的检查点恢复不用重头再来。评估方面定性评估像我们上面那样手动准备一些测试问题对比微调前后模型的回答。这是最直接的方法。定量评估可选如果你的领域有标准的评测集比如医疗QA的MedQA可以用它来跑分看准确率等指标是否有提升。但这需要额外的脚本和数据集。整个过程跑下来你会发现用自有数据微调一个大模型并没有想象中那么遥不可及。核心就是准备好高质量、格式正确的数据然后利用QLoRA这样的高效技术在有限的资源下进行训练。微调后的模型在特定领域内的回答会显得更专业、更靠谱更像一个“领域专家”而不是一个“泛泛而谈的万事通”。获取更多AI镜像想探索更多AI镜像和应用场景访问 CSDN星图镜像广场提供丰富的预置镜像覆盖大模型推理、图像生成、视频生成、模型微调等多个领域支持一键部署。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价