すごく簡単なONNXモデルでonnx.checker.check_modelを使ったところ、このエラーがでてはまりました。
エラーが出るソース
import onnx
from onnx import TensorProto
from onnx import helper
X = helper.make_tensor_value_info('X', TensorProto.FLOAT, [28, 28])
input_shape = helper.make_tensor_value_info('input_shape', TensorProto.INT64, [1])
reshape_out = helper.make_tensor_value_info('reshape_out', TensorProto.FLOAT, [784])
flat_op = helper.make_node(
'Reshape',
inputs=['X', 'input_shape'],
outputs=['reshape_out'],
name="reshape_node"
)
graph_def = helper.make_graph(
[flat_op],
'my-mlp',
[X],
[reshape_out]
)
model_def = helper.make_model(
graph_def,
producer_name='natsutan'
)
onnx.save(model_def, 'onnx/my_mlp.onnx')
onnx.checker.check_model(model_def)
print('The model is checked!')
MNISTの入力だけをPython APIでONNX化がやりたかったのですが、でるエラーがこれ。
File "C:\home\app\anaconda3\lib\site-packages\onnx\checker.py", line 86, in check_model
C.check_model(model.SerializeToString())
onnx.onnx_cpp2py_export.checker.ValidationError: Nodes in a graph must be topologically sorted, however input 'input_shape' of node:
input: "X" input: "input_shape" output: "reshape_out" name: "reshape_node" op_type: "Reshape"
is not output of any previous nodes.
OP一個しかないのになんで順番が関係あるのかわからず、エラーがでている箇所のソースを追いました。
この部分でfalseを返すと上のエラーが表示されます。
https://github.com/onnx/onnx/blob/64b4b6865d55fd3b94dea1f15a9368d4be0444c3/onnx/checker.h#L104
bool this_or_ancestor_graph_has(const std::string& name) const {
return this_graph_has(name) ||
(parent_context_ && parent_context_->this_or_ancestor_graph_has(name));
}
ちゃんと追ったわけではないので想像ですが、nameしか見ていないので変数の前方参照を失敗しているようです。
エラーがでるソースとにらめっこして、input_shapeが値を指定していない状態ではグラフの入力につなげないと駄目かもと思い修正しました。
graph_def = helper.make_graph(
[flat_op],
'my-mlp',
[X, input_shape], # 初期値を与えていないTensorはグラフの入力につなぐ
[reshape_out]
)
この修正で、onnx.checker.check_modelはエラーを出さなくなりました。このエラーが出たときは、ネットワークのトポロジーと合わせて、前方参照が全部できているかどうか確認すると問題解決が早そうです。
次は、グラフの入力になっているreshapeのパラメータをinitializerで固定値にしたい。