专门做外贸的网站汕头seo外包
专门做外贸的网站,汕头seo外包,四站合一网站建设,京推推cms网站建设通义千问1.5-1.8B-Chat-GInt4实战#xff1a;基于Transformer的文本分类任务微调
最近在做一个智能客服的项目#xff0c;需要把用户的问题自动分到不同的业务类别里#xff0c;比如“查询订单”、“投诉建议”、“产品咨询”这些。一开始想用规则或者传统机器学习模型&…通义千问1.5-1.8B-Chat-GInt4实战基于Transformer的文本分类任务微调最近在做一个智能客服的项目需要把用户的问题自动分到不同的业务类别里比如“查询订单”、“投诉建议”、“产品咨询”这些。一开始想用规则或者传统机器学习模型但发现用户问法千奇百怪效果总是不理想。后来就想能不能用现在很火的大语言模型来做这件事正好看到了通义千问开源的1.5-1.8B-Chat-GInt4这个模型体积不大但能力挺均衡特别适合我们这种资源有限的场景。最关键的是它基于经典的Transformer架构这意味着我们可以很方便地把它“改造”成一个文本分类专家。今天我就来分享一下怎么把这个通用聊天模型微调成专属于你业务领域的文本分类能手。整个过程就像教一个聪明的实习生熟悉你的业务一样既有意思效果也出奇的好。1. 为什么选择通义千问做文本分类你可能会有疑问文本分类不是有BERT、RoBERTa这些专门的模型吗为什么还要用通义千问这种聊天模型来微调我用下来的感受是这就像用瑞士军刀和专用工具的区别。专门的文本分类模型比如BERT在它训练好的任务上可能很锋利但泛化能力和理解复杂语境的能力往往不如经过海量数据“熏陶”过的大语言模型。通义千问1.5-1.8B-Chat-GInt4这个版本有几个点特别吸引我模型大小适中1.8B的参数在消费级显卡比如RTX 3090/4090上就能跑起来做微调也不会太吃力非常适合个人开发者或中小团队。聊天能力基础它本身是为了对话训练的所以对语言的理解、对上下文的把握能力比较强。这让它在判断一些模棱两可、需要推理的文本类别时有天然优势。GInt4量化这个版本用了4-bit的量化技术简单说就是在几乎不损失精度的情况下让模型变得更小、推理更快。这对后续部署上线非常友好。Transformer架构这是最关键的一点。Transformer就像积木的标准接口基于它构建的模型其微调方法、工具链都非常成熟和统一。我们用的Hugging Face生态里的所有工具都能无缝对接。所以我们的核心思路就是利用通义千问已经具备的强大语言理解能力作为“底座”通过微调让它的“思考”方式稍微偏一偏专注于为我们做分类决策。2. 动手之前环境与数据准备理论说再多不如动手试一次。我们先来看看需要准备些什么。2.1 搭建你的微调实验环境微调不需要特别高端的机器但有一个带GPU的电脑会快很多。以下是核心的软件准备# 1. 创建并激活一个Python虚拟环境推荐 python -m venv qwen_finetune_env source qwen_finetune_env/bin/activate # Linux/Mac # 或者 qwen_finetune_env\Scripts\activate # Windows # 2. 安装核心库 pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118 # 根据你的CUDA版本调整 pip install transformers datasets accelerate peft pip install sentencepiece protobuf # 通义千问分词器依赖 pip install scikit-learn # 用于评估指标这里重点说一下几个库transformers Hugging Face的核心提供了模型加载、训练和评估的一切。datasets 方便我们加载和处理数据集。accelerate 让训练代码轻松适应不同的硬件单卡、多卡、CPU。peft 这是我们实现高效微调比如LoRA的秘密武器后面会详细讲。2.2 准备你的定制数据集模型就像学生数据集就是教材。教材的质量直接决定学生学得怎么样。假设我们要做一个电商客服问题分类数据集大概长这样我们可以用一个CSV文件或者直接用Python列表来定义。这里我用一个简单的例子import pandas as pd # 模拟一个电商客服问答分类数据集 data { text: [ 我昨天买的衣服什么时候能发货, 这件衣服的材质是什么是纯棉的吗, 我要投诉快递员态度非常差, 订单号123456帮我查一下物流到哪了, 这款手机有优惠券吗, 怎么申请退货流程是怎样的, 你们家的会员有什么特权, 我收到的商品和图片颜色不一样怎么办, 忘记登录密码了如何找回, 可以开发票吗发票类型怎么选 ], label: [ 物流查询, 商品咨询, 投诉建议, 物流查询, 促销活动, 售后服务, 会员服务, 售后投诉, 账户问题, 发票服务 ] } df pd.DataFrame(data) print(df.head())数据准备的几个关键点类别均衡尽量让每个类别的样本数量差不多。如果“物流查询”有1000条而“发票服务”只有10条模型就会偏向前者。文本质量清洗一下数据比如去掉无关的特殊字符、乱码。但也要保留必要的口语化表达因为真实用户就是这么说话的。划分数据集通常按8:1:1的比例随机划分成训练集、验证集和测试集。训练集用来教模型验证集用来在训练过程中检查模型学得怎么样防止过拟合测试集是最终考试看模型真实水平。from sklearn.model_selection import train_test_split train_df, temp_df train_test_split(df, test_size0.2, random_state42, stratifydf[label]) val_df, test_df train_test_split(temp_df, test_size0.5, random_state42, stratifytemp_df[label]) print(f训练集: {len(train_df)} 条) print(f验证集: {len(val_df)} 条) print(f测试集: {len(test_df)} 条)3. 两种微调策略全参数微调 vs. LoRA高效微调环境数据都准备好了接下来就是关键的微调环节。这里我给你两种方案一种是“大力出奇迹”的全参数微调另一种是“四两拨千斤”的LoRA微调。3.1 方案一全参数微调 - 彻底的改造全参数微调顾名思义就是把预训练好的通义千问模型全部参数都拿出来用你的新数据重新训练一遍。这相当于让模型“重新学习”但学习的方向由你的数据集主导。优点效果通常最好模型能最大程度地适应你的特定任务。缺点消耗资源大需要更多显存训练时间长而且可能会让模型“忘记”它之前学到的通用知识这叫做灾难性遗忘。如果你的数据集比较大比如几万条以上并且任务和你数据分布差异很大可以考虑这种方式。from transformers import AutoTokenizer, AutoModelForCausalLM, TrainingArguments, Trainer from datasets import Dataset # 1. 加载模型和分词器 model_name Qwen/Qwen1.5-1.8B-Chat-GInt4 tokenizer AutoTokenizer.from_pretrained(model_name, trust_remote_codeTrue) # 注意对于全参数微调我们加载原始模型而非GInt4量化版因为训练需要更精确的计算。 # 实际中你可能需要加载“Qwen/Qwen1.5-1.8B-Chat”训练完再量化。这里为演示流程先按此思路。 model AutoModelForCausalLM.from_pretrained(model_name, trust_remote_codeTrue) # 2. 将分类任务构造成语言模型任务 # 思路把分类变成“问答”。例如“文本{text}\n类别” 让模型生成 “{label}” def preprocess_function(examples): # 构造输入文本 inputs [f文本{text}\n类别 for text in examples[text]] # 对输入进行编码 model_inputs tokenizer(inputs, max_length128, truncationTrue, paddingmax_length) # 将标签作为目标输出进行编码 labels tokenizer(examples[label], max_length16, truncationTrue, paddingmax_length) # 将标签设置为模型需要学习的部分 model_inputs[labels] labels[input_ids] return model_inputs # 转换pandas DataFrame为Hugging Face Dataset格式 train_dataset Dataset.from_pandas(train_df) val_dataset Dataset.from_pandas(val_df) tokenized_train train_dataset.map(preprocess_function, batchedTrue) tokenized_val val_dataset.map(preprocess_function, batchedTrue) # 3. 设置训练参数 training_args TrainingArguments( output_dir./qwen_text_classification_full, # 输出目录 evaluation_strategyepoch, # 每个epoch后在验证集评估 save_strategyepoch, # 每个epoch保存模型 learning_rate5e-5, # 学习率全微调可以小一点 per_device_train_batch_size4, # 根据你的GPU调整 per_device_eval_batch_size4, num_train_epochs3, # 训练轮数 weight_decay0.01, # 权重衰减防止过拟合 logging_dir./logs, logging_steps10, load_best_model_at_endTrue, # 训练结束后加载最佳模型 ) # 4. 创建Trainer并开始训练 trainer Trainer( modelmodel, argstraining_args, train_datasettokenized_train, eval_datasettokenized_val, tokenizertokenizer, ) trainer.train()3.2 方案二LoRA微调 - 高效且轻量的选择这是我更推荐大多数人的方法尤其是当你资源有限、或者想快速实验的时候。LoRALow-Rank Adaptation的思想很巧妙它不去动模型那庞大的原始参数而是在模型旁边附加一些小的、可训练的“适配层”。训练时只训练这些新增的小参数。因为要动的参数极少通常只有原模型的0.1%-1%所以训练速度极快显存占用也小得多而且几乎不会导致模型遗忘原有知识。from transformers import AutoTokenizer, AutoModelForCausalLM, TrainingArguments, Trainer from peft import LoraConfig, get_peft_model, TaskType from datasets import Dataset # 1. 加载模型和分词器同样训练时建议用非量化版本 model_name Qwen/Qwen1.5-1.8B-Chat tokenizer AutoTokenizer.from_pretrained(model_name, trust_remote_codeTrue) model AutoModelForCausalLM.from_pretrained(model_name, trust_remote_codeTrue) # 2. 配置LoRA lora_config LoraConfig( task_typeTaskType.CAUSAL_LM, # 因果语言模型任务 r8, # LoRA的秩影响参数量大小通常8、16、32 lora_alpha32, # 缩放参数 lora_dropout0.1, # Dropout概率 target_modules[q_proj, v_proj], # 对Transformer里的哪些模块应用LoRA通常是注意力层的Q, V矩阵 ) # 将原模型包装为PEFT模型 model get_peft_model(model, lora_config) model.print_trainable_parameters() # 打印可训练参数你会发现只占原模型的很小一部分 # 3. 数据预处理同全参数微调 def preprocess_function(examples): inputs [f文本{text}\n类别 for text in examples[text]] model_inputs tokenizer(inputs, max_length128, truncationTrue, paddingmax_length) labels tokenizer(examples[label], max_length16, truncationTrue, paddingmax_length) model_inputs[labels] labels[input_ids] return model_inputs train_dataset Dataset.from_pandas(train_df) val_dataset Dataset.from_pandas(val_df) tokenized_train train_dataset.map(preprocess_function, batchedTrue) tokenized_val val_dataset.map(preprocess_function, batchedTrue) # 4. 设置训练参数学习率可以设大一点 training_args TrainingArguments( output_dir./qwen_text_classification_lora, evaluation_strategyepoch, save_strategyepoch, learning_rate1e-4, # LoRA微调学习率可以稍大 per_device_train_batch_size8, # LoRA更省显存batch可以大一些 per_device_eval_batch_size8, num_train_epochs5, weight_decay0.01, logging_dir./logs, logging_steps10, load_best_model_at_endTrue, ) # 5. 创建Trainer并训练 trainer Trainer( modelmodel, argstraining_args, train_datasettokenized_train, eval_datasettokenized_val, tokenizertokenizer, ) trainer.train() # 6. 保存LoRA适配器权重非常小 model.save_pretrained(./qwen_lora_adapter)用LoRA训练完后你会得到一个小小的适配器文件通常就几MB到几十MB。使用时需要先加载原始的大模型再把这个小适配器“贴”上去模型就拥有了你的分类能力。4. 模型评估与效果验证模型训练完了不能光看训练损失下降就高兴得拉出来在测试集上“考一考”。对于分类任务最常用的指标就是准确率、精确率、召回率和F1分数。import numpy as np from sklearn.metrics import accuracy_score, classification_report # 假设我们已经用训练好的模型对测试集进行了预测 # 这里演示评估流程实际预测需要运行模型推理 def evaluate_model(model, tokenizer, test_df): all_predictions [] all_true_labels [] for _, row in test_df.iterrows(): # 构造输入 input_text f文本{row[text]}\n类别 inputs tokenizer(input_text, return_tensorspt).to(model.device) # 模型生成 with torch.no_grad(): outputs model.generate(**inputs, max_new_tokens10) # 限制生成长度 # 解码预测结果 prediction tokenizer.decode(outputs[0], skip_special_tokensTrue) # 提取生成的类别简单处理取“类别”后面的部分 predicted_label prediction.split(类别)[-1].strip() all_predictions.append(predicted_label) all_true_labels.append(row[label]) # 计算指标 accuracy accuracy_score(all_true_labels, all_predictions) print(f测试集准确率: {accuracy:.4f}) print(\n详细分类报告:) print(classification_report(all_true_labels, all_predictions)) return all_predictions # 加载训练好的模型以LoRA为例 from peft import PeftModel base_model AutoModelForCausalLM.from_pretrained(Qwen/Qwen1.5-1.8B-Chat, trust_remote_codeTrue) model PeftModel.from_pretrained(base_model, ./qwen_lora_adapter) model.eval() # 进行评估 predictions evaluate_model(model, tokenizer, test_df)看看输出报告你就能清楚地知道模型在哪个类别上表现好哪个类别上容易混淆。比如可能“物流查询”和“售后服务”有时候会被模型搞混因为用户可能同时问这两个问题。这时候你就需要回头检查数据或者考虑是否需要调整类别定义。5. 模型部署与应用推理模型验证效果不错接下来就是把它用起来。部署的方式有很多这里介绍两种最直接的。方式一脚本直接调用适合内部测试或小规模应用。就是把训练和保存模型的代码封装成一个预测函数。class TextClassifier: def __init__(self, base_model_path, lora_adapter_path): self.tokenizer AutoTokenizer.from_pretrained(base_model_path, trust_remote_codeTrue) base_model AutoModelForCausalLM.from_pretrained(base_model_path, trust_remote_codeTrue) self.model PeftModel.from_pretrained(base_model, lora_adapter_path) self.model.eval() # 如果有GPU移到GPU上 if torch.cuda.is_available(): self.model.cuda() def predict(self, text): input_text f文本{text}\n类别 inputs self.tokenizer(input_text, return_tensorspt) if torch.cuda.is_available(): inputs {k: v.cuda() for k, v in inputs.items()} with torch.no_grad(): outputs self.model.generate(**inputs, max_new_tokens10, do_sampleFalse) # 关闭采样获得确定性结果 prediction self.tokenizer.decode(outputs[0], skip_special_tokensTrue) predicted_label prediction.split(类别)[-1].strip() return predicted_label # 使用 classifier TextClassifier(Qwen/Qwen1.5-1.8B-Chat, ./qwen_lora_adapter) result classifier.predict(我买的手机屏幕碎了能保修吗) print(f预测类别: {result}) # 期望输出售后服务方式二使用Transformers的PipelineHugging Face的pipelineAPI让这件事变得更简单它封装了预处理、推理和后处理的完整流程。from transformers import pipeline from peft import PeftModel # 加载基础模型和适配器 base_model AutoModelForCausalLM.from_pretrained(Qwen/Qwen1.5-1.8B-Chat, trust_remote_codeTrue) model PeftModel.from_pretrained(base_model, ./qwen_lora_adapter) tokenizer AutoTokenizer.from_pretrained(Qwen/Qwen1.5-1.8B-Chat, trust_remote_codeTrue) # 创建文本生成pipeline并指定我们的模型 classifier_pipeline pipeline(text-generation, modelmodel, tokenizertokenizer, device0 if torch.cuda.is_available() else -1) def predict_with_pipeline(text): prompt f文本{text}\n类别 result classifier_pipeline(prompt, max_new_tokens10, do_sampleFalse)[0][generated_text] predicted_label result.split(类别)[-1].strip() return predicted_label # 测试 print(predict_with_pipeline(请问会员积分怎么兑换))整个流程走下来你会发现基于Transformer架构的通义千问模型来做微调其实并没有想象中那么复杂。核心就是利用好现有的工具Hugging Face想清楚你的任务怎么转化成模型能理解的形式比如我们用的“问答”格式然后选择一种适合你的微调策略全量或LoRA。我自己的项目里用LoRA微调后的模型在测试集上的准确率比之前用的传统方法高了将近15个百分点而且对于没见过的、更口语化的问法泛化能力也强了很多。最关键的是整个微调过程在单张24G显存的卡上不到一小时就完成了效率非常高。如果你也在为文本分类任务头疼尤其是那些类别复杂、表述多样的场景真的可以试试这个方法。它给了你一个很高的起点强大的预训练模型而你只需要付出相对较小的代价微调就能获得一个专属于你的、效果出色的分类工具。获取更多AI镜像想探索更多AI镜像和应用场景访问 CSDN星图镜像广场提供丰富的预置镜像覆盖大模型推理、图像生成、视频生成、模型微调等多个领域支持一键部署。