meituan / YOLOv6

YOLOv6: a single-stage object detection framework dedicated to industrial applications.
GNU General Public License v3.0
5.72k stars 1.03k forks source link

qat_export.py 运行到yolov6-v3/tools/qat/onnx_utils.py", line 202, in onnx_remove_qdqnode报错 if len(node.attribute[0].t.dims) > 0: IndexError: list index (0) out of range,该如何解决? #791

Open lueker opened 1 year ago

lueker commented 1 year ago

Before Asking

Search before asking

Question

使用qat_export.py 运行到yolov6-v3/tools/qat/onnx_utils.py", line 202, in onnx_remove_qdqnode报错 if len(node.attribute[0].t.dims) > 0: IndexError: list index (0) out of range,该如何解决?

报错代码段位于onnx_utils.py的onnx_remove_qdqnode中

def onnx_remove_qdqnode(onnx_model): onnx_replica = copy.deepcopy(onnx_model) graph = onnx_replica.graph nodes = graph.node

# demo for remove node with first input and output
in_rename_map = {}
scale_node_list = []
zero_node_list = []
activation_map = {}
for node_id, node in enumerate(graph.node):
    if node.op_type == "QuantizeLinear":
        # node input
        in_name = node.input[0]
        scale_name = node.input[1]
        zero_name = node.input[2]
        # print(scale_name)
        # node output
        out_name = node.output[0]
        # record input, remove one node, set node's input to its next
        in_rename_map[out_name] = in_name
        scale_node_list.append(scale_name)
        zero_node_list.append(zero_name)
        for i, node in enumerate(graph.node):
            if node.output[0] == scale_name:
                if len(node.attribute[0].t.dims) > 0:
                    print(node.attribute[0].t.dims)
                    graph.node.remove(nodes[i])
        for i, node in enumerate(graph.node):
            if node.output[0] == zero_name:
                graph.node.remove(nodes[i])

Additional

No response

xingyueye commented 1 year ago

@lueker hi, 请补充一下更详细的信息,你是用的v6哪个版本,哪个模型,config等信息

lueker commented 1 year ago

你好,用的yolov6-3.0版本,模型是yolov6s,配置文件是yolov6s_opt_qat.py:

YOLOv6s model

model = dict( type='YOLOv6s', pretrained='./weights/best_ckpt_opt.pt', scales='./weights/yolov6s_v2_scale.pt', depth_multiple=0.33, width_multiple=0.50, backbone=dict( type='EfficientRep', num_repeats=[1, 6, 12, 18, 6], out_channels=[64, 128, 256, 512, 1024], ), neck=dict( type='RepPANNeck', num_repeats=[12, 12, 12, 12], out_channels=[256, 128, 128, 256, 256, 512], ), head=dict( type='EffiDeHead', in_channels=[128, 256, 512], num_layers=3, begin_indices=24, anchors=1, anchors_init=[[10, 13, 19, 19, 33, 23]], out_indices=[17, 20, 23], strides=[8, 16, 32], atss_warmup_epoch=0, iou_type = 'giou', use_dfl = False, reg_max = 0, # if use_dfl is False, please set reg_max to 0 distill_weight={ 'class': 1.0, 'dfl': 1.0, }, ) )

solver = dict( optim='SGD', lr_scheduler='Cosine', lr0=0.00001, lrf=0.001, momentum=0.937, weight_decay=0.00005, warmup_epochs=3, warmup_momentum=0.8, warmup_bias_lr=0.1 )

data_aug = dict( hsv_h=0.015, hsv_s=0.5, hsv_v=0.4, degrees=0.0, translate=0.1, scale=0.5, shear=0.0, flipud=0.0, fliplr=0.0, mosaic=0.0, mixup=0.0, )

ptq = dict( num_bits = 8, calib_batches = 4,

'max', 'histogram'

calib_method = 'histogram',
# 'entropy', 'percentile', 'mse'
histogram_amax_method='entropy',
histogram_amax_percentile=99.99,
calib_output_path='./runs/opt_train_v6s_ptq',
sensitive_layers_skip=False,
sensitive_layers_list=['detect.stems.0.conv',
                       'detect.stems.1.conv',
                       'detect.stems.2.conv',
                       'detect.cls_convs.0.conv',
                       'detect.cls_convs.1.conv',
                       'detect.cls_convs.2.conv',
                       'detect.reg_convs.0.conv',
                       'detect.reg_convs.1.conv',
                       'detect.reg_convs.2.conv',
                       'detect.cls_preds.0',
                       'detect.cls_preds.1',
                       'detect.cls_preds.2',
                       'detect.reg_preds.0',
                       'detect.reg_preds.1',
                       'detect.reg_preds.2',
                       ],

)

qat = dict( calib_pt = './weights/best_ckpt_opt_calib_histogram.pt', sensitive_layers_skip = False, sensitive_layers_list=['detect.stems.0.conv', 'detect.stems.1.conv', 'detect.stems.2.conv', 'detect.cls_convs.0.conv', 'detect.cls_convs.1.conv', 'detect.cls_convs.2.conv', 'detect.reg_convs.0.conv', 'detect.reg_convs.1.conv', 'detect.reg_convs.2.conv', 'detect.cls_preds.0', 'detect.cls_preds.1', 'detect.cls_preds.2', 'detect.reg_preds.0', 'detect.reg_preds.1', 'detect.reg_preds.2', ], )

Choose Rep-block by the training Mode, choices=["repvgg", "hyper-search", "repopt"]

training_mode='repopt'

lueker commented 1 year ago

@xingyueye 我的整个流程是:opt-->ptq-->qat-->export_onnx 在opt阶段加载预训练模型和官网下载的scale模型,训练完之后生成的模型用于ptq,ptq训练完之后生成校准模型,然后将校准模型地址放到配置文件中,再训练10epoch的qat,现在的结果是可以导出含有qdqnode的onnx模型,但是在去除qdq的代码中报错了,麻烦帮我看看,问题出在哪里?感谢

xingyueye commented 1 year ago

@lueker 我这没复现你的问题,另外我看到你报错的地方 line 202, in onnx_remove_qdqnode 在我们的代码里应该是被注释掉的?你再细看一下这块代码是不是最新的

fakerhbj commented 1 year ago

@xingyueye 我的整个流程是:opt-->ptq-->qat-->export_onnx 在opt阶段加载预训练模型和官网下载的scale模型,训练完之后生成的模型用于ptq,ptq训练完之后生成校准模型,然后将校准模型地址放到配置文件中,再训练10epoch的qat,现在的结果是可以导出含有qdqnode的onnx模型,但是在去除qdq的代码中报错了,麻烦帮我看看,问题出在哪里?感谢

请问下 我有个疑问 qat出来的模型 是否合并了bn 然后我看qat_export代码里加载qat权重前是合并了bn的 能加载的进去吗