ONNX はチューリング完全だよ、という話

シクシク素数列 Advent Calendar 2018 向けです。

ONNX はニューラルネットのモデルをエクスポートして、別の実装でインポートできたりする、相互運用のためのフォーマットです。複雑なモデルをサポートできるようにと、 Loop とか If とかがあるので、チューリング完全です。ただまあ実際にえぐい使われ方してる例は見たことがなかったので、やってみました。

https://github.com/shinh/test/blob/master/onnx_gen_4949_prime.py

が、4か9を含む素数を出力する ONNX モデルを出力するプログラムで、

$ wget https://raw.githubusercontent.com/shinh/test/master/onnx_gen_4949_prime.py
$ wget https://raw.githubusercontent.com/shinh/test/master/onnx_script.py
$ python3 onnx_gen_4949_prime.py
$ ls gen_4949_prime
model.onnx  test_data_set_0

とかで ONNX ファイルが出力できます。実行は、 ONNX のループとかをサポートしている処理系があまりないと思いますので、 ONNX runtime とかを使ってください

$ python3
>>> import numpy as np
>>> import onnxruntime
>>> sess = onnxruntime.InferenceSession('gen_4949_prime/model.onnx')
>>> input_name = sess.get_inputs()[0].name
>>> output_name = sess.get_outputs()[0].name
>>> sess.run([output_name], {input_name: np.array(104)})[0]
array([  19,   29,   41,   43,   47,   59,   79,   89,   97,  109,  139,
        149,  179,  191,  193,  197,  199,  229,  239,  241,  269,  293,
        347,  349,  359,  379,  389,  397,  401,  409,  419,  421,  431,
        433,  439,  443,  449,  457,  461,  463,  467,  479,  487,  491,
        499,  509,  541,  547,  569,  593,  599,  619,  641,  643,  647,
        659,  691,  709,  719,  739,  743,  769,  797,  809,  829,  839,
        859,  907,  911,  919,  929,  937,  941,  947,  953,  967,  971,
        977,  983,  991,  997, 1009, 1019, 1039, 1049, 1069, 1091, 1093,
       1097, 1109, 1129, 1193, 1229, 1249, 1259, 1279, 1289, 1291, 1297,
       1319, 1399, 1409, 1423, 1427], dtype=int64)

入力で指定しているのが 104 なのは、 8 の倍数じゃないと ONNX runtime がクラッシュするぽかったからです。他にもいくつか ONNX runtime のバグらしきものを見つけた気がするので、適当に報告しておきます。

チューリング完全ということで、 ELVM のバックエンドを作っておきたいのですが、 TensorFlow モデルバックエンドが遅くて実用にならないという問題があって、 ONNX も似たような感じなので、どうしたものかと思っていたのでした。ただ、なんか最近手っ取り早く高速化する方法を思いついた気がしたので、今度やってみようかと思います。

なにかあれば下記メールアドレスへ。
shinichiro.hamaji _at_ gmail.com
shinichiro.h