YOLOV7量化第一步: 准备模型

news2024/11/19 8:49:23

1. 准备模型 手动/自动插入QDQ节点

1.1 准备容器

准备容器的时候有可能出现共享内存的问题, 这里在启动容器的时候设置一下,

# 增加了里面的共享内存
docker run --gpus all -it --shm-size=64g --name env_pyt_1.12 -v $(pwd):/app nvcr.io/nvidia/pytorch:22.03-py3 ```

美式的做法是

.
├── __pycache__
├── my_ptq.py
├── ptq.py
├── qat.py
├── quantize.py
├── rules.py
├── yolov7
└── yolov7.pt

实际做的时候会有路径的问题,最简单的办法就是直接去yolov7文件夹里面写

1.2 加载数据集然后进行一个简单的验证

这里面的create DataLoader是使用的是yolov7里面自带的, 下面是官方的create_dataloader代码

def create_dataloader(path, imgsz, batch_size, stride, opt, hyp=None, augment=False, cache=False, pad=0.0, rect=False,
                      rank=-1, world_size=1, workers=8, image_weights=False, quad=False, prefix=''):
    # Make sure only the first process in DDP process the dataset first, and the following others can use the cache
    with torch_distributed_zero_first(rank):
        dataset = LoadImagesAndLabels(path, imgsz, batch_size,
                                      augment=augment,  # augment images
                                      hyp=hyp,  # augmentation hyperparameters
                                      rect=rect,  # rectangular training
                                      cache_images=cache,
                                      single_cls=opt.single_cls,
                                      stride=int(stride),
                                      pad=pad,
                                      image_weights=image_weights,
                                      prefix=prefix)

    batch_size = min(batch_size, len(dataset))
    nw = min([os.cpu_count() // world_size, batch_size if batch_size > 1 else 0, workers])  # number of workers
    sampler = torch.utils.data.distributed.DistributedSampler(dataset) if rank != -1 else None
    loader = torch.utils.data.DataLoader if image_weights else InfiniteDataLoader
    # Use torch.utils.data.DataLoader() if dataset.properties will update during training else InfiniteDataLoader()
    dataloader = loader(dataset,
                        batch_size=batch_size,
                        num_workers=nw,
                        sampler=sampler,
                        pin_memory=True,
                        collate_fn=LoadImagesAndLabels.collate_fn4 if quad else LoadImagesAndLabels.collate_fn)
    return dataloader, dataset

下面是我们自己的代码
注意这里面的op是一个对象,这里用collections.namedtuple("Opt", "single_cls")(False)
是为了设置Opt这个对象里面的"single_cls"是False, 它里面还有其他的参数, 这里因为yolov7里面返回的是两个,第一个是data loader, 第二个是dataset

def prepare_dataset(cocodir, batch_size=8):   
    dataloader = create_dataloader(         # 这里的参数是跟官网的是一样的
        f"{cocodir}/val2017.txt",
        imgsz=640,
        batch_size=batch_size,
        opt=collections.namedtuple("Opt", "single_cls")(False),
        augment=False, hyp=None, rect=True, cache=False, stride=32, pad=0.5, image_weights=False
        )[0]
    return dataloader

下面是验证coco的函数, 这里就是把plot关了我们不用可视化的内容,然后官方test的内容第一个和第四个是mp和map, 这两个是我们要的参数, 这里的map是0.5-0.95的
在这里插入图片描述

def evaluate_coco(model, loader, save_dir='.', conf_thres=0.001, iou_thres=0.65):
    
    if save_dir and os.path.dirname(save_dir) != "":
        os.makedirs(os.path.dirname(save_dir), exist_ok=True)

    return test.test(
        "./data/coco.yaml",
        save_dir=Path(save_dir),
        conf_thres=conf_thres,
        iou_thres=iou_thres,
        model=model,
        dataloader=loader,
        is_coco=True,
        plots=False,
        half_precision=True,
        save_json=False
    )[0][3] 
import torch
from pytorch_quantization import quant_modules 
from models.yolo import Model
import sys


def load_yolov7_model(weight, device="cpu"):
    ckpt = torch.load(weight, map_location=device)                                  # 加载模型,模型参数在哪个设备上
    model = Model("cfg/training/yolov7.yaml", ch=3, nc=80).to(device)               # 跟yolov7的结构,这里没有包含参数
    state_dict = ckpt["model"].float().state_dict()                                 # 从加载的权重中提取模型的状态字典(state_dict), 包含了模型全部的参数,包括卷积权重等
    model.load_state_dict(state_dict, strict=False)                                 # 把提取出来的参数放到yolov7的结构中
    return model                                                                    # 返回正确权重和参数的模型

import collections
from utils.datasets import create_dataloader
def prepare_dataset(cocodir, batch_size=8):   
    dataloader = create_dataloader(         # 这里的参数是跟官网的是一样的
        f"{cocodir}/val2017.txt",
        imgsz=640,
        batch_size=batch_size,
        opt=collections.namedtuple("Opt", "single_cls")(False),
        augment=False, hyp=None, rect=True, cache=False, stride=32, pad=0.5, image_weights=False
        )[0]
    return dataloader

import test as test 
from pathlib import Path
import os
def evaluate_coco(model, loader, save_dir='.', conf_thres=0.001, iou_thres=0.65):
    
    if save_dir and os.path.dirname(save_dir) != "":
        os.makedirs(os.path.dirname(save_dir), exist_ok=True)

    return test.test(
        "./data/coco.yaml",
        save_dir=Path(save_dir),
        conf_thres=conf_thres,
        iou_thres=iou_thres,
        model=model,
        dataloader=loader,
        is_coco=True,
        plots=False,
        half_precision=True,
        save_json=False
    )[0][3]


if __name__ == "__main__":
    weight = "../yolov7.pt"
    device = torch.device("cuda:2" if torch.cuda.is_available() else "cpu")
    
    model = load_yolov7_model(weight=weight, device=device)
    
    cocodir = "/app/dataset/coco2017"    #../dataset/coco2017
    
    dataloader = prepare_dataset(cocodir=cocodir, )
    
    ap = evaluate_coco(model, dataloader)
    

首先,让我们看一下代码的输出:

Scanning '/app/dataset/coco2017/val2017.cache' images and labels... 4952 found, 48 missing, 0 empty, 0 corrupted: 100%|██████████████████████| 5000/5000 [00:00<?, ?it/s]
               Class      Images      Labels           P           R      mAP@.5  mAP@.5:.95: 100%|████████████████████████████████████| 625/625 [00:40<00:00, 15.29it/s]
                 all        5000       36781       0.718       0.626       0.676       0.452

这个输出提供了您模型在COCO 2017验证数据集上的性能评估。我将为您逐个解释关键指标:

  1. Scanning…:

    • 这一行显示了数据加载的状态。4952张图片和标签被找到,48张图片缺失,没有空标签,也没有损坏的标签。
  2. Class, Images, Labels:

    • Class: 分类的名称。在这里,“all”表示考虑所有分类。
    • Images: 总共测试的图像数量。这里是5000。
    • Labels: 在这5000张图片中,总共有36781个对象标签。
  3. P (Precision): 这是模型的精确度,值为0.718。这意味着当模型预测某个对象存在时,它有71.8%的概率是正确的。

  4. R (Recall): 这是模型的召回率,值为0.626。这意味着模型能够正确检测到62.6%的实际存在的对象。

  5. mAP@.5: 这是在IoU(Intersection over Union)阈值为0.5时的平均精度。IoU是预测的边界框和真实边界框之间的交集与并集之比。值为0.676表示在IoU=0.5时,模型的平均精度为67.6%。

  6. mAP@.5:.95: 这是在IoU从0.5到0.95的范围内的平均精度(以0.05为步长)。在COCO数据集上,这是一个非常重要的指标,因为它考虑了不同IoU阈值下的性能。值为0.452表示平均精度为45.2%。

简单来说,mAP(mean Average Precision)是评估物体检测模型性能的关键指标。它考虑了模型的精确度和召回率,并为每个类别计算AP(平均精度),然后取所有类别的AP的平均值得到mAP。

总体上,这些指标为您提供了模型在COCO 2017验证数据集上的性能概览。您可以使用这些指标来比较不同模型或相同模型的不同版本的性能。

1.3 准备自动插入QDQ节点模型

def prepare_model(weight, device):
    quant_modules.initialize()   # 自动加载qdq节点
    # initialize()
    model = load_yolov7_model(weight, device)
    model.float()
    model.eval()
    with torch.no_grad():
        model.fuse()  # conv bn 进行层的合并, 加速
    return model
    
if __name__ == "__main__":
    weight = "../yolov7.pt"
    device = torch.device("cuda:2" if torch.cuda.is_available() else "cpu")
    
    # load最初版本的模型
    pth_model = load_yolov7_model(weight=weight, device=device)
    print(pth_model)
    
    # 加载自动插入QDQ节点的模型
    model = prepare_model(weight=weight, device=device)
    print(model)

这里对比了一下自动插入的QDQ节点的模型, 通过打印的方式可以看到这里确实是有自动插入的节点

      (cv3): Conv(
        (conv): QuantConv2d(
          512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)
          (_input_quantizer): TensorQuantizer(8bit narrow fake per-tensor amax=dynamic calibrator=MaxCalibrator scale=1.0 quant)
          (_weight_quantizer): TensorQuantizer(8bit narrow fake axis=0 amax=dynamic calibrator=MaxCalibrator scale=1.0 quant)

下面是自动插入QDQ节点计算出来的map, 可以看出来其实是跟直接计算coco的是一样的,

Scanning '/app/dataset/coco2017/val2017.cache' images and labels... 4952 found, 48 missing, 0 empty, 0 corrupted: 100%|██████████████████████████████████████████████████| 5000/5000 [00:00<?, ?it/s]
               Class      Images      Labels           P           R      mAP@.5  mAP@.5:.95: 100%|████████████████████████████████████████████████████████████████| 625/625 [01:03<00:00,  9.78it/s]
                 all        5000       36781       0.722       0.622       0.675       0.452

1.4 手动插入QDQ节点在这里插入图片描述

1.4.1. 定义模块映射

首先,我们有一个预定义的_DEFAULT_QUANT_MAP列表,它为原始PyTorch模块(如torch.nn.Conv2d)和它们的量化版本(如quant_nn.QuantConv2d)提供了映射关系。

1.4.2. 构建ID到量化模块的字典

replace_to_quantization_model函数中,我们遍历_DEFAULT_QUANT_MAP列表并使用getattr函数动态地从torch.nn或其他模块中获取对应的类。然后,我们为这些类创建一个ID到量化版本的映射,并将其存储在module_dict字典中。

1.4.3. 递归地遍历模型的子模块

接下来,我们使用torch_module_find_quant_module函数递归地遍历整个模型的子模块。对于每个子模块,我们查看它的ID是否出现在module_dict字典中,以确定是否需要进行量化替换。

1.4.4. 检查忽略列表

在决定是否替换子模块之前,我们首先检查它是否出现在ignore_layer列表中。如果在这个列表中,那么我们不对它进行量化替换。这是通过quantization_ignore_match函数实现的。

1.4.5. 执行量化替换

如果一个子模块需要被量化并且不在忽略列表中,我们使用transfer_torch_to_quantization函数执行替换。这个函数首先为量化模块创建一个新的实例,然后复制原始模块的所有属性到新的量化模块。接着,它使用内部的__init__方法来完成量化初始化过程,包括设置量化描述符和校准器。

import torch
from pytorch_quantization import quant_modules 
from models.yolo import Model
from pytorch_quantization.nn.modules import _utils as quant_nn_utils
from pytorch_quantization import calib
import sys
import re
import yaml
import os
os.chdir("/app/bob/yolov7_QAT/yolov7")



def load_yolov7_model(weight, device="cpu"):
    ckpt = torch.load(weight, map_location=device)                                  # 加载模型,模型参数在哪个设备上
    model = Model("cfg/training/yolov7.yaml", ch=3, nc=80).to(device)               # 跟yolov7的结构,这里没有包含参数
    state_dict = ckpt["model"].float().state_dict()                                 # 从加载的权重中提取模型的状态字典(state_dict), 包含了模型全部的参数,包括卷积权重等
    model.load_state_dict(state_dict, strict=False)                                 # 把提取出来的参数放到yolov7的结构中
    return model                                                                    # 返回正确权重和参数的模型

import collections
from utils.datasets import create_dataloader
def prepare_dataset(cocodir, batch_size=8):   
    dataloader = create_dataloader(         # 这里的参数是跟官网的是一样的
        f"{cocodir}/val2017.txt",
        imgsz=640,
        batch_size=batch_size,
        opt=collections.namedtuple("Opt", "single_cls")(False),  # collections.namedtuple("Opt", "single_cls")(False)
        augment=False, hyp=None, rect=True, cache=False, stride=32, pad=0.5, image_weights=False,
        )[0]
    return dataloader

import test as test 
from pathlib import Path
import os
def evaluate_coco(model, loader, save_dir='.', conf_thres=0.001, iou_thres=0.65):
    
    if save_dir and os.path.dirname(save_dir) != "":
        os.makedirs(os.path.dirname(save_dir), exist_ok=True)

    return test.test(
        "./data/coco.yaml",
        save_dir=Path(save_dir),
        conf_thres=conf_thres,
        iou_thres=iou_thres,
        model=model,
        dataloader=loader,
        is_coco=True,
        plots=False,
        half_precision=True,
        save_json=False
    )[0][3]     
    
def prepare_model(weight, device):
    # quant_modules.initialize()   # 自动加载qdq节点
    # initialize()
    model = load_yolov7_model(weight, device)
    model.float()
    model.eval()
    with torch.no_grad():
        model.fuse()  # conv bn 进行层的合并, 加速
    return model

# 执行量化替换
def transfer_torch_to_quantization(nn_instance, quant_mudule):
    quant_instance = quant_mudule.__new__(quant_mudule)
    for k, val in vars(nn_instance).items():
        setattr(quant_instance, k, val)

    def __init__(self):
        # 返回两个QuantDescriptor的实例    self.__class__是quant_instance的类, EX: QuantConv2d
        quant_desc_input, quant_desc_weight = quant_nn_utils.pop_quant_desc_in_kwargs(self.__class__)
        if isinstance(self, quant_nn_utils.QuantInputMixin):
            self.init_quantizer(quant_desc_input)
            if isinstance(self._input_quantizer._calibrator, calib.HistogramCalibrator):
                self._input_quantizer._calibrator._torch_hist = True
        else:
            self.init_quantizer(quant_desc_input, quant_desc_weight)

            if isinstance(self._input_quantizer._calibrator, calib.HistogramCalibrator):
                self._input_quantizer._calibrator._torch_hist = True
                self._weight_quantizer._calibrator._torch_hist = True

    __init__(quant_instance)
    return quant_instance

def quantization_ignore_match(ignore_layer, path):
    if ignore_layer is None:
        return False
    if isinstance(ignore_layer, str) or isinstance(ignore_layer, list):
        if isinstance(ignore_layer, str):
            ignore_layer = [ignore_layer]
        if path in ignore_layer:
            return True
        for item in ignore_layer:
            if re.match(item, path):  
                return True  
    return False

# 递归函数
def torch_module_find_quant_module(module, module_dict, ignore_layer, prefix=''):
    for name in module._modules:
        submodule = module._modules[name]
        path =  name if prefix == '' else prefix + '.' + name
        torch_module_find_quant_module(submodule, module_dict, ignore_layer, prefix=path)

        submodule_id = id(type(submodule))
        if submodule_id in module_dict:
            ignored = quantization_ignore_match(ignore_layer, path)
            if ignored:
                print(f"Quantization : {path} has ignored.")
                continue
            # 转换
            module._modules[name] = transfer_torch_to_quantization(submodule, module_dict[submodule_id])

# 用量化模型替换
def replace_to_quantization_model(model, ignore_layer=None):
    """
    这里构建的module_dict里面的元素是一个映射的关系, 例如torch.nn -> quant_nn.QuantConv2d, 一共是15个, 跟DEFAULT_QUANT_MAP对齐
    """
    module_dict = {}
    for entry in quant_modules._DEFAULT_QUANT_MAP:           # 构建module_dict, 把DEFAULT_QUANT_MAP填充
        module = getattr(entry.orig_mod, entry.mod_name)     # 提取的原始的模块,从torch.nn中获取conv2d这个字符串
        module_dict[id(module)] = entry.replace_mod          # 使用替换的模块
    torch_module_find_quant_module(model, module_dict, ignore_layer)
    
if __name__ == "__main__":
    weight = "./yolov7.pt"
    device = torch.device("cuda:2" if torch.cuda.is_available() else "cpu")
    
    # load最初版本的模型
    pth_model = load_yolov7_model(weight=weight, device=device)
    # print(pth_model)
    
    # 加载自动插入QDQ节点的模型
    model = prepare_model(weight=weight, device=device)
    replace_to_quantization_model(model)
    print(model)
    
    cocodir = "/app/dataset/coco2017"    #../dataset/coco2017
    
    dataloader = prepare_dataset(cocodir=cocodir, )
    
    ap = evaluate_coco(pth_model, dataloader)
    

因为这里没有训练,所以计算出来的map也不会有太大的变化

Scanning '/app/dataset/coco2017/val2017.cache' images and labels... 4952 found, 48 missing, 0 empty, 0 corrupted: 100%|| 5000/5000 [00:00<?, 
               Class      Images      Labels           P           R      mAP@.5  mAP@.5:.95: 100%|█████████| 625/625 [00:41<00:00, 15.18it/s]
                 all        5000       36781       0.724       0.621       0.675       0.453

同样这个得量化也可以看出来是默认的per-tensor, MaxCalibrator, 后面要手动initiative来设置成Hstgram的量化校准器

      (conv): QuantConv2d(
        1024, 512, kernel_size=(1, 1), stride=(1, 1)
        (_input_quantizer): TensorQuantizer(8bit narrow fake per-tensor amax=dynamic calibrator=MaxCalibrator scale=1.0 quant)
        (_weight_quantizer): TensorQuantizer(8bit narrow fake axis=0 amax=dynamic calibrator=MaxCalibrator scale=1.0 quant)
      )

1.5 手动initlize()

手动初始化插入节点可以更好的控制好整个流程, 这里的做了一件事,就是通过设置参数把校准器从Max换到Hisgram, 这里改的把conv2d, MaxPool2d, Linear, 的input设置成Hisgram, 这里也可以设置成weight的校准器成Histgram

    quant_desc_input = QuantDescriptor(calib_method="histogram")   # "max" 
    quant_nn.QuantConv2d.set_default_quant_desc_input(quant_desc_input)
    quant_nn.QuantConv2d.set_default_quant_desc_weight(quant_desc_input)
        (2): QuantConv2d(
          1024, 255, kernel_size=(1, 1), stride=(1, 1)
          (_input_quantizer): TensorQuantizer(8bit narrow fake per-tensor amax=dynamic calibrator=MaxCalibrator scale=1.0 quant)
          (_weight_quantizer): TensorQuantizer(8bit narrow fake axis=0 amax=dynamic calibrator=MaxCalibrator scale=1.0 quant)
        )

这种就是设置weight和input的校准器都是直方图校准

        (2): QuantConv2d(
          1024, 255, kernel_size=(1, 1), stride=(1, 1)
          (_input_quantizer): TensorQuantizer(8bit narrow fake per-tensor amax=dynamic calibrator=HistogramCalibrator scale=1.0 quant)
          (_weight_quantizer): TensorQuantizer(8bit narrow fake per-tensor amax=dynamic calibrator=HistogramCalibrator scale=1.0 quant)
        )

下面是对比的手动插入QDQ节点的map计算和直接load模型的map, 从这里可以看出来因为没有训练,所以这边都是一样的

Scanning '/app/dataset/coco2017/val2017.cache' images and labels... 4952 found, 48 missing, 0 empty, 0 corrupted:
Origin Pth Model map: 
               Class      Images      Labels           P           R      mAP@.5  mAP@.5:.95: 100%|| 625/625 [00
                 all        5000       36781       0.724       0.622       0.676       0.453
auto QDQ Model map: 
               Class      Images      Labels           P           R      mAP@.5  mAP@.5:.95: 100%|| 625/625 [01
                 all        5000       36781       0.705       0.633       0.672       0.444

完整代码

import torch
from pytorch_quantization import quant_modules 
from models.yolo import Model
from pytorch_quantization.nn.modules import _utils as quant_nn_utils
from pytorch_quantization import calib
import sys
import re
import yaml
import os
os.chdir("/app/bob/yolov7_QAT/yolov7")



def load_yolov7_model(weight, device="cpu"):
    ckpt = torch.load(weight, map_location=device)                                  # 加载模型,模型参数在哪个设备上
    model = Model("cfg/training/yolov7.yaml", ch=3, nc=80).to(device)               # 跟yolov7的结构,这里没有包含参数
    state_dict = ckpt["model"].float().state_dict()                                 # 从加载的权重中提取模型的状态字典(state_dict), 包含了模型全部的参数,包括卷积权重等
    model.load_state_dict(state_dict, strict=False)                                 # 把提取出来的参数放到yolov7的结构中
    return model                                                                    # 返回正确权重和参数的模型

import collections
from utils.datasets import create_dataloader
def prepare_dataset(cocodir, batch_size=8):   
    dataloader = create_dataloader(         # 这里的参数是跟官网的是一样的
        f"{cocodir}/val2017.txt",
        imgsz=640,
        batch_size=batch_size,
        opt=collections.namedtuple("Opt", "single_cls")(False),  # collections.namedtuple("Opt", "single_cls")(False)
        augment=False, hyp=None, rect=True, cache=False, stride=32, pad=0.5, image_weights=False,
        )[0]
    return dataloader

import test as test 
from pathlib import Path
import os
def evaluate_coco(model, loader, save_dir='.', conf_thres=0.001, iou_thres=0.65):
    
    if save_dir and os.path.dirname(save_dir) != "":
        os.makedirs(os.path.dirname(save_dir), exist_ok=True)

    return test.test(
        "./data/coco.yaml",
        save_dir=Path(save_dir),
        conf_thres=conf_thres,
        iou_thres=iou_thres,
        model=model,
        dataloader=loader,
        is_coco=True,
        plots=False,
        half_precision=True,
        save_json=False
    )[0][3]   
    
      
from pytorch_quantization import nn as quant_nn
from pytorch_quantization.tensor_quant import QuantDescriptor
from absl import logging as quant_logging
# intput QuantDescriptor: Max ==> Histogram
def initialize():
    quant_desc_input = QuantDescriptor(calib_method="histogram")
    quant_nn.QuantConv2d.set_default_quant_desc_input(quant_desc_input)
    quant_nn.QuantMaxPool2d.set_default_quant_desc_input(quant_desc_input)
    quant_nn.QuantLinear.set_default_quant_desc_input(quant_desc_input)
    quant_logging.set_verbosity(quant_logging.ERROR)
    
def prepare_model(weight, device):
    # quant_modules.initialize()   # 自动加载qdq节点
    initialize()                 # intput QuantDescriptor: Max ==> Histogram
    model = load_yolov7_model(weight, device)
    model.float()
    model.eval()
    with torch.no_grad():
        model.fuse()  # conv bn 进行层的合并, 加速
    return model

# 执行量化替换
def transfer_torch_to_quantization(nn_instance, quant_mudule):
    quant_instance = quant_mudule.__new__(quant_mudule)
    for k, val in vars(nn_instance).items():
        setattr(quant_instance, k, val)

    def __init__(self):
        # 返回两个QuantDescriptor的实例    self.__class__是quant_instance的类, EX: QuantConv2d
        quant_desc_input, quant_desc_weight = quant_nn_utils.pop_quant_desc_in_kwargs(self.__class__)
        if isinstance(self, quant_nn_utils.QuantInputMixin):
            self.init_quantizer(quant_desc_input)
            if isinstance(self._input_quantizer._calibrator, calib.HistogramCalibrator):
                self._input_quantizer._calibrator._torch_hist = True
        else:
            self.init_quantizer(quant_desc_input, quant_desc_weight)

            if isinstance(self._input_quantizer._calibrator, calib.HistogramCalibrator):
                self._input_quantizer._calibrator._torch_hist = True
                self._weight_quantizer._calibrator._torch_hist = True

    __init__(quant_instance)
    return quant_instance

def quantization_ignore_match(ignore_layer, path):
    if ignore_layer is None:
        return False
    if isinstance(ignore_layer, str) or isinstance(ignore_layer, list):
        if isinstance(ignore_layer, str):
            ignore_layer = [ignore_layer]
        if path in ignore_layer:
            return True
        for item in ignore_layer:
            if re.match(item, path):  
                return True  
    return False

# 递归函数
def torch_module_find_quant_module(module, module_dict, ignore_layer, prefix=''):
    for name in module._modules:
        submodule = module._modules[name]
        path =  name if prefix == '' else prefix + '.' + name
        torch_module_find_quant_module(submodule, module_dict, ignore_layer, prefix=path)

        submodule_id = id(type(submodule))
        if submodule_id in module_dict:
            ignored = quantization_ignore_match(ignore_layer, path)
            if ignored:
                print(f"Quantization : {path} has ignored.")
                continue
            # 转换
            module._modules[name] = transfer_torch_to_quantization(submodule, module_dict[submodule_id])

# 用量化模型替换
def replace_to_quantization_model(model, ignore_layer=None):
    """
    这里构建的module_dict里面的元素是一个映射的关系, 例如torch.nn -> quant_nn.QuantConv2d, 一共是15个, 跟DEFAULT_QUANT_MAP对齐
    """
    module_dict = {}
    for entry in quant_modules._DEFAULT_QUANT_MAP:           # 构建module_dict, 把DEFAULT_QUANT_MAP填充
        module = getattr(entry.orig_mod, entry.mod_name)     # 提取的原始的模块,从torch.nn中获取conv2d这个字符串
        module_dict[id(module)] = entry.replace_mod          # 使用替换的模块
    torch_module_find_quant_module(model, module_dict, ignore_layer)
    
if __name__ == "__main__":
    weight = "./yolov7.pt"
    device = torch.device("cuda:2" if torch.cuda.is_available() else "cpu")
    
    # load最初版本的模型
    pth_model = load_yolov7_model(weight=weight, device=device)
    # print(pth_model)
    
    # 加载自动插入QDQ节点的模型
    model = prepare_model(weight=weight, device=device)
    replace_to_quantization_model(model)
    print(model)
    
    cocodir = "/app/dataset/coco2017"    #../dataset/coco2017
    
    dataloader = prepare_dataset(cocodir=cocodir, )
    
    print("Origin Pth Model map: ")
    ap = evaluate_coco(pth_model, dataloader)
    
    print("auto QDQ Model map: ")
    auto_ap = evaluate_coco(model, dataloader)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1095193.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

浏览器本地存储之Cookie和webStorage

浏览器本地存储主要包括 Cookie 和 Web Storage 两种机制。它们都是用来在客户端存储数据&#xff0c;以便在浏览器会话之间保持信息或在同一会话中的页面之间共享信息。 一、Cookie 1.1 概念 cookie是客户端与服务器端进行会话使用的一个能够在浏览器本地化存储的技术。简言…

【Hyper-V】Windows的Hyper-V管理器创建的虚拟机上怎么复制粘贴文件

在hyper-V 管理器中创建的虚拟机里面&#xff0c;发现它是不能直接复制粘贴文件的&#xff0c;那只能粘贴纯文本内容&#xff0c;也就是模拟输入内容&#xff0c;这是虚拟系统是被隔离的&#xff0c;也带来不便之处&#xff0c;要怎么解决这个限制呢。 例如&#xff0c;打开一…

Frame Buffer设备驱动 (ili9488 3.5寸tft屏)

Frame Buffer设备驱动 Frame Buffer设备ili9488介绍驱动编写代码编写ili9488.c设备树修改测试ili9488代码分析 LCD资料下载 Frame Buffer设备 在早期的输出显示设备中&#xff0c;大部分为CRT显示器&#xff0c;随着技术的不断发展&#xff0c;现在大部分使用的是液晶显示器。这…

RabbitMQ死信队列原理与项目代码示例

1、产生死信消息的原因 当在消费消息时&#xff0c;如果队列里的消息出现以下情况&#xff0c;那么该消息将成为一条死信消息&#xff1a; 当一条消息被使用 channel.basicNack方法 或 channel.basicReject方法所nack响应 &#xff0c;并且此时requeue 属性被设置为false。 消…

使用Elasticsearch来进行简单的DDL搜索数据

说明&#xff1a;Elasticsearch提供了多种多样的搜索方式来满足不同使用场景的需求&#xff0c;我们可以使用Elasticsearch来进行各种复制的查询&#xff0c;进行数据的检索。 1.1 精准查询 用来查询索引中某个类型为keyword的文本字段&#xff0c;类似于SQL的“”查询。 创…

Python学习基础笔记六十七——格式化字符串

Printf-Style String Formatting: Printf风格字符串格式化 salary input(请输入薪资&#xff1a;)# 计算出缴税额&#xff0c;存入变量tax tax int(salary) *25/100 # 转化为字符串&#xff0c;方便下面的字符串拼接 taxStr str(tax) # 计算出税后工资&#xff0c;存入变…

Linux基础—1

1、命令行 1) 重要快捷键 按键作用Tab命令补全Ctrl强行终止当前程序Ctrld键盘输入结束或退出终端Ctrls暂停当前程序&#xff0c;暂停后按下任意键恢复运行Ctrlz将当前程序放到后台运行&#xff0c;恢复到前台为命令fgCtrla将光标移至输入行头&#xff0c;相当于Home键Ctrle将…

计算机操作系统-第六天

目录 1、操作系统的体系结构&#xff08;简要了解&#xff09; 操作系统的内核&#xff1a; 操作系统的体系结构 关于微内核的相关理解&#xff1a; 本节思维导图&#xff1a; 1、操作系统的体系结构&#xff08;简要了解&#xff09; 操作系统的内核&#xff1a; 内核是…

整理总结提高抖音小店商品转化率的五大策略

要提高抖音小店的商品转化率&#xff0c;即将浏览者转化为实际购买者&#xff0c;四川不若与众整理了需要注意的以下几个关键因素。 首先&#xff0c;优化商品页面设计。商品页面是消费者获取产品信息和决策的关键环节。商家应确保商品页面简洁清晰&#xff0c;配备高质量的产品…

Pytest+Allure生成可添加附件的测试报告

#测试套件层级 allure.feature("测试PecExplorer") #重试次数&#xff0c;粒度为用例&#xff0c;建议用例设计可重复性高 pytest.mark.flaky(reruns3) class TestPecExplorer:#功能模块层级allure.story("登录界面")#测试用例层级allure.title("Test…

C语言程序设计 三四节课堂笔记

C语言程序设计 三四节课堂笔记 C语言程序设计 三四节课堂笔记3.0 程序编写顺序&#xff08;了解&#xff09;3.1 C语言的特点3.2 认识C程序1. C程序的基本框架2. C语言程序的结构特点3. C程序的开发过程 C语言程序设计 第四节课4.1 开发环境dev-C的使用1. 如何将英文界面调整为…

Spring-Java

Spring&#xff1a; 图片出处&#xff1a;b站黑马 ssm学习截图 是一个大家族 &#xff0c;是一套完整的开发生态圈。可以利用这个spring全家桶快速构建企业级开发环境。 Spring Freamwork 是其他框架的基础 Springbot 使用了注解开发 SpringCloud 分布式 云服务 Sprin…

Leetcode—88.合并两个有序数组【简单】

2023每日刷题&#xff08;一&#xff09; Leetcode—88.合并两个有序数组 题解 因为这两个数组已经排好序&#xff0c;我们可以把两个指针分别放在两个数组的末尾&#xff0c;即 nums1 的m − 1 位和 nums2 的 n − 1 位。每次将较大的那个数字复制到 nums1 的后边&#xff0…

计算机操作系统面试题自用

什么是操作系统&#xff1a; 操作系统是管理硬件和软件的一种应用程序。操作系统是运行在计算机上最重要的一种软件 操作系统的主要功能 解释一下操作系统的主要目的是什么 操作系统是一种软件&#xff0c;它的主要目的有三种 1 管理计算机资源&#xff0c;这些资源包括 C…

LangChain结合milvus向量数据库以及GPT3.5结合做知识库问答之一 --->milvus的docker compose安装

https://github.com/milvus-io/milvus/releaseshttps://github.com/milvus-io/milvus/releases 以下步骤均在Linux环境中进行&#xff1a; 将milvus-standalone-docker-compose.yml下载到本地。 1、新建一个目录milvus 2、将milvus-standalone-docker-compose.yml放到milvu…

UWB承启定位基站

UWB承启定位基站 随着我们使用UWB做超高精度的定位项目越来越多&#xff0c;我们发现之前的定位基站完全站在二维或三维的角度去设计还是存在对应的缺陷&#xff0c;这个时候需要在很短的距离内安装多一个基站&#xff0c;对于用户来说&#xff0c;会觉得设备变多了&#xff0…

05在IDEA中配置Maven的基本信息

配置Maven信息 配置Maven家目录 每次创建Project工程后都需要设置Maven家目录位置&#xff0c;否则IDEA将使用内置的Maven核心程序和使用默认的本地仓库位置 一般我们配置了Maven家目录后IDEA就会自动识别到conf/settings.xml配置文件和配置文件指定的本地仓库位置创建新的P…

Java中的栈(Stack)为什么要采用先进后出

Java虚拟机栈 Java虚拟机栈是描述Java方法运行过程的内存模型。 当一个方法即将被运行时&#xff0c;Java虚拟机栈首先会在Java虚拟机栈中为该方法创建一块“栈帧”&#xff0c;栈帧中包含局部变量表(基本数据类型变量、引用类型的变量、returnAddress类型的变量)、操作数栈、…

小谈设计模式(29)—访问者模式

小谈设计模式&#xff08;29&#xff09;—访问者模式 专栏介绍专栏地址专栏介绍 访问者模式角色分析访问者被访问者 优缺点分析优点将数据结构与算法分离增加新的操作很容易增加新的数据结构很困难4 缺点增加新的数据结构比较困难增加新的操作会导致访问者类的数量增加34 总结…

windows10系统-16-制作导航网站WebStack-Hugo

上个厕所功夫把AI导航搞定了 使用Hugo搭建静态站点 如何使用Hugo框架搭建一个快如闪电的静态网站 1 Hugo 参考Hugo中文文档 参考使用Hugo搭建个人网站 Hugo是由Go语言实现的静态网站生成器。简单、易用、高效、易扩展、快速部署。 1.1 安装Hugo 二进制安装&#xff08;推荐…