Ascend-SACT/RF-DETR
模型介绍文件和版本Pull Requests讨论分析
下载使用量0

RF-DETR模型迁移指导文档

1. 模型概述及场景

1.1 模型介绍

RF-DETR 是 Roboflow 开发的实时目标检测和实例分割 Transformer 架构模型。该模型基于 DINOv2 视觉 Transformer 骨干网络构建,在 Microsoft COCO 和 RF100-VL 数据集上实现了业界领先的精度与延迟平衡。RF-DETR 提供 Nano、Small、Medium、Large、XLarge、2XLarge 等多种尺寸变体,满足不同算力场景需求。本项目使用 RFDETRNano 模型进行 NPU 迁移,该模型参数量 30.5M,输入分辨率 384x384,在 COCO 数据集上达到 AP50=67.6、AP50:95=48.4 的检测精度。

1.2 应用场景

RF-DETR 适用于实时目标检测和实例分割场景,包括:

  • 工业质检中的缺陷检测与分类
  • 智能安防中的目标识别与追踪
  • 自动驾驶中的障碍物检测
  • 医疗影像中的病灶识别

2. 迁移环境

2.1 硬件环境

  • NPU 设备:Ascend 910B3 x 8(本迁移使用卡 4、5、6、7 进行 4 卡 DDP 训练)
  • 存储:本地存储 > 100GB(用于数据集和模型权重)

2.2 软件环境

项目版本 / 规格
操作系统 / 架构openEuler 24.03 (LTS) / aarch64
驱动 / 固件25.2.0
CANN8.2.RC1
Python3.10.14
torch / torch_npu2.4.0 / 2.4.0

核心依赖包版本

包名版本说明
torch2.4.0PyTorch 核心
torch_npu2.4.0NPU 适配库
torchvision0.19.0视觉处理库
transformers4.40.0Transformer 模型库
numpy1.26.4数值计算(必须 1.x 版本)
Pillow11.2.1图像处理
albumentations1.4.24图像增强
supervision0.27.0.post2目标检测可视化
pycocotools2.0.11COCO 数据集评估
peft0.11.0参数高效微调
pydantic2.9.2数据验证
scipy1.14.1科学计算
tqdm4.67.3进度条
opencv-python4.12.0.88图像处理
onnx1.17.0ONNX 格式支持
onnxruntime1.15.1ONNX 推理
accelerate0.34.2分布式训练加速
huggingface_hub1.11.0模型下载
safetensors0.7.0安全序列化

3. 资源与依赖

3.1 模型权重

https://github.com/roboflow/rf-detr(预训练权重自动下载)

3.2 数据集

https://cocodataset.org/#home(COCO 2017 数据集)

3.3 代码仓

https://github.com/roboflow/rf-detr

3.4 容器镜像资源

TODO(补充容器镜像链接)

3.5 工具资源

torch_npu、atc、ais_bench、npu-smi

4. 环境准备

4.1 资源准备

  1. 克隆 RF-DETR 代码仓。
  2. 准备 COCO 格式数据集。
  3. 创建 Python 3.10 虚拟环境。

克隆代码仓并准备环境:

cd /opt
git clone https://github.com/roboflow/rf-detr.git

创建虚拟环境:

python3.10 -m venv /opt/rfdetr_venv

4.2 环境创建

  1. 设置 CANN 环境变量。
  2. 配置 NPU 相关环境变量。
  3. 设置 Python 路径。

设置环境变量:

export LD_LIBRARY_PATH=/usr/local/python3.10/lib:$LD_LIBRARY_PATH
export PYTHONPATH=/opt/rfdetr_venv/lib/python3.10/site-packages:/rf-detr/src:$PYTHONPATH
export PYTHONNOUSERSITE=1
export TASK_QUEUE_ENABLE=0
export ACL_OP_INIT_MODE=1
export TBE_PARALLEL_COMPILER=0
source /usr/local/Ascend/ascend-toolkit/8.2.RC1/aarch64-linux/script/set_env.sh
source /usr/local/Ascend/nnal/atb/set_env.sh

4.3 依赖安装

  1. 安装 torch 和 torch_npu。
  2. 安装 RF-DETR 依赖包。

安装核心依赖:

pip install torch==2.4.0
pip install torch_npu==2.4.0
pip install transformers peft pydantic supervision tqdm requests
pip install pycocotools scipy albumentations

修复 CANN TBE 环境缺失的 attr 模块:

