跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客GitHub 精选镜像AI 生图工具UI配色美学隐私政策关于联系
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
PythonAI算法

Qwen3-VL 与 LLaMA-Factory 实现 Grounding 任务 LoRA 微调

介绍基于 Qwen3-VL 模型与 LLaMA-Factory 框架进行 Grounding 任务 LoRA 微调的完整流程。涵盖环境搭建、模型权重下载、推理代码示例、数据集格式转换(YOLO 至 Qwen 格式)及可视化训练配置。详细说明了相对坐标归一化处理、DeepStack 技术背景及多模态数据适配方法,并提供模型测试与导出步骤。

ApiHolic发布于 2026/4/6更新于 2026/7/1048 浏览
Qwen3-VL 与 LLaMA-Factory 实现 Grounding 任务 LoRA 微调

0. 官方资源

GitHub - QwenLM/Qwen3-VL

空间感知能力大幅提升:2D grounding 从绝对坐标变为相对坐标,支持判断物体方位、视角变化、遮挡关系,能实现 3D grounding,为复杂场景下的空间推理和具身场景打下基础。

OCR 支持更多语言及复杂场景:支持的中英外的语言从 10 种扩展到 32 种,覆盖更多国家和地区;在复杂光线、模糊、倾斜等实拍挑战性场景下表现更稳定;对生僻字、古籍字、专业术语的识别准确率也显著提升;超长文档理解和精细结构还原能力进一步提升。

一是采用 MRoPE-Interleave:原始 MRoPE 将特征维度按照时间(t)、高度(h) 和宽度 (w) 的顺序分块划分,使得时间信息全部分布在高频维度上。在 Qwen3-VL 中采取了 t,h,w 交错分布的形式,实现对时间,高度和宽度的全频率覆盖,这样更加鲁棒的位置编码能够保证模型在图片理解能力相当的情况下,提升对长视频的理解能力。

二是引入 DeepStack 技术:融合 ViT 多层次特征,提升视觉细节捕捉能力和图文对齐精度。沿用 DeepStack 的核心思想,将以往多模态大模型(LMM)单层输入视觉 tokens 的范式,改为在大型语言模型 (LLM) 的多层中进行注入。这种多层注入方式旨在实现更精细化的视觉理解。在此基础上,进一步优化了视觉特征 token 化的策略。具体而言,将来自 ViT 不同层的视觉特征进行 token 化,并以此作为视觉输入。实验结果表明,该方法在多种视觉理解任务上均展现出显著的性能提升。

三是将原有的视频时序建模机制 T-RoPE 升级为文本时间戳对齐机制:该机采用'时间戳 - 视频帧'交错的输入形式,实现帧级别的时间信息与视觉内容的细粒度对齐。同时,模型原生支持'秒数'与'时:分:秒'(HMS)两种时间输出格式。这一改进显著提升了模型对视频中动作、事件的语义感知与时间定位精度,使其在复杂时序推理任务——如事件定位、动作边界检测、跨模态时间问答等——中表现更稳健、响应更精准。

1. 配置环境

conda create -n Qwen3-vl python=3.10
conda activate Qwen3-vl
pip install accelerate
pip install qwen-vl-utils==0.0.14
uv pip install -U vllm

2. 下载代码

使用 git clone 克隆项目:

git clone https://github.com/QwenLM/Qwen3-VL

或从 GitHub 页面下载压缩包。

3. 下载权重文件

权重文件较大,建议使用 ModelScope 下载:

# 安装 ModelScope
pip install modelscope
# 下载完整模型库
modelscope download --model Qwen/Qwen3-VL-2B-Instruct

4. 推理代码

修改 Qwen/Qwen3-VL-4B-Instruct 为你下载的参数地址以及图片地址。

from transformers import Qwen3VLForConditionalGeneration, AutoProcessor
import torch
from PIL import Image

