Microsoftさんの「ONNX Runtime Web（ORT Web）」のサンプル【Quick Start - Web (using script tag)】を動かしてみたり公式デモの情報を見て試してみたりする

この記事は、以下のニュースに書かれていた「ONNX Runtime Web（ORT Web）」の一部を試してみたり、関連情報を見てみたという話です。

[●マイクロソフト、WebAssemblyとWebGLで推論エンジンを実装した「ONNX Runtime Web」（ORT Web）をオープンソースで公開 － Publickey](https://www.publickey1.jp/blog/21/webassemblywebglonnx_runtime_webort_web.html)

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">ブログ書きました： マイクロソフト、WebAssemblyとWebGLで推論エンジンを実装した「ONNX Runtime Web」（ORT Web）をオープンソースで公開 <a href="https://t.co/6y4XXjo1S1">https://t.co/6y4XXjo1S1</a></p>&mdash; Publickey (@publickey) <a href="https://twitter.com/publickey/status/1434539403364294661?ref_src=twsrc%5Etfw">September 5, 2021</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

## 情報をたどってサンプルを動かすまで
### 情報をたどる
上記の記事の最初に、以下のリポジトリへのリンクがはられていました。

●onnxruntime/js/web at master · microsoft/onnxruntime
　https://github.com/microsoft/onnxruntime/tree/master/js/web#readme
![ONNX Runtime Web](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/dec7ca94-67dd-2db3-b429-5618759e3ac3.jpeg)

そして、中を見ていくと以下の「Usage」の説明がありました。
![onnxruntime_js_web_at_master_·_microsoft_onnxruntime.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/2c9fef9b-40e2-0e70-fdbb-d6b6130e3394.jpeg)

そして、上記の[ONNX Runtime JavaScript examples](https://github.com/microsoft/onnxruntime-inference-examples/tree/main/js)の先を見てみます。

そして、ONNX Runtime JavaScript examples の中にも「Usage」の項目があります。
![onnxruntime-inference-examples_js_at_main_·_microsoft_onnxruntime-inference-examples.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/345f0e17-479a-4341-6328-a6f9536c8c4e.jpeg)

その中の「Quick Start」は以下の 3種類があります。

1. [Nodejs Binding](https://github.com/microsoft/onnxruntime-inference-examples/tree/main/js/quick-start_onnxruntime-node)
2. [Web (using script tag)](https://github.com/microsoft/onnxruntime-inference-examples/tree/main/js/quick-start_onnxruntime-web-script-tag)
3. [Web (using bundler)](https://github.com/microsoft/onnxruntime-inference-examples/tree/main/js/quick-start_onnxruntime-web-bundler)

個人的には、TensorFlow.js等を HTML＋JavaScript でという感じのことを好んでやっていたりするので、[Web (using script tag)](https://github.com/microsoft/onnxruntime-inference-examples/tree/main/js/quick-start_onnxruntime-web-script-tag) を深掘りしてみます。

### Web (using script tag) のサンプルを試す
[「Web (using script tag) のクイックスタート」](https://github.com/microsoft/onnxruntime-inference-examples/tree/main/js/quick-start_onnxruntime-web-script-tag)は、ページ内はシンプルでした。
![Web (using script tag) のクイックスタート](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/73feeabd-fe10-7dbf-bae7-91f44687969d.jpeg)

ちなみに、リポジトリ内のファイルも以下の 3つだけ。
![Web (using script tag) 関連のファイル](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/e3e5b6db-6dba-bc07-b78e-1ae52bde28ad.jpeg)

HTMLファイルの中身を見ていってみます。

```html
<!DOCTYPE html>
<html>
    <header>
        <title>ONNX Runtime JavaScript examples: Quick Start - Web (using script tag)</title>
    </header>
    <body>
        <!-- import ONNXRuntime Web from CDN -->
        <script src="https://cdn.jsdelivr.net/npm/onnxruntime-web/dist/ort.min.js"></script>
        <script>
            // use an async context to call onnxruntime functions.
            async function main() {
                try {
                    // create a new session and load the specific model.
                    //
                    // the model in this example contains a single MatMul node
                    // it has 2 inputs: 'a'(float32, 3x4) and 'b'(float32, 4x3)
                    // it has 1 output: 'c'(float32, 3x3)
                    const session = await ort.InferenceSession.create('./model.onnx');

                    // prepare inputs. a tensor need its corresponding TypedArray as data
                    const dataA = Float32Array.from([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]);
                    const dataB = Float32Array.from([10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120]);
                    const tensorA = new ort.Tensor('float32', dataA, [3, 4]);
                    const tensorB = new ort.Tensor('float32', dataB, [4, 3]);

                    // prepare feeds. use model input names as keys.
                    const feeds = { a: tensorA, b: tensorB };

                    // feed inputs and run
                    const results = await session.run(feeds);

                    // read from results
                    const dataC = results.c.data;
                    document.write(`data of result tensor 'c': ${dataC}`);

                } catch (e) {
                    document.write(`failed to inference ONNX model: ${e}.`);
                }
            }

            main();
        </script>
    </body>
</html>
```

内容を見た感じだと、先ほどのリポジトリ内にあった「[model.onnx](https://github.com/microsoft/onnxruntime-inference-examples/blob/main/js/quick-start_onnxruntime-web-script-tag/model.onnx)」を読み込んで使えば、この処理を実行できそうです。

ファイル読み込みを伴うので、HTMLファイルを直接ブラウザにドラッグ＆ドロップして実行というわけにはいかないため、ローカルでサーバを実行します。
[「Web (using script tag) のクイックスタート」](https://github.com/microsoft/onnxruntime-inference-examples/tree/main/js/quick-start_onnxruntime-web-script-tag)では、 `npx light-server -s . -p 8080` というコマンドで [light-server](https://www.npmjs.com/package/light-server) を使ってサーバを動かしていましたが、自分の場合は [Python のワンライナーWebサーバ](https://qiita.com/sudahiroshi/items/e74d61d939f18779970d#pythonsimplehttpserver%E7%B7%A8)を使いました。

そして、ブラウザからローカルサーバのアドレスでアクセスし、処理を実行してみます。
そうすると、ブラウザ上に以下の結果が表示されました。
![処理結果.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/88860a1c-247c-1318-af1f-af9e155f4cc0.jpeg)

このプログラムの内容は、3行4列の行列と4行3列の行列の2つの行列の積を求めるもののようなので、結果が正しいか確認してみます。

適当にググってでてきた以下のサイトで、今回の行列の積の計算を行ってみます。
　●行列の積 - 高精度計算サイト
　　https://keisan.casio.jp/exec/system/1308269580

計算結果は以下のとおりで、先ほどブラウザ上に表示されたものと一致していそうです。
![行列の積_-_高精度計算サイト.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/051da9e2-e7f4-a9c4-0495-e7c87108f8d7.jpeg)

## もう少し関連情報を見てみる
とりあえずサンプルは簡単に動かせたのですが、冒頭の記事にあった以下の部分の話には触れられずでした。
![記事の抜粋](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/9235abfa-1008-bc1c-b55d-1c02a0765d03.jpeg)

どうやら、以下の記事にもう少し情報がありそうなので、少し見てみます。

●ONNX Runtime Web—running your machine learning model in browser - Microsoft Open Source Blog
　https://cloudblogs.microsoft.com/opensource/2021/09/02/onnx-runtime-web-running-your-machine-learning-model-in-browser/

### モデルの準備
「Get Started」の中に書かれた内容を見ると、ONNX形式のモデルを準備すれば、もう少しいろいろなことができそうです。
![Get_Startedの冒頭の部分.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/186c2cf5-1e44-54c8-bd62-87eb0937db06.jpeg)

TensorFlow・PyTorch等でモデルを作って変換するか、[ONNX Model Zoo](https://github.com/onnx/models) からモデルを持ってくるか、という感じのことが書いてあります。

### ブラウザ上で推論を実行
さらに「Get Started」の中を読み進めていくと、ブラウザ上で推論を実行する話が書かれていそうでした。
![Get_Startedの続き](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/feb6ce54-3728-6545-c4a1-96b159773c0c.jpeg)

さらに読み進めると、以下に「[ONNX Runtime Web](https://microsoft.github.io/onnxruntime-web-demo/#/)」というリンクがありました。
![Get_Startedの続き（別のサンプルの話）](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/62a82bbb-7865-3b03-edcd-bea533ff29b1.jpeg)

リンク先を見ると、画像分類や他のいくつかのサンプルがありそうでした。
![デモ.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/167233cc-3f18-6a2c-b311-57c92ae12969.jpeg)

とりあえず、一番上の画像分類が試せそうな「[MobileNet, trained on ImageNet
](https://microsoft.github.io/onnxruntime-web-demo/#/mobilenet)」を開いてみます。
バックエンドを「GPU-WebGL」か「CPU-WebAssembly」のどちらかにして、画像分類を実行できそうな感じです。
![画像分類のデモ画面.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/d075c1c5-f3a4-e833-32c8-c0164e053d6c.jpeg)

画像は、既に用意されたものを選ぶか、自分でアップロードすることができるようでした。
とりあえず、既に用意されている画像を選んで動作確認をしてみました。
試しに「coffee」を選ぶと、以下のような推論の結果が表示されるのが確認できました。
![コーヒーの画像に対する結果.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/17c4c656-a3fc-1b4f-1ddc-19d6d59b9407.jpeg)

上記の左上から開けるメニューを開いて、その中のリンクの 1つを見るとさらに情報が書かれていそうでしたが、今回の記事はここまでにしておこうと思います。
　●microsoft/onnxruntime-web-demo: demos to show the capabilities of ONNX Runtime Web
　　https://github.com/Microsoft/onnxruntime-web-demo

## まとめ
今回、情報を見かけて気になった「ONNX Runtime Web（ORT Web）」に関する内容を試してみました。

画像分類等のデモの実装の話はまだ見られてないので、別途、調べて記事にできればと思います。