微调教程:基于Qwen2模型的指令微调指南
为使用Qwen2模型进行指令微调,首先需要安装必需的Python库,并确保环境支持CUDA。接着,从魔搭社区下载zh_cls_fudan-news
数据集,并准备数据集以适配Qwen2模型格式。使用modelscope下载Qwen2-1.5B-Instruct模型,并加载到Transformers中。通过提供的数据转换函数,将原始数据集转换为训练所需的格式。训练函数包括数据预处理、加载Lora配置以应用低秩适配(Lora),并设置训练参数。训练完成后,模型已保存,可进行推理。通过SwanLab可视化平台监控训练过程和效果,实现对大模型的高效微调,以针对特定任务如文本分类进行优化。
环境安装
为了开始使用Qwen2模型进行指令微调,您需要安装以下Python库。确保您已经安装了Python 3.8或更高版本,并确保您的环境支持CUDA。以下是安装命令:
pip install -q swanlab modelscope transformers datasets peft pandas accelerate
准备数据集
数据集将用于训练Qwen2模型,您需要从魔搭社区下载zh_cls_fudan-news
数据集。确保将train.jsonl
和test.jsonl
文件下载到本地目录中。
加载模型
使用modelscope下载Qwen2-1.5B-Instruct模型,并加载到Transformers中:
from modelscope import snapshot_download
from transformers import AutoTokenizer, AutoModelForCausalLM
model_dir = snapshot_download("qwen/Qwen2-1.5B-Instruct", cache_dir="./")
tokenizer = AutoTokenizer.from_pretrained(model_dir, use_fast=False, trust_remote_code=True)
model = AutoModelForCausalLM.from_pretrained(model_dir, device_map="auto", torch_dtype=torch.bfloat16)
完整代码
在开始训练之前,您需要将数据集转换为适配Qwen2模型的格式。以下是数据转换函数:
import json
def dataset_jsonl_transfer(origin_path, new_path):
messages = []
with open(origin_path, "r") as file:
for line in file:
data = json.loads(line)
context = data["text"]
catagory = data["category"]
label = data["output"]
message = {
"instruction": "你是一个文本分类领域的专家,你会接收到一段文本和几个潜在的分类选项,请输出文本内容的正确类型",
"input": f"文本:{context},类型选型:{catagory}",
"output": label,
}
messages.append(message)
with open(new_path, "w", encoding="utf-8") as file:
for message in messages:
file.write(json.dumps(message, ensure_ascii=False) + "\n")
数据预处理函数如下:
import pandas as pd
import torch
def process_func(example):
MAX_LENGTH = 384
input_ids, attention_mask, labels = [], [], []
instruction = tokenizer(f"系统\n你是一个文本分类领域的专家,你会接收到一段文本和几个潜在的分类选项,请输出文本内容的正确类型\n用户\n{example['input']}\n助手\n", add_special_tokens=False)
response = tokenizer(f"{example['output']}", add_special_tokens=False)
input_ids = instruction["input_ids"] + response["input_ids"] + [tokenizer.pad_token_id]
attention_mask = instruction["attention_mask"] + response["attention_mask"] + [1]
labels = [-100] * len(instruction["input_ids"]) + response["input_ids"] + [tokenizer.pad_token_id]
if len(input_ids) > MAX_LENGTH:
input_ids = input_ids[:MAX_LENGTH]
attention_mask = attention_mask[:MAX_LENGTH]
labels = labels[:MAX_LENGTH]
return {"input_ids": input_ids, "attention_mask": attention_mask, "labels": labels}
训练函数如下:
from swanlab.integration.huggingface import SwanLabCallback
from peft import LoraConfig, TaskType, get_peft_model
from transformers import TrainingArguments, Trainer, DataCollatorForSeq2Seq
def train_qwen2():
model_dir = snapshot_download("qwen/Qwen2-1.5B-Instruct", cache_dir="./")
tokenizer = AutoTokenizer.from_pretrained(model_dir, use_fast=False, trust_remote_code=True)
model = AutoModelForCausalLM.from_pretrained(model_dir, device_map="auto", torch_dtype=torch.bfloat16)
model.enable_input_require_grads()
train_dataset_path = "train.jsonl"
test_dataset_path = "test.jsonl"
train_jsonl_new_path = "new_train.jsonl"
test_jsonl_new_path = "new_test.jsonl"
# 转换并保存数据集
dataset_jsonl_transfer(train_dataset_path, train_jsonl_new_path)
dataset_jsonl_transfer(test_dataset_path, test_jsonl_new_path)
# 加载训练数据
train_df = pd.read_json(train_jsonl_new_path, lines=True)
train_dataset = train_df.map(process_func, remove_columns=train_df.columns)
# 定义Lora配置
config = LoraConfig(
task_type=TaskType.CAUSAL_LM,
target_modules=["q_proj", "k_proj", "v_proj", "o_proj", "gate_proj", "up_proj", "down_proj"],
inference_mode=False,
r=8,
lora_alpha=32,
lora_dropout=0.1,
)
# 应用Lora
model = get_peft_model(model, config)
# 为训练设置参数
args = TrainingArguments(
output_dir="./output/Qwen1.5",
per_device_train_batch_size=4,
gradient_accumulation_steps=4,
logging_steps=10,
num_train_epochs=2,
save_steps=100,
learning_rate=1e-4,
save_on_each_node=True,
gradient_checkpointing=True,
report_to="none",
)
swanlab_callback = SwanLabCallback(
project="Qwen2-fintune",
experiment_name="Qwen2-1.5B-Instruct",
description="使用通义千问Qwen2-1.5B-Instruct模型在zh_cls_fudan-news数据集上微调。",
config={
"model": "qwen/Qwen2-1.5B-Instruct",
"dataset": "huangjintao/zh_cls_fudan-news",
}
)
trainer = Trainer(
model=model,
args=args,
train_dataset=train_dataset,
data_collator=DataCollatorForSeq2Seq(tokenizer=tokenizer, padding=True),
callbacks=[swanlab_callback],
)
trainer.train()
# 保存训练好的模型
trainer.save_model("./output/Qwen1.5")
return model, tokenizer
model, tokenizer = train_qwen2()
推理训练好的模型
训练完成后,模型已保存至./output/Qwen1.5
。使用以下函数进行推理:
def predict(model, tokenizer, input_text):
input_ids = tokenizer.encode(input_text, return_tensors="pt")
output = model.generate(input_ids, max_length=50)
response = tokenizer.decode(output[0])
return response
# 示例:推理
input_text = "第四届全国大企业足球赛复赛结束新华社郑州5月3日电(实习生田兆运)上海大隆机器厂队昨天在洛阳进行的第四届牡丹杯全国大企业足球赛复赛中,以5:4力克成都冶金实验厂队,进入前四名。"
prediction = predict(model, tokenizer, input_text)
print(prediction)
结果演示与可视化
训练完成后,您可以在SwanLab可视化平台查看训练过程和结果。这是监控训练进度和效果的关键步骤。
# 运行SwanLab可视化
# 请确保SwanLab服务运行并且已登录您的账户
swanlab_callback.run()
总结
以上代码示例详细展示了如何使用Qwen2模型在zh_cls_fudan-news
数据集上进行指令微调。通过数据转换、模型训练和推理,您可以实现对大模型的微调,使其针对特定任务如文本分类进行优化。
共同学习,写下你的评论
评论加载中...
作者其他优质文章