def load_qwen3_vl_4b_model():
    """加载 Qwen3-VL-4B-Instruct 模型和处理器"""
    model = Qwen3VLForConditionalGeneration.from_pretrained(
        ,
        torch_dtype=torch.bfloat16,
        device_map=,
        attn_implementation= 
    )
    processor = AutoProcessor.from_pretrained()
     model, processor

 ():
    
    
    image = Image.(image_path).convert()
    
    messages = [
        {
            : ,
            : [
                {: , : image},
                {: , : text_query}
            ]
        }
    ]
    
    inputs = processor.apply_chat_template(
        messages, tokenize=, add_generation_prompt=, return_dict=, return_tensors=
    )
    
    generated_ids = model.generate(
        **inputs, max_new_tokens=, do_sample=, temperature=, top_p=
    )
    
    generated_ids_trimmed = [out_ids[(in_ids):]  in_ids, out_ids  (inputs.input_ids, generated_ids)]
    output_text = processor.batch_decode(generated_ids_trimmed, skip_special_tokens=, clean_up_tokenization_spaces=)
     output_text[]  output_text  

 __name__ == :
    model, processor = load_qwen3_vl_4b_model()
    image_path =  
    query =  
    result = process_multimodal_query(model, processor, image_path, query)
    (, result)
"Qwen/Qwen3-VL-4B-Instruct"
"auto"
"flash_attention_2"
# 可选,用于加速
"Qwen/Qwen3-VL-4B-Instruct"
return
def
process_multimodal_query
model, processor, image_path, text_query
"""处理多模态查询(图像 + 文本)"""
# 加载图像
open
'RGB'
# 构建消息格式
"role"
"user"
"content"
"type"
"image"
"image"
"type"
"text"
"text"
# 预处理输入
True
True
True
"pt"
# 生成输出
128
True
0.7
0.8
# 解码输出
len
for
in
zip
True
False
return
0
if
else
""
if
"__main__"
"example.jpg"
# 改为你的图片路径
"描述这张图片中的场景和主要对象"
# 改为你的提示词
print
"模型回复:"

5. 微调部分

5.1 使用 LLaMA-Factory 项目进行微调

5.1.1 下载项目

使用 git 下载:

git clone https://github.com/hiyouga/LLaMA-Factory
5.1.2 创建虚拟环境
conda create -n llama-factory python=3.12
conda activate llama-factory

安装环境:

pip install -e ".[torch,metrics]" --no-build-isolation

卸载默认的 cpu 版本的 torch:

pip uninstall torch torchvision

安装 gpu 版本的 torch,根据你的 cuda 版本选择;下面是 cuda11.8 版本的 torch 安装指令:

pip install torch==2.8.0 torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118

5.2 准备微调数据集

5.2.1 所需数据集格式

LLaMA-Factory 微调所需要的数据格式参考官方文档。

需要注意的是 Qwen3-VL 使用的 0-1000 的相对坐标记得归一化坐标的大小。 准备好数据集后还需要修改 LLaMA-Factory/data/dataset_info.json 文件,在里面增加上我们所需的文件夹。

5.2.2 YOLO 格式转换为 qwen3-vl-grounding 格式

其中,我的数据集来源是 YOLO 格式转换而来,因为我要做的是 Grounding 任务,转换代码如下:

可以通过这个代码将 YOLO 格式转换为 Qwen3-VL-Grounding 格式:

import os
import json
from tqdm import tqdm

# ================== 需要你修改的路径 ==================
IMAGE_DIR = "images" # 例如:qwen3_vl_grounding_train/images
LABEL_DIR = "labels" # 例如:qwen3_vl_grounding_train/labels
OUTPUT_JSON = "qwen3_vl_grounding_mllm.json"
CLASS_ID2NAME = {
    0: "house",
    # 1: "car",
    # ...
}
USE_ONLY_CLASS_IDS = None # 例如只保留房子:USE_ONLY_CLASS_IDS = {0}
USER_PROMPT = (
    "<image>\n"
    "Locate all objects in this image and output the bbox coordinates "
    "in JSON format using relative coordinates in the range [0, 1000]."
)

