3分で分かる！ONNXフォーマットとWindows Machine Learning！

最近何かと耳にするようになってきた「ONNX」。
Webの記事とかで見るんだけど「DeepLearningとかで使われてるアレでしょ？」「そもそもどう読むか分からない」という人のためにONNXがどういったものなのか、Windows Machine Learningとどう関係してくるのかを3分で分かるくらいの分量でまとめようと思います。

さくっと結論から見たい方はこちらから
[つまりWindows10上でWindowsMLを使って機械学習するにはどうすればいいの？](#つまりwindows10上でwindowsmlを使って機械学習するにはどうすればいいの)


## 想定読者
DeepLearning界隈の動向を追っているような方々は**対象にしていません。**
もともとこの記事を書こうと思ったきっかけが、Hololens界隈で[Windows Machine Learning](https://docs.microsoft.com/en-us/windows/uwp/machine-learning/overview)が話題になっているけどONNXに関する情報が少ないなーと思ったことです。
なので、日頃からDeepLearningに触れているわけではなく、特にHololensとかUWP界隈にいる人達向けの解説となります。

## ONNXとは？
![image.png](https://qiita-image-store.s3.amazonaws.com/0/91774/a4afe5bf-0c1f-63ae-4ef2-30ac9ec64dc1.png)
[公式ページ](https://onnx.ai/)

ONNXは**Open Neural Network eXchange**の略で、DeepLearningモデルを様々なフレームワーク間で交換するためのフォーマットです。
これを使えばあるDeepLearningフレームワークで学習させたモデルを他のフレームワークでも利用することができます。DeepLearningフレームワーク戦国時代には嬉しい仕組みです。
**ちなみにONNXは「オニキス」と発音します。**

## ONNXフォーマットの対応状況
![image.png](https://qiita-image-store.s3.amazonaws.com/0/91774/34e1a418-d0c9-a4b3-5e18-99cc8f304a7d.png)
[公式のGithub](https://github.com/onnx/tutorials)

こちらが2018年4月の段階での各種DeepLearningフレームワークのONNXフォーマットの対応状況です。
ONNXフォーマットを扱う上で注意しなくてはならない点が2つあります。

### 注意1:各フレームワーク間でのExport/Import
図の中にいろいろ見知らぬフレームワークの名前がありますが、大切なのは**全てのフレームワークで相互変換が可能なわけではない**ということです。
図を見ても分かる通り、各フレームワークでExport/Importの対応状況に差があり、例えばChainerで学習させたモデルをPyTorchに持ち込むということはできません。

### 注意2:各フレームワークのパーツレベルでの対応
またもうひとつ注意しなくてはならないのが、**各フレームワークが一部のDeepLearnigモデルのパーツ(関数)のExport/Importに対応していない**ということです。
少しややこしい話になりますが、ONNXの仕様上は存在しているがフレームワーク側でまだ対応できていないといったパーツが存在します。
特定のフレームワークのモデルをONNXフォーマットでExport/Importする場合、モデルのパーツ全てがそのフレームワークで対応している必要があります。
PyTrochを例に出すと、[こちらのページにあるパーツ](http://pytorch.org/docs/master/onnx.html)がPyTorchが対応しているパーツですが、この中にLSTMといったパーツは存在しておらずこれを含むモデルはONNXフォーマットでExportすることができません。

そのため、フレームワークがONNXフォーマットに対応しているからといって全てのモデルをExport/Importできるわけではないということに注意してください。

(余談: [ONNX公式の仕様](https://github.com/onnx/onnx/blob/master/docs/Operators.md)にはLSTMといったパーツも含まれているため、いずれ対応されると思います。)

## Windows Machine Learningとは
![image.png](https://qiita-image-store.s3.amazonaws.com/0/91774/5723c2ad-8156-7bc4-ce8f-c8dd57e8e6ee.png)
[公式](https://docs.microsoft.com/en-us/windows/uwp/machine-learning/)

Windows Machine Learning(Windows ML)はWindows10デバイス上で機械学習を行うためのAPIを提供するプラットフォームです。
これを使えば、Windows10上での機械学習のコードをC#を使ってさくっと書くことができるようになります。
重要なのはONNXフォーマットのモデルを読み込んで推論(予測)を行う機能が用意されていることです。

## winmltoolsを使えばCoreMLなどのモデルも取り込める
[winmltools](https://docs.microsoft.com/en-us/windows/uwp/machine-learning/conversion-samples)はMicrosoftが公式で出しているWindows ML向けのtoolで、これを使えばCoreMLやScikit-learnといった機械学習フレームワークのモデルをWindows MLが読み込めるONNXフォーマットに変換して保存することができます。
(CoreMLはDeepLearningフレームワークの1種です)

```py
# coremltoolsはCoreMLモデルを扱うtool
from coremltools.models.utils import load_spec
from winmltools import convert_coreml
from winmltools.utils import save_model, save_text

# CoreMLモデルのロード
model_coreml = load_spec("MobileNet.mlmodel")
# CoreMLモデルをONNXモデルに変換
model_onnx = convert_coreml(model_coreml, name="mobilenet")

# モデルをONNXフォーマットのバイナリモデルとテキストで保存する
save_model(model_onnx, "Mobilenet.onnx")
save_text(model_onnx, "Mobilenet.txt")
```

## つまりWindows10上でWindowsMLを使って機械学習するにはどうすればいいの？
結局のところ、機械学習モデルをONNXフォーマットで用意できれば後はWindows MLで読み込んでAPIを使って推論を行えます。
そのため機械学習モデルを

1. Windows ML上で学習
2. 各種DeepLearningライブラリでモデルを学習させONNXフォーマットでExport
3. 公開されている機械学習モデルをwinmltoolsで変換したり、各種フレームワークでExport

といった手段で用意することが考えられます。

2や3で各フレームワークで学習済みのモデルをExportする際には、[こちら](#注意2各フレームワークのパーツレベルでの対応)で書いたように各フレームワークがそのモデルの全てのパーツに対してExportに対応しているかどうかが鍵になります。どんなモデルでもONNXフォーマットに変換できるわけではありません。
3. に関してはModel Zooといって学習済みモデルを公開する場所がいくつかあり、そこから良さそうなモデルを探してきてwinmltoolsで変換するのが良いでしょう。

- [ONNX Models](https://github.com/onnx/models): ONNXの学習済みモデルを配布している
- [Core ML Store](https://coreml.store/): CoreMLの学習済みモデルを配布している


## おまけ
3のパターンとして、CoreMLの学習済みモデルが公開されているMobileNetを使ってリアルタイムに画像認識を行うアプリを作ったので参考までにどうぞ
[https://github.com/ymym3412/WindowsML-CoreML-MobileNet-demo](https://github.com/ymym3412/WindowsML-CoreML-MobileNet-demo)

やり方やコードはこちらの記事のものをほぼ流用させて頂きました。ありがとうございました。
[Custom Vision Serviceから出力したモデルを使ってWindowsML上で物体認識をする（その１　AIモデルの作成と出力）](https://qiita.com/linyixian/items/1ba75afe7bdf93bd53f8)

## 参考文献
[ONNX公式](https://onnx.ai/)
[Github: ONNX/ONNX](https://github.com/onnx/onnx)
[Windows Machine Learning](https://docs.microsoft.com/en-us/windows/uwp/machine-learning/)
[Github: Microsoft/Windows-Machine-Learning](https://github.com/Microsoft/Windows-Machine-Learning)
[Custom Vision Serviceから出力したモデルを使ってWindowsML上で物体認識をする（その１　AIモデルの作成と出力）](https://qiita.com/linyixian/items/1ba75afe7bdf93bd53f8)
[HoloLensでWindowsMLを試してみる(サンプル実行編)](http://akihiro-document.azurewebsites.net/post/hololens_windowsmachinelearningsample/)