はじめに
sklearnで作成したRansomForestモデルをONNXファイルに変換し、Windows Machine Learningで利用する際に気を付けることを書いていきます。
サンプルに、HoloLens2取得したHandGestureを分類するコードをGithubに挙げました。 github.com
環境(python)
- python 3.6 (winmltoolsがpython3.7以降をサポートしていないため)
- winmltools 1.5.1
- skl2onnx 1.7.1 (whlファイルからインポートしてください)
- その他 (pandas, sklearnなど)
環境(uwp)
- Microsoft.AI.MachineLearning v1.5.2
1. sklearnで学習 -> ONNXファイルに変換する時
1-1. zipmapの削除
Windows Machine LearningのUWPアプリでONNXモデルを利用する際、どうやらモデルに型不明な経路(?)があると、ロードに失敗します。
これを防ぐために、convert_sklearn関数でinitial_typesやfinal_typesを指定します。 ここでfinal_types指定の際、zipmap出力の型(map(string,tensor(float))の指定方法がわからず、方法を模索していたところ、zipmap変換をしない方法にたどり着きました。
options = {id(pipeline): {'zipmap': False}}
上記のoptionsをconvert_sklearnの引数に指定します。
from skl2onnx import convert_sklearn from winmltools.convert.common.data_types import FloatTensorType, StringTensorType, Int64TensorType options = {id(pipeline): {'zipmap': False}} rf_onnx = convert_sklearn(pipeline, target_opset=7, options=options, name = 'RandomForestClassifier', initial_types=[('input', FloatTensorType([1, 120]))], )
出力されたONNXモデルは以下のようになります。
1-2. convert_sklearnはskl2onnxのものを使う
ONNXのバージョンに気をつける必要はありますが、とりあえずwinmltoolsのコンバータを使用せず、最新のskl2onnxを使うことができました。
from skl2onnx import convert_sklearn
2. Windows Machine Learning(UWP)で利用する時
2-1. 入力・出力をONNXと一致させる
当然といえば当然ですが、入力・出力の型を合わせる必要があります。skleanrからのコンバート時にinitial_typesを指定するなども、その一環として行っています。
... # データ入力時 handGestureInput input = new handGestureInput(); input.Input120 = TensorFloat.CreateFromArray(new long[] { 1 , 120 }, feature); ... public sealed class handGestureInput { public TensorFloat Input120; }
2-2. TensorStringの出力の仕方
TensorString型の取り出しには、一癖あるなぁと感じます。 取り出し方としては、TensorString.GetAsVectorView().ToList()で、string型のListに変換し、その要素を取り出します。
//Evaluate the model var handGestureOutput = await handGestureModelGen.EvaluateAsync(input); IList<string> stringList = handGestureOutput.label.GetAsVectorView().ToList(); Debug.WriteLine($"判定された動作ラベル:{stringList[0]}");
終わりに
sklearnで作成したRansomForestモデルをONNXファイルに変換し、Windows Machine Learningで利用する際に気を付けることを書きました。 (HoloLens2上で実行できたらいいな....)