pip install attrs decorator
cp /opt/rfdetr_venv/lib/python3.10/site-packages/attrs /usr/local/Ascend/ascend-toolkit/8.2.RC1/python/site-packages/ -r
cp /opt/rfdetr_venv/lib/python3.10/site-packages/decorator.py /usr/local/Ascend/ascend-toolkit/8.2.RC1/python/site-packages/

5. 训练迁移步骤

5.1 数据准备

将 COCO 数据集转换为标准格式存放于 /data/coco_formatted 目录,目录结构如下:

/data/coco_formatted/
├── annotations/
│   ├── instances_train2017.json
│   └── instances_val2017.json
├── train2017/
│   └── *.jpg
└── val2017/
    └── *.jpg

5.2 配置修改

关键适配修改点:

  1. 设备类型从 cuda 改为 npu。
  2. 分布式训练后端从 nccl 改为 hccl。
  3. 不使用 torch.compile() 函数(NPU backend 不支持)。
  4. torch.npu.set_compile_mode(jit_compile=False) 可选设置,经测试不关闭 JIT 也能正常训练。
  5. DDP 训练设置 find_unused_parameters=True。
  6. 设置 TASK_QUEUE_ENABLE=0 和 ACL_OP_INIT_MODE=1 绕过 TBE 算子编译问题。
  7. 训练前执行 warmup 预热,确保 NPU 算子编译完成。

5.3 单卡训练

单卡训练脚本:[train_npu_native.py]

启动单卡训练:

export ASCEND_RT_VISIBLE_DEVICES=4
python train_npu_native.py --epochs 10 --batch-size 8 --output-dir output/rfdetr_npu_single

单卡训练成功

5.4 多卡训练

多卡 DDP 训练脚本:train_npu_ddp.py

DDP 启动脚本:run_ddp.sh

启动 4 卡 DDP 训练:

./run_ddp.sh

或手动启动:

export ASCEND_RT_VISIBLE_DEVICES=4,5,6,7
/usr/local/python3.10/bin/python3.10 -m torch.distributed.launch \
    --nproc_per_node=4 \
    --master_addr=127.0.0.1 \
    --master_port=29500 \
    --use_env \
    train_npu_ddp.py \
    --epochs 50 \
    --batch-size 8 \
    --output-dir output/rfdetr_npu_4card

多卡训练成功

5.5 训练结果分析

短期训练结果(50 epochs)

训练完成 50 epochs 后,loss 从初始值 11.1578 下降至 6.2836,训练过程稳定。

训练日志关键数据:

Epoch 1 completed, loss: 11.1578
Epoch 10 completed, loss: 8.2097
Epoch 20 completed, loss: 7.7716
Epoch 30 completed, loss: 7.5393
Epoch 40 completed, loss: 7.3361
Epoch 50 completed, loss: 6.2836
Training completed! Best loss: 6.2836

完整训练结果(250 epochs)

继续训练至 250 epochs 后,loss 最终下降至 4.12,总体降幅约 63%。

完整训练曲线:

阶段Epoch范围Loss变化降幅
第1阶段1→5011.16 → 6.28-44%
第2阶段51→1006.28 → 6.28持平
第3阶段101→1506.27 → 5.40-14%
第4阶段151→2005.38 → 4.66-13%
第5阶段201→2504.67 → 4.12-12%

训练Loss曲线:

训练Loss曲线

训练速度:单卡约 1.0 it/s,4 卡 DDP 约 1.8 it/s,每 epoch 约 1.5 分钟。

输出模型文件:

  • output/rfdetr_npu_4card/best_model.pth:最佳模型权重(Epoch 248,loss=4.12)
  • output/rfdetr_npu_4card/model_epoch_*.pth:各 epoch checkpoint

6. 推理迁移步骤

6.1 PyTorch转换ONNX

  1. 安装 onnx 包。
  2. 使用 RF-DETR 提供的 ONNX 导出功能转换模型。
  3. 调用 model.export() 函数预热模型,准备导出。

安装 onnx 包:

pip install onnx

ONNX 导出脚本:

导出脚本内容:

import os
import sys

os.environ['TASK_QUEUE_ENABLE'] = '0'
os.environ['ACL_OP_INIT_MODE'] = '1'
os.environ['TBE_PARALLEL_COMPILER'] = '0'

venv_site_packages = "/opt/rfdetr_venv/lib/python3.10/site-packages"
sys.path.insert(0, venv_site_packages)
sys.path = [p for p in sys.path if 'python3.11' not in p]

