ONNXがサポートしている最適化 fuse_pad_into_conv を調べてみました。
どうもconvにfuseする系は最適化ができないようで、fuse_pad_into_convは上手く動きませんでした。
最適化をしている場所
https://github.com/onnx/onnx/blob/master/onnx/optimizer/passes/fuse_pad_into_conv.h
// Before:
// P = Pad(X) - opset 10 and below (or) Pad(X, Pads, [Constant_value]) - opset 11 and
// above Z = Conv(P, Y)
// After:
// Z = Conv(X, Y) with "pads" attribute set
//
// the pass handles the case when Pad is zero-padding the input
// (i.e. mode=constant and Constant_value=0)
コメントによると、PadとConvが並んでいるとPadを削除してくれるようです。
最適化前のグラフ
最適化をするとこのようなエラーがでます。
File "C:\home\app\anaconda3\lib\site-packages\onnx\optimizer.py", line 55, in optimize
optimized_model_str = C.optimize(model_str, passes)
IndexError: invalid unordered_map<K, T> key
全ソースです。
import numpy as np
import onnx
from onnx import helper, numpy_helper
from onnx import TensorProto
from onnx import optimizer
X = helper.make_tensor_value_info('X', TensorProto.FLOAT, [5, 5])
Y = helper.make_tensor_value_info('Y', TensorProto.FLOAT, [5, 5])
pads_list = numpy_helper.from_array(np.array([1,1,1,1], dtype=np.int64))
pads_list.name = 'pads_list'
W = numpy_helper.from_array(np.zeros((1, 3, 3), dtype=np.float))
W.name = 'W'
pad = helper.make_node(
'Pad',
['X', 'pads_list'],
['pad_out'],
mode='constant',
)
conv = helper.make_node(
'Conv',
kernel_shape=[3, 3],
inputs = ['pad_out', 'W'],
outputs = ['Y'],
)
graph_def = helper.make_graph(
[pad, conv],
'test-model',
[X],
[Y],
initializer = [pads_list, W]
)
model_def = helper.make_model(
graph_def,
producer_name='onnx_example'
)
onnx.save(model_def, 'onnx/fuse_pad_into_conv.onnx')
onnx.checker.check_model(model_def)
# 最適化パスを指定
passes = ['fuse_pad_into_conv']
optimized_model = optimizer.optimize(model_def, passes)
onnx.save(optimized_model, 'onnx/fuse_pad_into_conv.onnx')