maemaewaterの日記

エンジニア兼ゲーマーの人の日記です。PHP/Python/JavaScript/C#/C++などによるプログラムに関することを主に書いています。

ML.NETでONNXを使用する

ML.NETでONNX形式のモデルを扱えないかどうか調べていたところ以下の動画で解説されていました。

https://www.youtube.com/watch?v=lamnwHvjEV0

この動画で説明されていることでもあるのですが、少しまとめてみようと思います。

プロジェクトの作成

ここでは、プロジェクトはコンソールアプリ(.NET Core)で作成しています。

依存関係の追加

NuGetパッケージの管理から次のパッケージを探します。

実は、はじめML .NETの方(Microsoft.ML)でOnnxの実行環境を探していたのですが、別のパッケージになるようでした。

プログラム

using Microsoft.ML.OnnxRuntime;
float[] input = new float[16 * 16]; // モデルの入力に合わせる

var session = new InferenceSession("model.onnx");

Tensor<float> tensor = new DenseTensor<float>(input, session.InputMetadata.First().Value.Dimensions);
var namedValues = new List<NamedOnnxValue> { NamedOnnxValue.CreateFromTensor("0", tensor) };

var results = session.Run(namedValues);
var resultValues = results.First().AsTensor<float>().ToArray();
int resultValue = Array.IndexOf(resultValues, resultValues.Max());

Console.WriteLine("value is {0}", resultValue);
ONNX形式のファイルの読み込み

一番初めのInferenceSessionの初期化の箇所で指定しています。各機械学習のライブラリで出力されたものを使用します。

var session = new InferenceSession("model.onnx");
モデルに入力する値と名前と形式を指定

この例では、入力はinputに入れています。1次元のfloat型の配列で作成して、ここからTensorを作っています。

Tensor<float> tensor = new DenseTensor<float>(input, session.InputMetadata.First().Value.Dimensions);

ここで作成したテンソルをモデルのどの入力に指定するかどうかをNamedOnnxValueを使用して指定しています。ここで、入力名"0"が指定されていますが、これはONNXモデルを作成したときに指定されているものになりますので、ONNX形式の出力部分などを確認します(指定していないと"0"のようになっていました。)

モデルを実行と結果の取得
var results = session.Run(namedValues);
var resultValues = results.First().AsTensor<float>().ToArray();
int resultValue = Array.IndexOf(resultValues, resultValues.Max());

session.Runを実行すると入力した値から結果を計算してくれます。そのあとは、出力された結果で一番大きい値を取り出し最終的な結果としています。

参考にさせていただいた資料:

www.youtube.com