# ================== 坐标工具函数 ==================
def yolo_to_xyxy_relative(xc, yc, w, h):
    """YOLO 归一化坐标 (xc, yc, w, h) ∈ [0,1] -> 相对坐标系下的四点 [x_min, y_min, x_max, y_max](仍然是 [0,1])"""
    x_min = xc - w / 2
    y_min = yc - h / 2
    x_max = xc + w / 2
    y_max = yc + h / 2
    x_min = max(0.0, min(1.0, x_min))
    y_min = max(0.0, min(1.0, y_min))
    x_max = max(0.0, min(1.0, x_max))
    y_max = max(0.0, min(1.0, y_max))
    return [x_min, y_min, x_max, y_max]

def scale_to_qwen_coords(xyxy_rel, scale=1000):
    """[0,1] -> [0, scale],Qwen3-VL 默认 scale=1000 返回整数坐标 [x_min, y_min, x_max, y_max]"""
    x_min, y_min, x_max, y_max = xyxy_rel
    return [
        int(round(x_min * scale)),
        int(round(y_min * scale)),
        int(round(x_max * scale)),
        int(round(y_max * scale)),
    ]

def collect_image_files(image_dir):
    exts = {".jpg", ".jpeg", ".png", ".bmp", ".webp"}
    files = []
    for fname in os.listdir(image_dir):
        if os.path.splitext(fname)[1].lower() in exts:
            files.append(fname)
    return sorted(files)

# ================== 主逻辑 ==================
def main():
    image_files = collect_image_files(IMAGE_DIR)
    if not image_files:
        print(f"No images found in {IMAGE_DIR}")
        return
    dataset = []
    for img_name in tqdm(image_files, desc="Converting"):
        img_path = os.path.join(IMAGE_DIR, img_name)
        img_rel_or_abs = os.path.abspath(img_path)
        base, _ = os.path.splitext(img_name)
        label_path = os.path.join(LABEL_DIR, base + ".txt")
        if not os.path.exists(label_path):
            continue
        bboxes_qwen = []
        cls_ids = []
        with open(label_path, "r", encoding="utf-8") as f:
            for line in f:
                line = line.strip()
                if not line:
                    continue
                parts = line.split()
                if len(parts) < 5:
                    print(f"Label format error in {label_path}: {line}")
                    continue
                cls_id = int(parts[0])
                if USE_ONLY_CLASS_IDS is not None and cls_id not in USE_ONLY_CLASS_IDS:
                    continue
                xc = float(parts[1])
                yc = float(parts[2])
                w = float(parts[3])
                h = float(parts[4])
                xyxy_rel = yolo_to_xyxy_relative(xc, yc, w, h)
                xyxy_qwen = scale_to_qwen_coords(xyxy_rel, scale=1000)
                bboxes_qwen.append(xyxy_qwen)
                cls_ids.append(cls_id)
        if not bboxes_qwen:
            continue
        objects = []
        for cid, box in zip(cls_ids, bboxes_qwen):
            obj = {
                "cls_id": cid,
                "bbox_2d": box
            }
            if cid in CLASS_ID2NAME:
                obj["cls_name"] = CLASS_ID2NAME[cid]
            objects.append(obj)
        answer_obj = {"objects": objects}
        answer_str = json.dumps(answer_obj, ensure_ascii=False)
        sample = {
            "conversations": [
                {"from": "human", "value": USER_PROMPT},
                {"from": "gpt", "value": answer_str}
            ],
            "images": [img_rel_or_abs]
        }
        dataset.append(sample)
    with open(OUTPUT_JSON, "w", encoding="utf-8") as f:
        json.dump(dataset, f, ensure_ascii=False, indent=2)
    print(f"Done. Wrote {len(dataset)} samples to {OUTPUT_JSON}")

if __name__ == "__main__":
    main()

然后将生成的 json 文件放在 LLaMA-Factory/data 路径下面。

5.3 使用 LLaMA-Factory 可视化界面进行微调

cd LLaMA-Factory
5.3.1 启动可视化界面
llamafactory-cli webui
5.3.2 修改训练参数

需要修改的参数包括:语言、模型、模型路径、模型下载源、计算类型等。

其中计算类型为 Pure_bf16 更省显存。

