通义千问模型微调——swift框架

部署运行你感兴趣的模型镜像

1.创建环境

服务器CUDA Version: 12.2

conda create -n lora_qwen python=3.10 -y 
conda activate lora_qwen 
conda install pytorch==2.4.0 torchvision==0.19.0 torchaudio==2.4.0 pytorch-cuda=12.1 -c pytorch -c nvidia -y

1.1环境搭建

本文使用swift进行微调,所以先下载swift,以及一些必要的packages

git clone https://github.com/modelscope/ms-swift.git
pip install transformers==4.49.0 
pip install pyav qwen_vl_utils 
pip install numpy==1.22.4 
pip install modelscope

1.2模型下载

使用modelscope下载指定模型,其中:

--model表示模型名称,可在modelscope官网找到

--local_dir代表模型下载地址

运行下面的命令,模型会下载到:./Qwen/Qwen2.5-VL-7B-Instruct目录下

modelscope download --model Qwen/Qwen2.5-VL-7B-Instruct --local_dir ./

下面脚本用于和模型进行对话,可以简单测试一下模型是否能够使用

CUDA_VISIBLE_DEVICES=1 swift infer --model_type qwen2_5_vl --ckpt_dir ./Qwen/Qwen2.5-VL-7B-Instruct

1.3数据集准备

下方是数据集格式,保存类型为.jsonl

[
    {
        "query": "OCR一下<image>",
        "response": "朵拉童衣",
        "images": [
            "datasets/lora_qwen/train/billboard_00001_010_朵拉童衣.jpg"
        ]
    },
    {
        "query": "OCR一下<image>",
        "response": "童衣雜貨舖",
        "images": [
            "datasets/lora_qwen/train/billboard_00002_010_童衣雜貨舖.jpg"
        ]
    },...
]

2.微调

2.1采用LoRA进行微调

对文件夹中之前下载的ms-swift-main/examples/train/multimodal/ocr.sh进行修改

# 20GB
CUDA_VISIBLE_DEVICES=0,1 \
MAX_PIXELS=1003520 \
swift sft \
    --model ./Qwen/Qwen2.5-VL-7B-Instruct \
    --model_type qwen2_5_vl \
    --dataset ./datatsets/train.jsonl \
    --val_dataset ./datatsets/val.jsonl \
    --train_type lora \
    --torch_dtype bfloat16 \
    --num_train_epochs 100 \
    --per_device_train_batch_size 1 \
    --per_device_eval_batch_size 1 \
    --learning_rate 1e-4 \
    --lora_rank 64 \
    --lora_alpha 64 \
    --target_modules all-linear \
    --freeze_vit true \
    --gradient_accumulation_steps 16 \
    --eval_steps 50 \
    --save_steps 50 \
    --save_total_limit 10 \
    --logging_steps 5 \
    --max_length 2048 \
    --output_dir output \
    --warmup_ratio 0.05 \
    --dataloader_num_workers 4
  • 常用参数解释:

--model:原模型的权重地址

--dataset:训练集的数据地址

--val_dataset:验证集的数据地址

--train_type:全参数训练(full) 或 LoRA微调训练(lora)

--num_train_epochs:总共要训练的轮数

--per_device_train_batch_size:训练阶段batchsize大小,根据显存大小来设置

--per_device_eval_batch_size:验证阶段batchsize大小,根据显存大小来设置

--learning_rate:学习率,一般设为0.0001或0.00001

--target_modules:需要做微调的目标模块,all-linear表示所有的线形层,也就是Attention和FeedForward层

--freeze_vit:一般设为true,不微调视觉编码器,只微调LLM部分

2.2使用Transformer进行推理

import os
import re
import torch
from PIL import Image

from datasets import Dataset
from modelscope import AutoTokenizer
from peft import LoraConfig, TaskType, get_peft_model, PeftModel
from transformers import (
    AutoProcessor,
    Qwen2_5_VLForConditionalGeneration,
    Trainer, TrainingArguments,
    Seq2SeqTrainer, Seq2SeqTrainingArguments, 
    DataCollatorForSeq2Seq,
)
from qwen_vl_utils import process_vision_info

rewrite_print = print
def print(save_txt, *arg, **kwargs):
    rewrite_print(*arg, **kwargs)
    rewrite_print(*arg, **kwargs, file=open(save_txt, "a+", encoding="utf-8"))

def process_func(model, img_path, input_content):
    messages = [
        {
            "role": "user",
            "content": [
                {"type": "image", "image": img_path},
                {"type": "text", "text": input_content},
            ],
        }
    ]
    text = processor.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)
    image_inputs, video_inputs = process_vision_info(messages)

    inputs = processor(
        text=[text],
        images=image_inputs,
        videos=video_inputs,
        padding=True,
        return_tensors="pt",
    )

    generated_ids = model.generate(**inputs, max_new_tokens=512)
    generated_ids_trimmed = [
        out_ids[len(in_ids) :] for in_ids, out_ids in zip(inputs.input_ids, generated_ids)
    ]
    output_text = processor.batch_decode(
        generated_ids_trimmed, skip_special_tokens=True, clean_up_tokenization_spaces=False
    )

    print(save_txt_path, img_path)
    print(save_txt_path, output_text[0])
    print(save_txt_path, '\n')

