OpenPPL / ppq

PPL Quantization Tool (PPQ) is a powerful offline neural network quantization tool.
Apache License 2.0
1.57k stars 236 forks source link

RuntimeError: Op Execution Error: BatchNormalization_27(Type: Conv, Num of Input: 3, Num of Output: 1) #496

Closed zyt1024 closed 1 year ago

zyt1024 commented 1 year ago

我要量化的模型是个多输入的,量化代码如下:

calibration_dataset = input

dataloader = DataLoader(
    dataset=calibration_dataset,
    batch_size=32, shuffle=True)

print('网络正量化中,根据你的量化配置,这将需要一段时间:')
# quantized = quantize(
#     working_directory=WORKING_DIRECTORY, setting=SETTING,
#     model_type=MODEL_TYPE, executing_device=EXECUTING_DEVICE,
#     input_shape=None,
#     inputs=input, 
#     target_platform=TARGET_PLATFORM,
#     dataloader=dataloader, calib_steps=256)
quantized = quantize_onnx_model(
    onnx_import_file=os.path.join(WORKING_DIRECTORY,'model.onnx'), setting=SETTING,
    device=EXECUTING_DEVICE,
    input_shape=None,
    inputs=input, 
    platform=TARGET_PLATFORM,
    calib_dataloader=dataloader, 
    calib_steps=256)

# -------------------------------------------------------------------
# 如果你需要执行量化后的神经网络并得到结果,则需要创建一个 executor
# 这个 executor 的行为和 torch.Module 是类似的,你可以利用这个东西来获取执行结果
# 请注意,必须在 export 之前执行此操作。
# -------------------------------------------------------------------
executor = TorchExecutor(graph=quantized)
# output = executor.forward(input)

# -------------------------------------------------------------------
# 导出 PPQ 执行网络的所有中间结果,该功能是为了和硬件对比结果
# 中间结果可能十分庞大,因此 PPQ 将使用线性同余发射器从执行结果中采样
# 为了正确对比中间结果,硬件执行结果也必须使用同样的随机数种子采样
# 查阅 ppq.util.fetch 中的相关代码以进一步了解此内容
# 查阅 ppq.api.fsys 中的 dump_internal_results 函数以确定采样逻辑
# -------------------------------------------------------------------
if DUMP_RESULT:
    dump_internal_results(
        graph=quantized, dataloader=dataloader,
        dump_dir=WORKING_DIRECTORY, executing_device=EXECUTING_DEVICE)

# -------------------------------------------------------------------
# PPQ 计算量化误差时,使用信噪比的倒数作为指标,即噪声能量 / 信号能量
# 量化误差 0.1 表示在整体信号中,量化噪声的能量约为 10%
# 你应当注意,在 graphwise_error_analyse 分析中,我们衡量的是累计误差
# 网络的最后一层往往都具有较大的累计误差,这些误差是其前面的所有层所共同造成的
# 你需要使用 layerwise_error_analyse 逐层分析误差的来源
# -------------------------------------------------------------------
print('正计算网络量化误差(SNR),最后一层的误差应小于 0.1 以保证量化精度:')
reports = graphwise_error_analyse(
    graph=quantized, running_device=EXECUTING_DEVICE, steps=256,
    dataloader=dataloader, collate_fn=lambda x: x.to(EXECUTING_DEVICE))
for op, snr in reports.items():
    if snr > 0.1: ppq_warning(f'层 {op} 的累计量化误差显著,请考虑进行优化')

if REQUIRE_ANALYSE:
    print('正计算逐层量化误差(SNR),每一层的独立量化误差应小于 0.1 以保证量化精度:')
    layerwise_error_analyse(graph=quantized, running_device=EXECUTING_DEVICE, steps=256,
                            interested_outputs=None,
                            dataloader=dataloader, collate_fn=lambda x: x.to(EXECUTING_DEVICE))

print('网络量化结束,正在生成目标文件:')
export(working_directory=WORKING_DIRECTORY,
       quantized=quantized, platform=TargetPlatform.ONNXRUNTIME)

这是我的报错日志:

Layerwise Equalization: 100%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 3/3 [00:00<00:00, 315.31it/s]
Finished.
Traceback (most recent call last):
  File "/home//.local/lib/python3.7/site-packages/ppq/executor/torch.py", line 536, in __forward
    outputs = operation_forward_func(operation, inputs, self._executing_context)
  File "/home/atzyt/.local/lib/python3.7/site-packages/ppq/executor/op/torch/default.py", line 308, in Conv_forward
    dilation=dilation, stride=stride)
RuntimeError: Given groups=7, weight of size [7, 1, 1, 1], expected input[1, 1, 7, 128] to have 7 channels, but got 1 channels instead

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "ppq_onnx_2.py", line 122, in <module>
    calib_steps=256)
  File "/home//.local/lib/python3.7/site-packages/ppq/core/defs.py", line 54, in _wrapper
    return func(*args, **kwargs)
  File "/home//.local/lib/python3.7/site-packages/ppq/api/interface.py", line 269, in quantize_onnx_model
    collate_fn=collate_fn
  File "/home//.local/lib/python3.7/site-packages/ppq/core/defs.py", line 54, in _wrapper
    return func(*args, **kwargs)
  File "/home//.local/lib/python3.7/site-packages/ppq/quantization/quantizer/base.py", line 52, in quantize
    executor.tracing_operation_meta(inputs=inputs)
  File "/home/atyt/.local/lib/python3.7/site-packages/torch/autograd/grad_mode.py", line 27, in decorate_context
    return func(*args, **kwargs)
  File "/home//.local/lib/python3.7/site-packages/ppq/core/defs.py", line 54, in _wrapper
    return func(*args, **kwargs)
  File "/home//.local/lib/python3.7/site-packages/ppq/executor/torch.py", line 602, in tracing_operation_meta
    hooks=hooks)
  File "/home//.local/lib/python3.7/site-packages/ppq/executor/torch.py", line 563, in __forward
    raise RuntimeError(f'Op Execution Error: {str(operation)}') from _
RuntimeError: Op Execution Error: BatchNormalization_27(Type: Conv, Num of Input: 3, Num of Output: 1)
zyt1024 commented 1 year ago

补充一点日志

网络正量化中,根据你的量化配置,这将需要一段时间:
[Warning] Isolated BatchNormalization(BatchNormalization_27) was detected, PPQ will replace it to 1*1 Convolution(2D).
ZhangZhiPku commented 1 year ago

哈哈哈看起来你可以关掉PPQ替换Batchnorm的那个过程,这个BatchNormalization_27似乎不能被替换。 您可以在ppq.core.common.py里面找到关闭替换batchnorm的开关。