import torch

from rfdetr.config import RFDETRNanoConfig, TrainConfig
from rfdetr._namespace import build_namespace
from rfdetr.models.lwdetr import build_model

model_config = RFDETRNanoConfig(num_classes=80)
train_config = TrainConfig(dataset_dir="/data/coco_formatted")
ns = build_namespace(model_config, train_config)

model = build_model(args=ns)

checkpoint = torch.load('best_model.pth', map_location='cpu')
model.load_state_dict(checkpoint['model_state_dict'])
model = model.float()
model.eval()

print("Calling model.export() to prepare for ONNX export...")
model.export()

resolution = 384
dummy_input = torch.randn(1, 3, resolution, resolution).float()

print(f"Exporting ONNX with resolution {resolution}x{resolution}...")

torch.onnx.export(
    model,
    dummy_input,
    'best_model.onnx',
    export_params=True,
    opset_version=17,
    do_constant_folding=True,
    input_names=['images'],
    output_names=['output'],
    dynamic_axes=None,
    dynamo=False
)

print("转换完成!输出文件: best_model.onnx")

执行 ONNX 导出:

export LD_LIBRARY_PATH=/usr/local/python3.10/lib:$LD_LIBRARY_PATH
export PYTHONPATH=/opt/rfdetr_venv/lib/python3.10/site-packages:/rf-detr/src:$PYTHONPATH
/opt/rfdetr_venv/bin/python3.10 export_onnx.py

校验 ONNX 模型:

python -c "import onnx; model = onnx.load('best_model.onnx'); onnx.checker.check_model(model); print('ONNX模型验证通过!')"

6.2 ONNX转换OM

使用 ATC 工具将 ONNX 模型转换为 OM 格式。

关键配置:

  1. 设置 CPLUS_INCLUDE_PATH 环境变量,解决 GridSample 算子编译失败问题。
  2. 使用 numpy 1.x 版本,避免 numpy 2.x 兼容性问题。
  3. 设置 TBE_PARALLEL_COMPILER=0 关闭并行编译。

OM 转换脚本:

转换脚本内容:

#!/bin/bash

source /usr/local/Ascend/ascend-toolkit/set_env.sh

export TBE_PARALLEL_COMPILER=0
export ASCEND_SLOG_PRINT_TO_STDOUT=0
export ASCEND_GLOBAL_LOG_LEVEL=3

export CPLUS_INCLUDE_PATH=/usr/include/c++/12:/usr/include/c++/12/aarch64-openEuler-linux:$CPLUS_INCLUDE_PATH
export C_INCLUDE_PATH=/usr/include:$C_INCLUDE_PATH

ONNX_MODEL="best_model.onnx"
OM_MODEL="best_model"
CHIP_TYPE="Ascend910B3"
INPUT_SHAPE="images:1,3,384,384"
PRECISION="allow_mix_precision"

echo "开始转换ONNX模型到OM格式..."
atc --model=$ONNX_MODEL \
    --framework=5 \
    --output=$OM_MODEL \
    --input_format=NCHW \
    --input_shape=$INPUT_SHAPE \
    --precision_mode=$PRECISION \
    --soc_version=$CHIP_TYPE

if [ $? -eq 0 ]; then
    echo "模型转换成功!OM文件已保存为: $OM_MODEL.om"
else
    echo "模型转换失败,请检查错误信息。"
    exit 1
fi

执行 OM 转换:

chmod +x convert_onnx_to_om.sh
./convert_onnx_to_om.sh

输出文件:best_model.om(约57MB)

6.3 OM模型推理

使用 ais_bench 进行 OM 模型推理。

安装 ais_bench:

pip install ais_bench

图片预处理脚本:

预处理脚本内容:

import cv2
import numpy as np
import glob
import os
import random

os.makedirs("bin", exist_ok=True)

MEAN = np.array([0.485, 0.456, 0.406])
STD = np.array([0.229, 0.224, 0.225])

val_images = glob.glob("/data/coco_formatted/val/*.jpg")
selected_images = random.sample(val_images, min(10, len(val_images)))

for f in selected_images:
    img = cv2.imread(f)
    img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
    img = cv2.resize(img, (384, 384))
    img = img.astype(np.float32) / 255.0
    img = (img - MEAN) / STD
    img = img.transpose(2, 0, 1)[None, ...].astype(np.float32)
    bin_name = f"bin/" + os.path.basename(f)[:-4] + ".bin"
    img.tofile(bin_name)
    print(f"Converted: {f} -> {bin_name}")