修改 dataset_info.json:

将下面代码夹在文件的最前面;然后可视化界面的数据集那栏就能找到自己的数据集了:

"qwen3_vl_grounding_mllm": {
    "file_name": "qwen3_vl_grounding_mllm.json",
    "formatting": "sharegpt",
    "columns": {
        "messages": "conversations",
        "images": "images"
    }
}

一次点击保存训练参数、载入训练参数、开始就可以开始训练了。

5.3.3 对话测试模型

点击 chat、选择训练好模型路径、点击加载模型、进行问答。

输入图片和提示词进行问答。

导出模型。

目录

  1. 0. 官方资源
  2. 1. 配置环境
  3. 2. 下载代码
  4. 3. 下载权重文件
  5. 安装 ModelScope
  6. 下载完整模型库
  7. 4. 推理代码
  8. 5. 微调部分
  9. 5.1 使用 LLaMA-Factory 项目进行微调
  10. 5.1.1 下载项目
  11. 5.1.2 创建虚拟环境
  12. 5.2 准备微调数据集
  13. 5.2.1 所需数据集格式
  14. 5.2.2 YOLO 格式转换为 qwen3-vl-grounding 格式
  15. ================== 需要你修改的路径 ==================
  16. ================== 坐标工具函数 ==================
  17. ================== 主逻辑 ==================
  18. 5.3 使用 LLaMA-Factory 可视化界面进行微调
  19. 5.3.1 启动可视化界面
  20. 5.3.2 修改训练参数
  21. 5.3.3 对话测试模型
  • 免费图片AI生成工具免费生成了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 免费图片视频在线生成30秒,将你的创意变成现实开始设计
  • X/Twitter免费视频下载器免登陆无限额度免费视频解析下载了解详情
  • 100+免费在线小游戏爽一把
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • 使用 cpolar 远程部署 Open-Lovable 实现网页克隆
  • 轻量级 SVGA 动画播放器:Web 端流畅动画实现
  • 自研 C# UI 引擎 XchyUI:内核 200KB,支持 .NET8 AOT 跨平台
  • Agent Skills 技能机制详解与实践指南
  • AI 在前后端开发中的差异化落地:从 MVP 到千万级并发
  • Coze(扣子)全解析:100 个落地用途与发布使用指南
  • 分布式文件系统 HDFS 数据读写过程详解
  • 环境模型在 DQN 中的应用:预测与规划机制解析
  • Python 强化学习自主迷宫求解:生成、训练与评估
  • 基于 Django 的非物质文化遗产管理系统设计与实现
  • 大模型驱动文档图像识别技术革新
  • HTML 基础语法与简单网页制作示例
  • AI 绘画的商业应用与版权合规指南
  • C++11 核心特性详解:Lambda、可变参数与函数包装器
  • Kubernetes 云原生运维实战:AIGC 智能重构与深度实践
  • 开源 AI 绘画趋势:Z-Image-Turbo 轻量化部署指南
  • 基于 Amazon SageMaker 的 AIGC 应用部署与 Web 集成实践
  • 基于 AI 视觉模型的 Unity 编辑器插件界面优化实战
  • C++ 虚函数与纯虚函数:从接口设计到虚析构陷阱
  • 算法基础:滑动窗口技巧与经典例题解析

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • RSA密钥对生成器

    生成新的随机RSA私钥和公钥pem证书。 在线工具,RSA密钥对生成器在线工具,online

  • Mermaid 预览与可视化编辑

    基于 Mermaid.js 实时预览流程图、时序图等图表,支持源码编辑与即时渲染。 在线工具,Mermaid 预览与可视化编辑在线工具,online

  • 随机西班牙地址生成器

    随机生成西班牙地址(支持马德里、加泰罗尼亚、安达卢西亚、瓦伦西亚筛选),支持数量快捷选择、显示全部与下载。 在线工具,随机西班牙地址生成器在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online

  • curl 转代码

    解析常见 curl 参数并生成 fetch、axios、PHP curl 或 Python requests 示例代码。 在线工具,curl 转代码在线工具,online