Skip to content

Yolov11-n 模型int8量化误差过大 #5916

@WYL-Projects

Description

@WYL-Projects

问题描述

在我对自己训练的yolov11-n ncnn模型进行int8量化后,int8模型推理图像出现了目标框不准的问题,我执行了以下命令进行模型量化:

../ncnnoptimize yolov11n.param yolov11n.bin yolov11n_opt.param yolov11n_opt.bin 0
../quantize/ncnn2table yolov11_opt.param yolov11_opt.bin data.txt yolov11n.table mean=[104,117,123] norm=[0.017,0.017,0.017] shape=[640,640,3] pixel=BGR thread=8 method=kl
../quantize/ncnn2int8 yolov11n_opt.param yolov11n_opt.bin yolov11n-int8.param yolov11n-int8.bin yolov11n.table

为了对比yolov11n和yolov11n-int8 ncnn模型的检测效果,我执行了以下代码:


import numpy as np
import ncnn
import torch

from ultralytics.data.augment import LetterBox
from ultralytics.engine.results import Results
from ultralytics.utils import ops
from PIL import Image
import cv2


def test_inference(image_path):
    im = cv2.imread(image_path)
    ori_img_shape = im.shape[:2]
    new_shape = (640, 640)
    pre_tranform = LetterBox(new_shape=(640,640), auto=False, stride=32)
    resized_image = pre_tranform(image=im)
    resized_image = resized_image[..., ::-1].transpose((2, 0, 1))  # BGR to RGB, BHWC to BCHW, (n, 3, h, w)
    resized_image = np.ascontiguousarray(resized_image)
    image_normalized  = resized_image / 255.0
    image_normalized = image_normalized.astype(np.float32) 
 
    outs = []
    with ncnn.Net() as net:
        net.load_param("runs/detect/vstd_yolov11/v1.1/weights/best_ncnn_model/yolov11n-int8.param")
        net.load_model("runs/detect/vstd_yolov11/v1.1/weights/best_ncnn_model/yolov11n-int8.bin")
        net.opt.use_int8_inference = True

        with net.create_extractor() as ex:
            ex.input("in0", ncnn.Mat(image_normalized).clone())
            # ex.input("in0", ncnn.Mat(image_normalized).clone())

            _, out0 = ex.extract("out0")
            outs.append(torch.from_numpy(np.array(out0)).unsqueeze(0))
    out = outs[0]
    out_mean = torch.mean(out)
    out_max = torch.max(out)
    out_min = torch.min(out)
    print(out.shape, out_mean, out_max, out_min)

    # 后处理
    classes_name = ["person", "biycle", "car", "motorcycle", "bus", "truck"]
    pred = ops.non_max_suppression(
        out,
        0.5,
        0.5,
        agnostic=False,
        max_det=300
    )[0]
    pred[:, :4] = ops.scale_boxes(new_shape, pred[:, :4], ori_img_shape)
    r = Results(im, path=image_path, names=classes_name, boxes=pred)
    r.save(filename=f"datasets/000000001532_int8.jpg", line_width=2)
    print(pred)
    

    

if __name__ == "__main__":
    image_path = "/data/object_detection/coco2017/000000001532.jpg"
    test_inference(image_path)

以下是模型的推理结果,上图是float32的效果,下图是int8的效果:

Image

Image

请问这种量化误差过大的问题如何解决?我目前没啥头绪,期待回复!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions