这个错误说明 MovingAverageMinMaxObserver 内部使用的 aminmax 操作在量化图上不支持。这是版本兼容性问题。
快速解决方案
方案1:使用更简单的 Observer(推荐)
from horizon_plugin_pytorch.quantization import FakeQuantize
from horizon_plugin_pytorch.quantization.observer import MinMaxObserver # 不用 MovingAverage
class SharedCatModule(nn.Module):
def __init__(self):
super().__init__()
self.conv1 = nn.Conv2d(32, 32, 3, padding=1)
self.conv2 = nn.Conv2d(32, 32, 3, padding=1)
self.conv3 = nn.Conv2d(32, 32, 3, padding=1)
self.relu1 = nn.ReLU()
self.relu2 = nn.ReLU()
self.relu3 = nn.ReLU()
# 使用 MinMaxObserver 而不是 MovingAverageMinMaxObserver
self.shared_fake_quant = FakeQuantize(
observer=MinMaxObserver
)
def forward(self, x):
x1 = self.relu1(self.conv1(x))
x2 = self.relu2(self.conv2(x))
x3 = self.relu3(self.conv3(x))
x1_q = self.shared_fake_quant(x1)
x2_q = self.shared_fake_quant(x2)
x3_q = self.shared_fake_quant(x3)
return torch.cat([x1_q, x2_q, x3_q], dim=1)
方案2:不手动创建 FakeQuantize,改用标准 QAT 流程(更稳定)
根据官方文档,不要手动插入 FakeQuantize,而是通过 prepare_qat_fx 的 qconfig_dict 控制:
import torch
import torch.nn as nn
import copy
from horizon_plugin_pytorch.quantization import prepare_qat_fx, convert_fx, set_fake_quantize, FakeQuantState
from horizon_plugin_pytorch.quantization.qconfig import default_qat_8bit_fake_quant_qconfig
class CatModule(nn.Module):
def __init__(self):
super().__init__()
self.conv1 = nn.Conv2d(32, 32, 3, padding=1)
self.conv2 = nn.Conv2d(32, 32, 3, padding=1)
self.conv3 = nn.Conv2d(32, 32, 3, padding=1)
self.relu = nn.ReLU()
def forward(self, x):
x1 = self.relu(self.conv1(x))
x2 = self.relu(self.conv2(x))
x3 = self.relu(self.conv3(x))
return torch.cat([x1, x2, x3], dim=1)
model = CatModule()
# 关键:为所有分支设置同一个 qconfig 对象(注意是调用函数返回对象)
shared_qconfig = default_qat_8bit_fake_quant_qconfig()
model.conv1.qconfig = shared_qconfig
model.conv2.qconfig = shared_qconfig
model.conv3.qconfig = shared_qconfig
model.relu.qconfig = shared_qconfig
# prepare
model = prepare_qat_fx(copy.deepcopy(model))
# calibration 状态
model.eval()
set_fake_quantize(model, FakeQuantState.CALIBRATION)
# 执行 calibration
with torch.no_grad():
for data in calib_loader: # 多批数据
model(data)
# validation 状态
model.eval()
set_fake_quantize(model, FakeQuantState.VALIDATION)
# 转换
model = convert_fx(model)
方案3:如果上述都不可行,接受 rescale 开销,优化模型结构
根据 X5 高效模型设计指导,减少 cat 操作:
# 不推荐:多次 cat
x = torch.cat([a, b], dim=1)
x = torch.cat([x, c], dim=1)
# 推荐:一次性 cat
x = torch.cat([a, b, c], dim=1)
# 或者用 add 替代(如果业务允许)
x = a + b + c # elementwise add 不需要 rescale
诊断信息
请运行以下代码,告诉我输出,方便进一步定位问题:
import horizon_plugin_pytorch
print(f"Plugin version: {horizon_plugin_pytorch.__version__}")
from horizon_plugin_pytorch.quantization import FakeQuantize
import inspect
print(f"FakeQuantize signature: {inspect.signature(FakeQuantize.__init__)}")
# 检查可用的 observer
from horizon_plugin_pytorch.quantization import observer
print(f"Available observers: {[x for x in dir(observer) if 'Observer' in x]}")
建议
根据 Marcelo6151 的回复,QAT 深度优化建议联系 FAE 支持。如果上述方案都无法解决,建议:
- 提供工具链版本和完整代码给 FAE
- 考虑使用 PTQ 方案(YAML 配置更简单)
- 参考社区已有案例:QAT 快速上手(fx mode)
先试试方案1(换 MinMaxObserver),有结果随时同步 ![]()