最近我整理并开源了一个基于 Qwen2.5-VL-7B-Instruct + LoRA 的自定义目标检测项目。

项目支持使用自己的图片、类别和边界框标注,对 Qwen2.5-VL-7B 进行 LoRA 微调。整个流程包含数据集校验、模型训练、断点续训、最佳模型选择、测试集评估、检测结果可视化以及单张图片推理。

GitHub 项目地址:

GitHub - LeonBytes/Qwen-LoRA: A configurable LoRA fine-tuning pipeline for Qwen2.5-VL-7B, covering custom object detection, dataset validation, evaluation, visualization, and inference. · GitHub

如果这个项目对你有帮助,欢迎 Star。

一、项目介绍

传统目标检测项目通常使用 YOLO、Faster R-CNN、DETR 等模型。本项目尝试将视觉语言模型 Qwen2.5-VL-7B-Instruct 微调为生成式目标检测器。

模型接收一张图片和一段检测指令,并以 JSON 格式返回不同类别的边界框坐标,例如:

{
  "class_a": [
    [35, 48, 180, 240],
    [225, 60, 390, 275]
  ],
  "class_b": [
    [70, 310, 245, 465]
  ]
}

每个边界框采用以下格式:

[x1, y1, x2, y2]

坐标使用原图像素坐标,而不是归一化坐标。

项目中的类别没有写死在 Python 代码里。用户只需修改 JSON 配置和数据集标注,即可将项目应用到自己的目标检测任务。

二、主要功能

项目目前包含以下功能:

  • 基于 Qwen2.5-VL-7B-Instruct 的视觉语言模型微调
  • 使用 PEFT LoRA 降低可训练参数量
  • 支持任意数量和名称的自定义类别
  • 支持一张图片中同一类别存在多个实例
  • 只对 assistant 的目标检测答案计算训练损失
  • 使用验证集 eval_loss 选择最佳 checkpoint
  • 支持 Early Stopping
  • 支持训练中断后的自动断点续训
  • 支持测试集自动评估
  • 支持 IoU 一对一边界框匹配
  • 计算每个类别的 Precision、Recall 和 F1
  • 计算 Micro F1 和 Macro F1
  • 自动生成 Ground Truth 与 Prediction 对比图
  • 支持单张图片推理
  • 支持 Windows、Linux 和 Google Colab
  • 提供中英文 README

三、项目结构

Qwen-LoRA/
├── assets/
├── configs/
│   └── example.json
├── data/
│   └── example_train.json
├── outputs/
├── scripts/
│   ├── common.py
│   ├── evaluate.py
│   ├── metrics.py
│   ├── predict.py
│   ├── train.py
│   └── validate_dataset.py
├── .gitignore
├── LICENSE
├── README.md
├── README_EN.md
└── requirements.txt

各个脚本的职责如下:

  • common.py:配置、路径、随机种子和模型加载
  • train.py:LoRA 训练和数据整理
  • evaluate.py:测试集评估入口
  • metrics.py:JSON 解析、IoU、指标统计和结果可视化
  • predict.py:单张图片推理
  • validate_dataset.py:数据集格式和边界框检查

四、运行环境

推荐环境:

  • Python 3.10 或 3.11
  • Windows 或 Linux
  • 支持 CUDA 的 NVIDIA GPU
  • 推荐 24 GB 以上显存
  • Anaconda 或 Miniconda

需要注意,当前训练流程依赖 CUDA。macOS 可以用于代码编辑、配置修改和数据集校验,但不能直接使用 Apple GPU 运行当前的 7B 模型训练流程。

Mac 用户可以使用 Google Colab 或连接远程 NVIDIA GPU 服务器。

五、安装方法

首先克隆项目:

git clone https://github.com/LeonBytes/Qwen-LoRA.git
cd Qwen-LoRA

创建 Conda 环境:

conda create -n qwen-detection python=3.10 -y
conda activate qwen-detection

安装依赖:

python -m pip install --upgrade pip
pip install -r requirements.txt

检查 PyTorch 是否识别 CUDA:

python -c "import torch; print(torch.cuda.is_available()); print(torch.cuda.get_device_name(0) if torch.cuda.is_available() else 'CUDA GPU not found')"

如果第一项输出为 True,说明 PyTorch 已识别 NVIDIA GPU。

六、数据集目录

数据集需要按照以下结构组织:

data/
├── train.json
├── validation.json
├── test.json
└── images/
    ├── train/
    ├── validation/
    └── test/

建议按照大约以下比例划分:

训练集:80%
验证集:10%
测试集:10%

同一来源的重复图片或高度相似图片不要跨数据集分配,否则可能造成数据泄漏,使测试结果虚高。

七、图片尺寸建议

建议将训练集、验证集和测试集图片统一处理为:

1280 × 1280

对于非正方形图片,推荐使用等比例缩放加填充,也就是 letterbox,而不是直接将图片拉伸到正方形。

这样可以避免目标形状发生明显变形。

需要特别注意:

  • 边界框坐标必须对应处理后的 1280 × 1280 图片
  • 修改图片尺寸后,需要同步转换所有边界框
  • 训练、验证、测试和实际推理应使用相同的预处理方法
  • 当前项目不会自动修改数据集图片尺寸,需要提前完成图片处理

八、数据标注格式

每个 JSON 文件的根节点是一个数组。

每个样本包含图片名称和两轮对话:

[
  {
    "image": "example_001.jpg",
    "conversations": [
      {
        "from": "human",
        "value": "<image>\nLocate all class_a and class_b objects in this image and output their bbox coordinates in JSON format."
      },
      {
        "from": "gpt",
        "value": "{\"class_a\":[[35,48,180,240],[225,60,390,275],[430,95,610,320]],\"class_b\":[[70,310,245,465],[330,345,560,510]]}"
      }
    ]
  }
]

字段说明:

  • image:图片文件名或相对路径
  • human.value:模型接收的图片检测指令
  • gpt.value:目标检测答案,以 JSON 字符串保存
  • 每个类别可以包含零个、一个或多个边界框

如果某个类别在当前图片中不存在,建议保留该类别并使用空列表:

{
  "class_a": [],
  "class_b": [[70, 310, 245, 465]]
}

九、自定义类别

复制配置文件:

cp configs/example.json configs/my_dataset.json

修改类别和 Prompt:

{
  "class_names": [
    "class_a",
    "class_b"
  ],
  "prompt": "Locate all class_a and class_b objects in this image and output their bbox coordinates in JSON format."
}

以下位置的类别必须完全一致:

  • 配置文件中的 class_names
  • 配置文件中的 prompt
  • 数据集中每条 human.value
  • 每条 gpt.value 内部 JSON 的键

增加或删除类别后,建议使用新的输出目录重新训练。

十、训练前校验数据

开始训练前,建议先运行数据校验:

python scripts/validate_dataset.py \
  --config configs/my_dataset.json \
  --data-dir data

校验器会检查:

  • JSON 根节点和样本结构
  • humangpt 消息顺序
  • gpt.value 是否为合法 JSON
  • 是否存在未知类别
  • 是否缺少配置中的类别
  • 图片文件是否存在
  • 图片是否可以正常读取
  • 边界框格式是否正确
  • 边界框是否超出图片范围

发现错误时,校验器会返回非零退出码,避免错误数据直接进入训练流程。

十一、开始 LoRA 训练

执行以下命令:

python scripts/train.py \
  --config configs/my_dataset.json \
  --data-dir data \
  --output-dir outputs/my_experiment

训练输出大致如下:

outputs/my_experiment/
├── checkpoint-*/
├── best_model/
├── logs/
├── run_config.json
├── trainer_state.json
└── training_results.json

其中:

  • checkpoint-* 保存完整训练状态,可用于断点续训
  • best_model 保存验证损失最低的 LoRA adapter
  • logs 保存 TensorBoard 日志
  • run_config.json 保存本次实验配置
  • training_results.json 保存训练结果

如果训练意外中断,重新运行相同命令即可从最新 checkpoint 恢复。

也可以临时修改最大训练步数:

python scripts/train.py \
  --config configs/my_dataset.json \
  --data-dir data \
  --output-dir outputs/my_experiment \
  --max-steps 500

十二、查看训练日志

运行:

tensorboard --logdir outputs/my_experiment/logs

然后根据终端提示,在浏览器中打开 TensorBoard。

十三、测试集评估

训练完成后运行:

python scripts/evaluate.py \
  --config configs/my_dataset.json \
  --data-dir data \
  --output-dir outputs/my_experiment

评估结果会保存到:

outputs/my_experiment/test_evaluation/
├── evaluation_report.json
├── predictions.json
└── visualizations/

其中:

  • evaluation_report.json:检测指标
  • predictions.json:每张图片的预测框和原始模型输出
  • visualizations:Ground Truth 与 Prediction 对比图片

如果不需要生成可视化:

python scripts/evaluate.py \
  --config configs/my_dataset.json \
  --data-dir data \
  --output-dir outputs/my_experiment \
  --skip-visualizations

需要说明的是,项目中的 F1 是固定 IoU 阈值下的生成式目标检测指标,并不等同于 COCO mAP。

十四、单张图片推理

运行:

python scripts/predict.py path/to/image.jpg \
  --config configs/my_dataset.json \
  --output-dir outputs/my_experiment

示例输出:

{
  "class_a": [
    [35.0, 48.0, 180.0, 240.0]
  ],
  "class_b": []
}

也可以手动指定 LoRA adapter 和基础模型:

python scripts/predict.py path/to/image.jpg \
  --config configs/my_dataset.json \
  --adapter-path path/to/adapter \
  --model-path path/to/base-model

十五、Google Colab 运行方式

挂载 Google Drive:

from google.colab import drive

drive.mount("/content/drive")

进入项目并安装依赖:

%cd /content/drive/MyDrive/qwen-lora-detection
!pip install -r requirements.txt

校验数据:

!python scripts/validate_dataset.py \
  --config configs/my_dataset.json \
  --data-dir data

开始训练:

!python scripts/train.py \
  --config configs/my_dataset.json \
  --data-dir data \
  --output-dir outputs/my_experiment

测试评估:

!python scripts/evaluate.py \
  --config configs/my_dataset.json \
  --data-dir data \
  --output-dir outputs/my_experiment

十六、显存不足怎么办

如果出现 CUDA out of memory,可以尝试:

  1. train_batch_size 改为 1
  2. 减小 model_max_length
  3. 减小输入图片尺寸
  4. 增加 gradient_accumulation_steps
  5. 减小 LoRA rank
  6. 使用显存更大的 GPU

需要注意,减小 LoRA rank 主要减少可训练参数和优化器状态,但 Qwen2.5-VL-7B 基础模型仍然需要占用较多显存。

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