print(f"\nTotal converted: {len(selected_images)} images")

执行图片预处理:

python3 jpg_bin.py

OM 推理脚本:

推理脚本内容:

import os
import sys
import glob
import numpy as np

sys.path.insert(0, '/usr/local/lib/python3.11/site-packages')
sys.path.insert(0, '/usr/local/lib64/python3.11/site-packages')

from ais_bench.infer.interface import InferSession

os.makedirs("results", exist_ok=True)

session = InferSession(device_id=0, model_path="best_model.om")

bin_files = glob.glob("bin/*.bin")
print(f"Found {len(bin_files)} bin files")

for bin_file in bin_files:
    input_data = np.fromfile(bin_file, dtype=np.float32).reshape(1, 3, 384, 384)
    
    outputs = session.infer([input_data])
    
    result_name = f"results/" + os.path.basename(bin_file)[:-4] + "_output.bin"
    
    if isinstance(outputs, list):
        for i, output in enumerate(outputs):
            output_name = f"results/" + os.path.basename(bin_file)[:-4] + f"_output_{i}.bin"
            if isinstance(output, np.ndarray):
                output.tofile(output_name)
                print(f"Saved: {output_name}, shape: {output.shape}")
    else:
        if isinstance(outputs, np.ndarray):
            outputs.tofile(result_name)
            print(f"Saved: {result_name}, shape: {outputs.shape}")
    
    print(f"Processed: {bin_file}")

print(f"\nTotal processed: {len(bin_files)} images")

执行 OM 推理:

export ASCEND_RT_VISIBLE_DEVICES=0
python3 om_inference.py

6.4 推理结果分析

OM 推理脚本(图片直接推理)

推荐使用 inference_om.py 脚本进行图片直接推理,无需手动转换为 bin 文件。

推理脚本:inference_om.py

执行推理:

source /usr/local/Ascend/ascend-toolkit/8.2.RC1/aarch64-linux/script/set_env.sh
python3.11 inference_om.py \
    -m best_model_epoch248.om \
    -i /data/coco_formatted/val/000000200839.jpg \
    --threshold 0.5 \
    --output result.jpg

参数说明:

参数说明默认值
-mOM模型路径必需
-i输入图片/目录必需
--threshold置信度阈值0.3
--output输出图片路径output_om.jpg
--deviceNPU设备ID0

推理结果示例

测试图片检测结果:

Detected 6 objects (threshold=0.5)
  [1] airplane: score=0.9427, box=[92.2, 170.1, 477.2, 316.0]
  [2] refrigerator: score=0.7923, box=[142.9, 240.4, 179.3, 271.9]
  [3] refrigerator: score=0.7400, box=[199.4, 237.6, 230.6, 275.2]
  [4] refrigerator: score=0.7370, box=[234.5, 201.8, 265.8, 244.2]
  [5] refrigerator: score=0.6601, box=[360.1, 193.9, 408.7, 260.4]
  [6] refrigerator: score=0.5389, box=[305.8, 192.2, 341.7, 243.2]

置信度分布分析(10张测试图片)

指标值
最高置信度0.77(airplane检测)
平均置信度0.103
threshold≥0.368个有效检测
threshold≥0.518个高置信检测
threshold≥0.74个非常确定检测

置信度分布:

  • [0.0, 0.1): 69.7%
  • [0.1, 0.2): 22.7%
  • [0.2, 0.3): 4.4%
  • [0.3, 0.5): 2.4%
  • [0.5, 0.7): 0.7%
  • [0.7, 1.0): 0.2%

推理结果可视化示例:

OM推理检测结果

OM 模型输出格式说明

模型输出两个 tensor:

  • output_0: (1, 300, 4) - 检测框坐标(cx, cy, w, h 格式),归一化坐标 [0, 1]
  • output_1: (1, 300, 81) - 分类 logits(80类 + 1背景),需使用 sigmoid 激活

后处理步骤:

  1. 使用 sigmoid(logits[:, 1:]) 获取类别概率(跳过背景类 index 0)
  2. 取最大概率作为置信度:score = max(probs)
  3. 类别 ID = argmax(probs) + 1
  4. 坐标转换:xyxy = [cx - w/2, cy - h/2, cx + w/2, cy + h/2]
  5. 缩放至原图尺寸:乘以原图宽高

检测结果保存于 vis_results/ 目录,包含标注框的可视化图片。