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

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

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

ApiHolic发布于 2026/4/6更新于 2026/5/2027 浏览
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 对话测试模型
  • 💰 8折买阿里云服务器限时8折了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 🤖 一键搭建Deepseek满血版了解详情
  • 一键打造专属AI 智能体了解详情
极客日志微信公众号二维码

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

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

更多推荐文章

查看全部
  • 基于大模型构建本地知识库的技术实践
  • CSS 元素显示模式详解:块级、行内与行内块
  • GitHub Copilot 学生认证流程详解(2026 更新)
  • 2026 年 AI 编程工具对比:GitHub Copilot、Cursor 与 Codeium 选型指南
  • OpenClaw 跨平台卸载指南:Windows、macOS、Linux 及包管理器清理
  • 数据结构:二叉树与堆
  • 告别 Electron:纯 C# 自研轻量 UI 引擎 XchyUI,内核<200KB
  • Linux 系统下安装配置 Nginx
  • Microi 吾码:服务器虚拟化资源管理与网络配置实践
  • Android Studio 配置 Gradle 国内镜像地址
  • C++ 二叉搜索树详解:增删查改与 Key/Value 场景实现
  • AI Agent 生产级框架实战:架构、记忆与工具调用详解
  • pdf-lib:JavaScript 全栈 PDF 处理方案
  • Python 月相可视化系统:从天文计算到 Web 界面生成
  • 知网AIGC检测怎么过?2026最新降AI率全流程攻略
  • IDEA 中 AI 编程插件对比:Copilot、TRAE、灵码实测
  • 滑动窗口实战:长度最小的子数组与无重复字符的最长子串
  • VS Code 安装 GitHub Copilot 实现 AI 辅助编程
  • Python 微博文本情感分析:基于词典、LSTM 与 SVM
  • AI 大模型定义及其在物流行业的变革应用

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如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