RuntimeError: Failed to export an ONNX attribute, since it's not constant, please try to make things (e.g., kernel size) static if possible
Traceback (most recent call last):
File "/home/spple/pycharm-2018.3.2/helpers/pydev/pydevd.py", line 1741, in
main()
File "/home/spple/pycharm-2018.3.2/helpers/pydev/pydevd.py", line 1735, in main
globals = debugger.run(setup['file'], None, None, is_module)
File "/home/spple/pycharm-2018.3.2/helpers/pydev/pydevd.py", line 1135, in run
pydev_imports.execfile(file, globals, locals) # execute the script
File "/home/spple/pycharm-2018.3.2/helpers/pydev/_pydev_imps/_pydev_execfile.py", line 18, in execfile
exec(compile(contents+"\n", file, 'exec'), glob, loc)
File "/home/spple/paddle/vis-project/pytorch_inference/pytorch1.1.0_inference.py", line 113, in
main()
File "/home/spple/paddle/vis-project/pytorch_inference/pytorch1.1.0_inference.py", line 77, in main
hl_graph = hl.build_graph(model, temp_input)
File "/home/spple/anaconda3/envs/pytorch1_1_0--py3_6--cuda9_0/lib/python3.6/site-packages/hiddenlayer/graph.py", line 141, in build_graph
import_graph(g, model, args)
File "/home/spple/anaconda3/envs/pytorch1_1_0--py3_6--cuda9_0/lib/python3.6/site-packages/hiddenlayer/pytorch_builder.py", line 71, in import_graph
torch.onnx._optimize_trace(trace, torch.onnx.OperatorExportTypes.ONNX)
File "/home/spple/anaconda3/envs/pytorch1_1_0--py3_6--cuda9_0/lib/python3.6/site-packages/torch/onnx/__init__.py", line 40, in _optimize_trace
trace.set_graph(utils._optimize_graph(trace.graph(), operator_export_type))
File "/home/spple/anaconda3/envs/pytorch1_1_0--py3_6--cuda9_0/lib/python3.6/site-packages/torch/onnx/utils.py", line 188, in _optimize_graph
graph = torch._C._jit_pass_onnx(graph, operator_export_type)
File "/home/spple/anaconda3/envs/pytorch1_1_0--py3_6--cuda9_0/lib/python3.6/site-packages/torch/onnx/__init__.py", line 50, in _run_symbolic_function
return utils._run_symbolic_function(*args, **kwargs)
File "/home/spple/anaconda3/envs/pytorch1_1_0--py3_6--cuda9_0/lib/python3.6/site-packages/torch/onnx/utils.py", line 589, in _run_symbolic_function
return fn(g, *inputs, **attrs)
File "/home/spple/anaconda3/envs/pytorch1_1_0--py3_6--cuda9_0/lib/python3.6/site-packages/torch/onnx/symbolic.py", line 130, in wrapper
args = [_parse_arg(arg, arg_desc) for arg, arg_desc in zip(args, arg_descriptors)]
File "/home/spple/anaconda3/envs/pytorch1_1_0--py3_6--cuda9_0/lib/python3.6/site-packages/torch/onnx/symbolic.py", line 130, in
args = [_parse_arg(arg, arg_desc) for arg, arg_desc in zip(args, arg_descriptors)]
File "/home/spple/anaconda3/envs/pytorch1_1_0--py3_6--cuda9_0/lib/python3.6/site-packages/torch/onnx/symbolic.py", line 90, in _parse_arg
raise RuntimeError("Failed to export an ONNX attribute, "
RuntimeError: Failed to export an ONNX attribute, since it's not constant, please try to make things (e.g., kernel size) static if possible
转换onnx出问题,有一次是因为
def calc_tf_padding(x,
kernel_size,
stride=1,
dilation=1):
"""
Calculate TF-same like padding size.
Parameters:
----------
x : tensor
Input tensor.
kernel_size : int
Convolution window size.
stride : int, default 1
Strides of the convolution.
dilation : int, default 1
Dilation value for convolution layer.
Returns
-------
tuple of 4 int
The size of the padding.
"""
height, width = x.size()[2:]
oh = math.ceil(height / stride)
ow = math.ceil(width / stride)
pad_h = max((oh - 1) * stride + (kernel_size - 1) * dilation + 1 - height, 0)
pad_w = max((ow - 1) * stride + (kernel_size - 1) * dilation + 1 - width, 0)
return pad_h // 2, pad_h - pad_h // 2, pad_w // 2, pad_w - pad_w // 2
改为:
return (int(pad_h // 2), int(pad_h - pad_h // 2), int(pad_w // 2), int(pad_w - pad_w // 2))
还有一次:
raise RuntimeError("Failed to export an ONNX attribute, "
RuntimeError: Failed to export an ONNX attribute, since it's not constant, please try to make things (e.g., kernel size) static if possible
怀疑是使用了
return F.interpolate(input=x, scale_factor=self.scale_factor, mode='bilinear', align_corners=True)
所以打开
/home/spple/anaconda3/envs/pytorch1_1_0--py3_6--cuda9_0/lib/python3.6/site-packages/torch/onnx/symbolic.py
find:
upsample_nearest2d
改为:
'''
@parse_args('v', 'is', 'i')
def upsample_bilinear2d(g, input, output_size, align_corners):
if align_corners:
return _unimplemented("upsample_bilinear2d", "align_corners == True")
height_scale = float(output_size[-2]) / input.type().sizes()[-2]
width_scale = float(output_size[-1]) / input.type().sizes()[-1]
scales = g.op("Constant", value_t=torch.tensor([1., 1., height_scale,
width_scale]))
return g.op("Upsample", input, scales,
mode_s="linear")
'''
def upsample_bilinear2d(g, input, output_size, align_corners):
output_size = _maybe_get_const(output_size, 'is')
if _is_value(output_size):
offset = 2
input_length = len(input.type().sizes())
offsets = g.op("Constant", value_t=torch.tensor([1. for i in range(offset)]))
dividend = g.op("Cast", output_size, to_i=cast_pytorch_to_onnx["Float"])
divisor = g.op(
"Slice",
g.op("Shape", input),
axes_i=[0],
ends_i=[input_length],
starts_i=[offset]
)
divisor = g.op("Cast", divisor, to_i=cast_pytorch_to_onnx["Float"])
scale_dims = g.op("Div", dividend, divisor)
scales = g.op("Concat", offsets, scale_dims, axis_i=0)
else:
height_scale = float(output_size[-2]) / input.type().sizes()[-2]
width_scale = float(output_size[-1]) / input.type().sizes()[-1]
scales = g.op("Constant", value_t=torch.tensor([1., 1., height_scale, width_scale]))
return g.op("Upsample", input, scales, mode_s="linear")
然后就可以了
不过推荐换到最新版,最新版已经解决了这个问题。pytorch1.2.0
self.classifier = nn.Sequential(
nn.Dropout(0.2),
nn.Linear(self.last_channel, n_class),
)
pytorch中的命名方式:
如果是train
classifier.1.weight
classifier.1.bias
如果是eval()
classifier.0.weight
classifier.0.bias
如果我想把这个结构改成:
classifier.weight
classifier.bias
结构应该是训练完以后,把网络修改为
self.classifier = nn.Linear(self.last_channel, n_class)
模型载入方式也改变了:
self.model = FairNasC(n_class=class_num)
self.model.eval()
state_dict = torch.load(ckpt_path)
model_dict = self.model.state_dict()
state_dict = {k: v for k, v in state_dict.items() if k.find("num_batches_tracked")<0 }
state_dict = {k: v for k, v in state_dict.items() if k.find("classifier.1.")<0 }
state_dict = {k: v for k, v in state_dict.items() if k in model_dict}
for k, v in state_dict.items():
print(k)
self.model.load_state_dict(state_dict)
其中:
state_dict = {k: v for k, v in state_dict.items() if k.find("num_batches_tracked")<0 }
是因为pytorch1.1.0训练出来的模型,BN层结构与pytorch0.3.0不一样,所以进行删除多余结构
if use_cuda: inputs, targets = inputs.cuda(), targets.cuda(async=True) inputs, targets = torch.autograd.Variable(inputs), torch.autograd.Variable(targets)
https://blog.csdn.net/amds123/article/details/70144995
https://blog.csdn.net/qq_18644873/article/details/88216904
https://blog.csdn.net/qq_18644873/article/details/88216904
https://blog.csdn.net/jacke121/article/details/80597759