为了账号安全,请及时绑定邮箱和手机立即绑定

Qwen2大模型微调入门实战(完整代码)

标签:
杂七杂八
概述

微调教程:基于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.jsonltest.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数据集上进行指令微调。通过数据转换、模型训练和推理,您可以实现对大模型的微调,使其针对特定任务如文本分类进行优化。

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消