def get_lora_model(model_path, lora_model_path):
    model = Qwen2_5_VLForConditionalGeneration.from_pretrained(model_path, device_map="auto", torch_dtype=torch.bfloat16)
    model.enable_input_require_grads()

    config = LoraConfig(
        task_type=TaskType.CAUSAL_LM,
        target_modules="model\..*layers\.\d+\.(self_attn\.(q_proj|k_proj|v_proj|o_proj)|mlp\.(gate_proj|up_proj|down_proj))",
        inference_mode=True,
        r=64,
        lora_alpha=64,
        lora_dropout=0.05,
        bias="none",
    )

    peft_model = PeftModel.from_pretrained(model, model_id=lora_model_path, config=config)
    return peft_model

if __name__ == '__main__':
    save_txt_path = 'log.txt'

    model_path = "./Qwen2.5-VL-7B-Instruct"
    lora_model_path = "./output/v2-20250228-202446/checkpoint-900"
    lora_model = get_lora_model(model_path, lora_model_path)
    processor = AutoProcessor.from_pretrained(model_path)
    
    img_path = "图片路径"
    prompt = "OCR一下"
    process_func(lora_model, img_path, prompt)

3.实验参数情况

模型微调显存:30G左右(主要看数据集,图片越大,prompt,answer越多,占用显存越多);

模型微调后推理:20G左右;

您可能感兴趣的与本文相关的镜像

Llama Factory

Llama Factory

模型微调
LLama-Factory

LLaMA Factory 是一个简单易用且高效的大型语言模型(Large Language Model)训练与微调平台。通过 LLaMA Factory,可以在无需编写任何代码的前提下,在本地完成上百种预训练模型的微调

### 通义模型微调代码示例指南 以下是基于 PyTorch 和 Hugging Face Transformers 的框架实现通义模型微调的一个完整代码示例。此过程涉及加载预训练模型、准备数据集以及执行微调操作。 #### 加载预训练模型 首先,需要从 Hugging Face Model Hub 或本地路径加载通义的大规模预训练模型: ```python from transformers import AutoTokenizer, AutoModelForCausalLM model_name_or_path = "Qwen/Qwen-2" # 替换为你使用的具体版本 tokenizer = AutoTokenizer.from_pretrained(model_name_or_path) model = AutoModelForCausalLM.from_pretrained(model_name_or_path) ``` 上述代码片段用于初始化 tokenizer 和模型实例[^1]。 #### 数据处理与格式化 为了使模型能够适应特定任务,在微调前需对原始数据进行清洗和转换为适合输入的形式。这里假设我们有一个简单的答数据集 `train_data`,其中每条记录包含题 (`question`) 和答案 (`answer`) 字段。 ```python def preprocess_function(examples): inputs = [f"{example['question']} {tokenizer.eos_token} {example['answer']}" for example in examples] model_inputs = tokenizer(inputs, max_length=512, truncation=True, padding="max_length", return_tensors="pt") labels = model_inputs.input_ids.clone() return {"input_ids": model_inputs["input_ids"], "attention_mask": model_inputs["attention_mask"], "labels": labels} # 假设 train_dataset 是已经加载好的 Dataset 对象 tokenized_datasets = train_dataset.map(preprocess_function, batched=True) ``` 这段脚本定义了一个函数来拼接题和答案,并将其编码成 token ID 序列[^3]。 #### 设置 Trainer 并启动微调 Hugging Face 提供了方便易用的 `Trainer` API 来简化训练流程配置工作: ```python from transformers import TrainingArguments, Trainer training_args = TrainingArguments( output_dir="./results", num_train_epochs=2, per_device_train_batch_size=8, save_steps=10_000, save_total_limit=2, logging_dir='./logs', ) trainer = Trainer( model=model, args=training_args, train_dataset=tokenized_datasets, data_collator=lambda data: {'input_ids': torch.stack([item['input_ids'] for item in data]), 'attention_mask': torch.stack([item['attention_mask'] for item in data]), 'labels': torch.stack([item['labels'] for item in data])} ) trainer.train() ``` 在此部分中,创建了一个 `TrainingArguments` 实例指定超参数设置;接着构建 `Trainer` 类完成最终集成。 --- #### 部署与推理服务 当微调完成后,可以通过 SDK 将其部署到云端或者边缘设备上提供在线预测功能。下面展示了一种 RESTful 接口形式的服务端逻辑设计思路: ```python import uvicorn from fastapi import FastAPI from pydantic import BaseModel from typing import List import torch app = FastAPI() class InputData(BaseModel): texts: List[str] @app.post("/predict/") async def predict(input_data: InputData): input_texts = input_data.texts encoded_input = tokenizer(input_texts, return_tensors='pt', padding=True, truncation=True, max_length=512).to('cuda') with torch.no_grad(): outputs = model.generate(**encoded_input, max_new_tokens=50) results = tokenizer.batch_decode(outputs, skip_special_tokens=True) return {"predictions": results} if __name__ == "__main__": uvicorn.run(app, host="0.0.0.0", port=8000) ``` 该模块实现了接收 POST 请求并返回生成文本的核心业务能力[^2]。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值