通义千问1.5-1.8B-Chat-GPTQ-Int4微调实践:使用自定义数据提升垂直领域表现

📅 发布时间:2026/7/6 17:01:42 👁️ 浏览次数:
通义千问1.5-1.8B-Chat-GPTQ-Int4微调实践:使用自定义数据提升垂直领域表现
通义千问1.5-1.8B-Chat-GPTQ-Int4微调实践使用自定义数据提升垂直领域表现最近有不少朋友在问像通义千问这样的大模型虽然通用能力很强但一遇到自己行业里的专业问题回答就有点“飘”要么不够准要么干脆答非所问。这其实很正常通用模型毕竟不是行业专家。如果你也有类似的困扰比如想让模型更懂你的业务回答得更专业那么今天聊的这件事就特别适合你用你自己的数据去微调一个专属的模型。听起来很高深别担心我们不用从头训练一个模型那成本太高了。现在流行的是“轻量级微调”比如LoRA它就像给模型打一个“专业补丁”用很小的代价就能让模型学会新知识。今天我就手把手带你走一遍这个流程。我们会用通义千问1.5-1.8B-Chat这个已经量化好的轻量版模型在星图GPU平台上用你自己的数据给它“开小灶”让它在你关心的领域里表现更出色。整个过程从数据准备到训练评估我都会用大白话讲清楚。1. 为什么需要微调从“通才”到“专才”你可能用过很多大模型它们上知天文下知地理聊天写诗样样都行。但当你问它一个非常具体的专业问题比如“根据最新的会计准则这笔交易该如何确认收入”或者“这个病症的鉴别诊断要点是什么”它的回答可能就流于表面不够深入甚至会出现事实性错误。这是因为通用大模型是在海量、多样的互联网文本上训练的它的知识是广而泛的。它没有在你的专业数据集上“学习”过自然无法给出精准的答案。微调就是解决这个问题的钥匙。你可以把预训练好的大模型想象成一个天赋极高的“通才”学生它已经掌握了人类语言的基本规律和大量常识。微调就是请一位“行业导师”你的专业数据对这个学生进行一段时间的针对性辅导。辅导结束后这个学生就变成了既保有原来广博知识又在特定领域非常精通的“专才”。而LoRA这类方法可以理解为一种“高效辅导法”。它不改变学生大脑的核心结构模型的主体参数而是通过增加一些轻量的、可训练的“辅助模块”来吸收新知识。这样做的好处太多了训练快、资源省、效果好而且还能轻松切换——给同一个学生配上不同的“辅助模块”它就能胜任不同专业的工作。2. 动手之前环境与数据准备好了道理讲明白了我们开始动手。第一步是把“厨房”收拾好把“食材”准备好。2.1 搭建训练环境我们选择在星图GPU平台上进行主要是图个方便。它提供了现成的算力不用自己折腾显卡驱动和CUDA开箱即用。你只需要一个账号创建一个带GPU的容器实例就行过程就像租用一台云电脑非常简单。在容器内部我们需要安装必要的软件“厨具”。这里假设你已经有了基本的Python环境。# 1. 创建并激活一个独立的Python环境强烈推荐避免包冲突 conda create -n qwen_finetune python3.10 conda activate qwen_finetune # 2. 安装深度学习框架PyTorch请根据你的CUDA版本选择对应命令星图平台一般会提供 # 例如对于CUDA 11.8 pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118 # 3. 安装微调核心工具包 pip install transformers datasets peft accelerate # transformers: Hugging Face的模型库用来加载模型和分词器 # datasets: 方便地加载和处理数据集 # peft: 实现LoRA等高效微调方法的库 # accelerate: 简化分布式训练让代码更容易适配不同硬件 # 4. 安装其他可能需要的工具 pip install sentencepiece # 一些模型的分词器需要 pip install scikit-learn # 用于后续的评估指标计算环境搭好了就像厨房里锅碗瓢盆都齐了。接下来准备最重要的“食材”——数据。2.2 准备你的专属数据数据是微调的灵魂质量直接决定模型学成什么样。我们需要的格式很简单一段“对话”。通常我们准备一个JSON文件里面包含很多条这样的对话记录。每条记录大概长这样{ conversations: [ {role: user, content: 请问糖尿病患者在饮食上应该注意什么}, {role: assistant, content: 糖尿病患者饮食管理是关键需注意1. 控制总热量摄入保持理想体重2. 选择低升糖指数GI食物如全麦面包、燕麦3. 均衡营养保证优质蛋白和膳食纤维4. 严格限制添加糖和精制碳水5. 定时定量少食多餐。具体方案应咨询医生或营养师制定。} ] }这是一个简化的医疗问答例子。user是用户的问题assistant是你期望模型给出的理想答案。怎么准备这些数据呢来源可以是公司内部的客服问答记录、产品文档的QA、行业标准知识库或者你自己整理的问答对。数量对于LoRA微调几百到几千条高质量的数据通常就能看到明显效果。当然数据越多越丰富模型学得可能越好。质量要求准确性答案必须专业、正确。这是底线。多样性问题要覆盖你业务场景的各个方面不要过于单一。格式一致尽量保持问答风格的统一。准备好数据后我们通常会把它们分成三份训练集用于模型学习比如80%、验证集用于训练过程中检查模型学得怎么样防止“学过头”比如10%、测试集用于最终评估模型效果比如10%。3. 核心步骤模型加载与LoRA微调食材下锅开始烹饪。这一步是核心但有了现成的工具库代码并不复杂。3.1 加载模型与分词器我们使用的是通义千问1.5-1.8B-Chat的GPTQ-Int4量化版本。量化能让模型体积变小、运行速度变快非常适合我们这种资源有限的微调场景。from transformers import AutoTokenizer, AutoModelForCausalLM, BitsAndBytesConfig import torch # 1. 指定模型路径这里以Hugging Face模型库ID为例你需要替换为你的模型实际路径 model_name Qwen/Qwen1.5-1.8B-Chat-GPTQ-Int4 # 2. 加载分词器 tokenizer AutoTokenizer.from_pretrained(model_name, trust_remote_codeTrue) # 设置padding token有些模型需要 if tokenizer.pad_token is None: tokenizer.pad_token tokenizer.eos_token # 3. 以4bit量化方式加载模型极大节省显存 bnb_config BitsAndBytesConfig( load_in_4bitTrue, # 使用4bit量化加载 bnb_4bit_compute_dtypetorch.float16, # 计算时使用半精度浮点数 bnb_4bit_use_double_quantTrue, # 使用双重量化进一步压缩 bnb_4bit_quant_typenf4, # 一种高效的4bit量化类型 ) model AutoModelForCausalLM.from_pretrained( model_name, quantization_configbnb_config, # 应用量化配置 device_mapauto, # 自动将模型各部分分配到可用的GPU/CPU上 trust_remote_codeTrue ) model.eval() # 先设置为评估模式 print(模型与分词器加载完毕)3.2 应用LoRA配置现在我们给这个模型“装上”LoRA训练模块。我们只训练这部分新增的小参数模型原有的绝大部分参数都被“冻结”住不动。from peft import LoraConfig, get_peft_model, TaskType # 1. 定义LoRA配置 lora_config LoraConfig( task_typeTaskType.CAUSAL_LM, # 因果语言模型任务 inference_modeFalse, # 训练模式 r8, # LoRA的秩rank可以理解为“补丁”的复杂度通常8、16、32试试 lora_alpha32, # 缩放参数一般设置为r的两倍或相近值 lora_dropout0.1, # Dropout率防止过拟合 target_modules[q_proj, k_proj, v_proj, o_proj], # 将LoRA模块应用到Transformer的注意力层 ) # 2. 将LoRA配置应用到原模型上得到可训练的PEFT模型 model get_peft_model(model, lora_config) model.print_trainable_parameters() # 打印可训练参数数量你会发现只占原模型的0.1%左右3.3 准备数据与训练接下来我们要用之前准备好的“食材”数据来“训练”烹饪模型了。from datasets import load_dataset from transformers import DataCollatorForLanguageModeling, TrainingArguments, Trainer # 1. 加载你的数据集假设你的数据是JSON格式并且已经分成了train和validation data_files {train: path/to/your_train.json, validation: path/to/your_val.json} dataset load_dataset(json, data_filesdata_files) # 2. 对数据进行预处理和分词 def tokenize_function(examples): # 将对话拼接成模型需要的格式。通义千问Chat模型通常有特定的模板这里需要根据模型文档调整。 # 以下是一个通用示例实际请参考Qwen官方文档的对话格式。 texts [] for conv in examples[conversations]: # 简单拼接实际应用需按模型要求格式化 text tokenizer.apply_chat_template(conv, tokenizeFalse, add_generation_promptFalse) texts.append(text) return tokenizer(texts, truncationTrue, paddingmax_length, max_length512) # 设置最大长度 tokenized_datasets dataset.map(tokenize_function, batchedTrue, remove_columnsdataset[train].column_names) # 3. 设置训练参数 training_args TrainingArguments( output_dir./qwen-lora-finetuned, # 输出目录 num_train_epochs3, # 训练轮数根据数据量调整 per_device_train_batch_size4, # 每个GPU的批次大小根据显存调整 per_device_eval_batch_size4, gradient_accumulation_steps4, # 梯度累积模拟更大的批次 warmup_steps100, # 学习率预热步数 logging_steps50, # 每50步打印一次日志 evaluation_strategysteps, # 按步数进行评估 eval_steps200, # 每200步评估一次 save_strategysteps, save_steps500, learning_rate2e-4, # 学习率LoRA常用范围1e-4到5e-4 fp16True, # 使用混合精度训练节省显存加快速度 push_to_hubFalse, # 是否上传到Hugging Face Hub report_tonone, # 不报告给其他平台 ) # 4. 创建数据收集器 data_collator DataCollatorForLanguageModeling(tokenizertokenizer, mlmFalse) # mlmFalse 表示是因果语言模型 # 5. 创建Trainer并开始训练 trainer Trainer( modelmodel, argstraining_args, train_datasettokenized_datasets[train], eval_datasettokenized_datasets[validation], data_collatordata_collator, tokenizertokenizer, ) trainer.train()训练过程会在终端打印日志你可以看到损失loss在下降这表示模型正在从你的数据中学习。训练完成后模型会保存在output_dir指定的目录下。4. 效果评估与使用看看“专才”表现如何训练完了我们得考考这个“学生”看看它在你专业领域里是不是真的变厉害了。4.1 加载微调后的模型并测试训练保存的其实是LoRA的权重那个“补丁”我们需要把它和原模型结合起来使用。from peft import PeftModel # 1. 加载原始基础模型同样用4bit量化 base_model AutoModelForCausalLM.from_pretrained( model_name, quantization_configbnb_config, device_mapauto, trust_remote_codeTrue ) # 2. 加载训练好的LoRA权重并与基础模型合并 fine_tuned_model PeftModel.from_pretrained(base_model, ./qwen-lora-finetuned/checkpoint-xxx) # 替换为你的checkpoint路径 fine_tuned_model fine_tuned_model.merge_and_unload() # 将LoRA权重合并进原模型方便后续推理 # 3. 准备一个测试问题 test_question 请简要说明有限责任公司和股份有限公司在股东责任上的主要区别。 # 按照模型的对话模板格式化输入 messages [{role: user, content: test_question}] text tokenizer.apply_chat_template(messages, tokenizeFalse, add_generation_promptTrue) # 4. 让模型生成回答 inputs tokenizer(text, return_tensorspt).to(fine_tuned_model.device) with torch.no_grad(): outputs fine_tuned_model.generate(**inputs, max_new_tokens256, do_sampleTrue, temperature0.7) response tokenizer.decode(outputs[0][inputs[input_ids].shape[1]:], skip_special_tokensTrue) print(f问题{test_question}) print(f微调模型回答{response}) # 5. 可选对比一下原始模型的回答 base_model.eval() with torch.no_grad(): outputs_base base_model.generate(**inputs, max_new_tokens256, do_sampleTrue, temperature0.7) response_base tokenizer.decode(outputs_base[0][inputs[input_ids].shape[1]:], skip_special_tokensTrue) print(f原始模型回答{response_base})通过对比你应该能发现微调后的模型在专业问题的回答上术语更准确逻辑更清晰更像一个“业内人士”。而原始模型的回答可能更笼统或者包含一些不相关的信息。4.2 更系统的评估除了直观感受我们还可以用一些量化指标来评估比如BLEU / ROUGE比较生成答案和标准答案的文本相似度。精确匹配Exact Match答案是否完全正确。人工评估这是最可靠的方法。找几位领域专家从“准确性”、“专业性”、“完整性”、“流畅性”等维度给模型的回答打分。你可以从测试集中拿出一部分问题用微调前后的模型分别生成答案然后进行上述对比评估用数据来证明微调的效果。5. 一些实践心得与避坑指南走完整个流程你可能已经成功了。这里再分享几点我的心得体会希望能帮你少走弯路。第一数据质量大于数量。一百条清洗干净、标注精准的数据胜过一万条噪音大、答案模糊的数据。在准备数据阶段多花点时间后面训练会顺利很多。第二从小的配置开始实验。一开始不要把训练轮数epoch设得太高r值LoRA秩也可以从8开始尝试。先用一小部分数据跑一个epoch看看损失曲线是否正常下降生成的结果有没有改善。没问题了再上全量数据。第三注意过拟合。如果模型在训练集上表现很好但在验证集上表现变差那就是过拟合了。可以尝试增加LoRA的dropout率或者收集更多样化的训练数据。第四对话格式要对。不同的Chat模型Qwen, Llama, ChatGLM有自己约定的对话模板。一定要按照你所用模型的官方文档来格式化你的输入否则模型可能无法正确理解对话上下文。最后微调不是一劳永逸的。你的业务知识在更新模型也需要定期用新数据“复习”一下。可以把微调看作一个持续迭代的过程。获取更多AI镜像想探索更多AI镜像和应用场景访问 CSDN星图镜像广场提供丰富的预置镜像覆盖大模型推理、图像生成、视频生成、模型微调等多个领域支持一键部署。