Thank you for your contribution!I want to change the model to onnx , but I get many errors.could you tell me when will you update the code to support onnx format?
I haven't worked on that, so I can't provide any more infomation. you can share you work or error info and let the community give you some help.
I haven't worked on that, so I can't provide any more infomation. you can share you work or error info and let the community give you some help.
I get this error when I am trying to change the model to onnx:
File "/home/hy/anaconda3/lib/python3.7/site-packages/torch/onnx/symbolic_helper.py", line 82, in _parse_arg "', since it's not constant, please try to make " RuntimeError: Failed to export an ONNX attribute 'onnx::Div', since it's not constant, please try to make things (e.g., kernel size) static if possible
And my code is here:
model = EfficientDetBackbone(compound_coef=compound_coef, num_classes=len(obj_list)) model.load_state_dict(torch.load(f'weights/efficientdet-d{compound_coef}.pth')) model = model.cuda() image_input = torch.rand(1,3,512,512) image_input = image_input.cuda() model.backbone_net.model.set_swish(memory_efficient=False) torch.onnx.export(model, image_input, 'weights/efficientdet_D4.onnx', verbose=False) model.backbone_net.model.set_swish(memory_efficient=True)
it's running well on the other depository
I have resolved it,just set flag onnx_export to true,it will work.
file backbone.py,add onnx_export :
`class EfficientDetBackbone(nn.Module):
def __init__(self, num_classes=80, compound_coef=0, load_weights=False,onnx_export = False, **kwargs):
super(EfficientDetBackbone, self).__init__()
self.compound_coef = compound_coef
self.backbone_compound_coef = [0, 1, 2, 3, 4, 5, 6, 6]
self.fpn_num_filters = [64, 88, 112, 160, 224, 288, 384, 384]
self.fpn_cell_repeats = [3, 4, 5, 6, 7, 7, 8, 8]
self.input_sizes = [512, 640, 768, 896, 1024, 1280, 1280, 1536]
self.box_class_repeats = [3, 3, 3, 4, 4, 4, 5, 5]
self.anchor_scale = [4., 4., 4., 4., 4., 4., 4., 5.]
self.aspect_ratios = kwargs.get('ratios', [(1.0, 1.0), (1.4, 0.7), (0.7, 1.4)])
self.num_scales = len(kwargs.get('scales', [2 ** 0, 2 ** (1.0 / 3.0), 2 ** (2.0 / 3.0)]))
conv_channel_coef = {
# the channels of P3/P4/P5.
0: [40, 112, 320],
1: [40, 112, 320],
2: [48, 120, 352],
3: [48, 136, 384],
4: [56, 160, 448],
5: [64, 176, 512],
6: [72, 200, 576],
7: [72, 200, 576],
}
num_anchors = len(self.aspect_ratios) * self.num_scales
self.bifpn = nn.Sequential(
*[BiFPN(self.fpn_num_filters[self.compound_coef],
conv_channel_coef[compound_coef],
True if _ == 0 else False,
attention=True if compound_coef < 6 else False,onnx_export = onnx_export) # modify by alex , add onnx_export
for _ in range(self.fpn_cell_repeats[compound_coef])])
self.num_classes = num_classes
self.regressor = Regressor(in_channels=self.fpn_num_filters[self.compound_coef], num_anchors=num_anchors,
num_layers=self.box_class_repeats[self.compound_coef],onnx_export = onnx_export) # modify by alex , add onnx_export
self.classifier = Classifier(in_channels=self.fpn_num_filters[self.compound_coef], num_anchors=num_anchors,
num_classes=num_classes,
num_layers=self.box_class_repeats[self.compound_coef],onnx_export = onnx_export) # modify by alex , add onnx_export
self.anchors = Anchors(anchor_scale=self.anchor_scale[compound_coef], **kwargs) # anchor_scale
`
@zhui-ying Would you share all of your modification more precisely?
I tried to reproduce but I am still getting errors.
@zhui-ying @ordogfioka I modify the code as what you did, but I still got the same problem as you post before.
@zhui-ying Same question, could you provide a complete code to convert onnx? Thanks a lot.
change opset_version=11 works though:
torch.onnx.export(model, image_input, 'weights/efficientdet_D4.onnx', verbose=True, opset_version=11)`
But it causes errors when converting to trt using tensorrt 7.0
我根据你改的试了试还是出现了‘Failed to export an ONNX attribute, since it's not constant, please try to make things (e.g., kernel size) static if possible’这个错误,这个改咋整啊,我的pytorch版本是1.2.0
我根据你改的试了试还是出现了‘Failed to export an ONNX attribute, since it's not constant, please try to make things (e.g., kernel size) static if possible’这个错误,这个改咋整啊,我的pytorch版本是1.2.0
我用的1.4
我根据你改的试了试还是出现了‘Failed to export an ONNX attribute, since it's not constant, please try to make things (e.g., kernel size) static if possible’这个错误,这个改咋整啊,我的pytorch版本是1.2.0
我用的1.4
你好,我也用的1.4,但是转onnx时,报错RuntimeError: ONNX export failed: Could't export Python operator SwishImplementation,你有遇到这样的问题吗?
onnx_export = true
opset_version=11
onnx_export = true
opset_version=11
作者在utils_extra.py 里自己定义的两个类(staticsamepadding和pooling)里面的forward函数里包含了python,numpy的代码,并且是根据x动态确定shape的,这些是不能直接导出成onnx的。解决方法是把image_shape 当作参数传入init里。比如:
class Conv2dStaticSamePadding(nn.Module):
"""
created by Zylo117
The real keras/tensorflow conv2d with same padding
"""
def __init__(self, in_channels, out_channels, kernel_size, stride=1, bias=True, groups=1, dilation=1, image_size=None, **kwargs):
super().__init__()
self.conv = nn.Conv2d(in_channels, out_channels, kernel_size, stride=stride,
bias=bias, groups=groups)
self.stride = self.conv.stride
self.kernel_size = self.conv.kernel_size
self.dilation = self.conv.dilation
if isinstance(self.stride, int):
self.stride = [self.stride] * 2
elif len(self.stride) == 1:
self.stride = [self.stride[0]] * 2
if isinstance(self.kernel_size, int):
self.kernel_size = [self.kernel_size] * 2
elif len(self.kernel_size) == 1:
self.kernel_size = [self.kernel_size[0]] * 2
assert image_size is not None
h, w = image_size if type(image_size) == list else [image_size, image_size]
h_step = math.ceil(w / self.stride[1])
v_step = math.ceil(h / self.stride[0])
h_cover_len = self.stride[1] * (h_step - 1) + 1 + (self.kernel_size[1] - 1)
v_cover_len = self.stride[0] * (v_step - 1) + 1 + (self.kernel_size[0] - 1)
extra_h = h_cover_len - w
extra_v = v_cover_len - h
left = extra_h // 2
right = extra_h - left
top = extra_v // 2
bottom = extra_v - top
self.static_padding = nn.ZeroPad2d((left, right, top, bottom))
def forward(self, x):
x = self.static_padding(x)
x = self.conv(x)
return x
同理Anchor class也要修改。
@neverrop 我用torch1.4,添加onnx_export=true, opset_version=true之后其他没改动,倒是转换成功了,很神奇。我目的是onnx2ncnn,但是失败了,里面不支持的op太多了,用onnxsim精简op时报错,很无力。
@vicwer 我也转成功,但是我用onnxruntime加载的时候报错onnxruntime.capi.onnxruntime_pybind11_state.Fail: [ONNXRuntimeError] : 1 : FAIL : Node () Op (Conv) [ShapeInferenceError] Attribute strides has incorrect size,你有遇到过这错误吗?
onnx_export = true
opset_version=11作者在utils_extra.py 里自己定义的两个类(staticsamepadding和pooling)里面的forward函数里包含了python,numpy的代码,并且是根据x动态确定shape的,这些是不能直接导出成onnx的。解决方法是把image_shape 当作参数传入init里。比如:
class Conv2dStaticSamePadding(nn.Module): """ created by Zylo117 The real keras/tensorflow conv2d with same padding """ def __init__(self, in_channels, out_channels, kernel_size, stride=1, bias=True, groups=1, dilation=1, image_size=None, **kwargs): super().__init__() self.conv = nn.Conv2d(in_channels, out_channels, kernel_size, stride=stride, bias=bias, groups=groups) self.stride = self.conv.stride self.kernel_size = self.conv.kernel_size self.dilation = self.conv.dilation if isinstance(self.stride, int): self.stride = [self.stride] * 2 elif len(self.stride) == 1: self.stride = [self.stride[0]] * 2 if isinstance(self.kernel_size, int): self.kernel_size = [self.kernel_size] * 2 elif len(self.kernel_size) == 1: self.kernel_size = [self.kernel_size[0]] * 2 assert image_size is not None h, w = image_size if type(image_size) == list else [image_size, image_size] h_step = math.ceil(w / self.stride[1]) v_step = math.ceil(h / self.stride[0]) h_cover_len = self.stride[1] * (h_step - 1) + 1 + (self.kernel_size[1] - 1) v_cover_len = self.stride[0] * (v_step - 1) + 1 + (self.kernel_size[0] - 1) extra_h = h_cover_len - w extra_v = v_cover_len - h left = extra_h // 2 right = extra_h - left top = extra_v // 2 bottom = extra_v - top self.static_padding = nn.ZeroPad2d((left, right, top, bottom)) def forward(self, x): x = self.static_padding(x) x = self.conv(x) return x同理Anchor class也要修改。
能否提供修改好的类文件? staticsamepadding(已经有了)和pooling, 以及Anchor class
@neverrop 或者能否百度网盘共享下一转换好的模型呢?
@vicwer 我也转成功,但是我用onnxruntime加载的时候报错onnxruntime.capi.onnxruntime_pybind11_state.Fail: [ONNXRuntimeError] : 1 : FAIL : Node () Op (Conv) [ShapeInferenceError] Attribute strides has incorrect size,你有遇到过这错误吗?
modify efficientnet/model.py line 50:
k = self._block_args.kernel_size
s = self._block_args.stride
if isinstance(s, list):
s = s[0]
# print(s)
self._depthwise_conv = Conv2d(
in_channels=oup, out_channels=oup, groups=oup, # groups makes it depthwise
kernel_size=k, stride=s, bias=False)
strides should be int for converting to onnx. in author's code sometimes it's list
@RENCHEN90 thanks man, this solved the issue for me. However, I had to modify line 415 in model.py as well:
if block._depthwise_conv.stride == [2, 2]: change to
if block._depthwise_conv.stride == (2, 2):
since if you pass a single int as stride to Conv2dStaticSamePadding the type of depthwise_conv.stride will be tuple instead of list. At least with pytorch 1.5 and python 3.7 this is the case.
`class Conv2dStaticSamePadding(nn.Module):
"""
created by Zylo117
The real keras/tensorflow conv2d with same padding
"""
def __init__(self, in_channels, out_channels, kernel_size, stride=1, bias=True, groups=1, dilation=1, image_size=None, **kwargs):
super().__init__()
self.conv = nn.Conv2d(in_channels, out_channels, kernel_size, stride=stride,
bias=bias, groups=groups)
self.stride = self.conv.stride
self.kernel_size = self.conv.kernel_size
self.dilation = self.conv.dilation
if isinstance(self.stride, int):
self.stride = [self.stride] * 2
elif len(self.stride) == 1:
self.stride = [self.stride[0]] * 2
if isinstance(self.kernel_size, int):
self.kernel_size = [self.kernel_size] * 2
elif len(self.kernel_size) == 1:
self.kernel_size = [self.kernel_size[0]] * 2
assert image_size is not None
h, w = image_size if type(image_size) == list else [image_size, image_size]
h_step = math.ceil(w / self.stride[1])
v_step = math.ceil(h / self.stride[0])
h_cover_len = self.stride[1] * (h_step - 1) + 1 + (self.kernel_size[1] - 1)
v_cover_len = self.stride[0] * (v_step - 1) + 1 + (self.kernel_size[0] - 1)
extra_h = h_cover_len - w
extra_v = v_cover_len - h
left = extra_h // 2
right = extra_h - left
top = extra_v // 2
bottom = extra_v - top
self.static_padding = nn.ZeroPad2d((left, right, top, bottom))
def forward(self, x):
x = self.static_padding(x)
x = self.conv(x)
return x`
I had a error: assert image_size is not None
How should i set image_size for Conv2dStaticSamePadding(conv_channels[2], num_channels, 1)
@neverrop 我用torch1.4,添加onnx_export=true, opset_version=true之后其他没改动,倒是转换成功了,很神奇。我目的是onnx2ncnn,但是失败了,里面不支持的op太多了,用onnxsim精简op时报错,很无力。
@
@vicwer 我也转成功,但是我用onnxruntime加载的时候报错onnxruntime.capi.onnxruntime_pybind11_state.Fail: [ONNXRuntimeError] : 1 : FAIL : Node () Op (Conv) [ShapeInferenceError] Attribute strides has incorrect size,你有遇到过这错误吗?
modify efficientnet/model.py line 50:
Depthwise convolution phase
k = self._block_args.kernel_size s = self._block_args.stride if isinstance(s, list): s = s[0] # print(s) self._depthwise_conv = Conv2d( in_channels=oup, out_channels=oup, groups=oup, # groups makes it depthwise kernel_size=k, stride=s, bias=False)strides should be int for converting to onnx. in author's code sometimes it's list
@RENCHEN90 your code can send me ([email protected]), the new code can not succes
Most helpful comment
modify efficientnet/model.py line 50:
Depthwise convolution phase
strides should be int for converting to onnx. in author's code sometimes it's list