ONNX のモデル出力と、ONNX を使った推論をやってみた

遠藤です。

先日、ニューラルネットワークをフレームワーク間でやり取りするフォーマットである NNEF と ONNX を紹介いたしました。今回のブログ記事では、それらのうちの ONNX を実際に利用してみて、実際の使用感をレポートしたいと思います。

使用したコードについて

今回の実験で使用したコードは、すべて以下のリポジトリにコミットされています。

fixstars / blog / source / onnx_sample / onnx – Bitbucket

null

上記のコードを実行する際に使用した Docker コンテナのビルドスクリプトは、以下のとおりです。 nvidia-docker  を使って実行してください。

fixstars / blog / source / onnx_sample / docker / Dockerfile – Bitbucket

FROM nvidia/cuda:9.1-cudnn7-devel # install dependent Ubuntu packages RUN apt-get update -y && \ apt-get install -y –no-install-recommends \ build-essential \ ca-certificates \ cmake \ git \ python3-dev \ python3-pip \ \ libgoogle-glog-dev \ libgtest-dev \ libiomp-dev \ libleveldb-dev \ liblmdb-dev \ libopencv-dev \ libopenmpi-dev \ libsnappy-dev \ libprotobuf-dev \ openmpi-bin

各フレームから ONNX への出力 (エクスポート)

今回試したのは以下の4つのフレームワークで、それぞれについてスクリプトファイルを作成しました。

  • Caffe2
  • PyTorch
  • CNTK
  • Chainer

各スクリプトでは、 (1) モデルの読み込み、 (2) ONNX モデルへの変換、 (3) 変換された ONNX モデルの検査を行っていて、最終的にモデルを ONNX ファイルに書き出します。それぞれの実験結果を次にまとめます。

Caffe2 to ONNX

Caffe Model Zoo より CaffeNet を ONNX に変換した例です。変換中に若干ワーニングが出てしまっているものの、正常に変換処理が完了しました。

PyTorch to ONNX

PyTorch に定義されている VGG-16 with Batch Normalization を変換した例です。こちらも若干のワーニングが発生しましたが、正常に変換処理が完了しました。

CNTK to ONNX

実験では、まずは公開されている ResNet-152AlexNet を変換しようとしましたが、下記のエラーが発生しました。原因は未対応のレイヤが使われているということで、ImageNet を分類するモデルは同様の問題を踏んでしまうことが分かりました。

そこでネットワークを変えて CIFAR-10 向けの ResNet-20 を試してみたところ、未対応レイヤの問題を踏まずに実行できることが分かったので試してみました。

ONNX への変換処理自体はうまく通っているように見えますが、変換したモデルを検査すると、ONNX モデルに問題があるというエラーが出てしまいました。この件について CNTK 開発元に問い合わせたところこれは Known Issue だとのことなので、将来の CNTK リリースで改善されると期待されます。

Chainer to ONNX

Chainer に定義されている ResNet-152 を ONNX に変換しました。一切のワーニングやエラーなく、正常に ONNX への変換処理が完了しました。

 

実験結果としては、それぞれのネットワークから ONNX にネットワークを出力することが確認できました。CNTKだけ、既知の問題が発生しているようですので、今後の改善に期待です。

ONNX モデルを用いた各フレームワークでの推論 (インポート)

今回試したのは以下の4フレームワークです。それぞれのフレームワークに対し、 ONNX Model Zoo より VGG-19 のネットワークと、 Caffe2 からエクスポートした CaffeNet の両方を用いて推論を実行させました。

  • Caffe2
  • CNTK
  • MXNet
  • TensorFlow

今回の実験では、以下のかわいらしい(筆者の実家の)猫の写真を、それぞれのネットワークを用いて認識しました。

Caffe2 の実験結果

まずは Model Zoo の VGG-19 を用いた際の認識結果です。見事、61% の確率で tabby cat と認識されました!識別結果2位も猫なので、両方合わせると非常に高い確率で猫であると認識されました。

次に Caffe2 からエクスポートした CaffeNet を用いた際の認識結果です。こちらは Top-1 と Top-2 の順序が変わっているものの、やはり非常に高い確率で猫として認識されています。

どちらのモデルでも、正しく猫を猫として認識してくれました!

CNTK の実験結果

まずは VGG-19 による認識結果です。同じモデルなので、当然のように同じ結果が出ています。各項目の確率の値までほぼ一致していることが分かります。

次は CaffeNet を用いた認識結果ですが、大まかな順位は同じような結果が出ているものの、各項目の確率の値が大きく変化していることが分かりました。

どちらのモデルでも正しく猫と認識されましたが、 CaffeNet の挙動に疑問が残る結果となりました。

MXNet の実験結果

まずは VGG-19 による認識結果です。こちらは、Caffe2/CNTK と同様に、確率の値までほぼ一致しました。

CaffeNet を用いた認識結果も、Caffe2 を用いて推論した時と確率の値がほぼ一致しました。

MXNet によって推論を行ったところ、Caffe2 と計算結果がほぼ一致することが確認できました。

TensorFlow の実験結果

結論から言うと、TensorFlow でも Caffe2/MXNet とほぼ同じ結果が得られました。

VGG-19 による認識結果です。

CaffeNet による認識結果です。

実験結果としては、それぞれのフレームワークで ONNX のインポートを行い、正しくかわいい猫の認識ができました。CNTK における CaffeNet の例を除き、基本的に同一モデル同一出力となることが確認でき、フレームワーク間の差は基本的には見られないことが分かりました。

CNTK で CaffeNet の出力結果が変わった件については、十分な調査はしていないのですが、おそらく LRN (Local Response Normalization) の実装に差があるのではないかと推測しています。

ONNX を用いたモデルの出力と推論が簡単にできることを、実際に確かめることができました。ONNX を用いることで、フレームワークの選択肢がデプロイ先の環境に引きずられることなく、使いたい好きなフレームワークを使うことができるようになります。皆さんもぜひ使ってみてください!

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です