sai10の雑記

センサー類, Python, Unity(C#), 機械学習とかについてのメモ

sklearnで作成したRansomForestモデルをONNXに変換してwinML(UWP)で利用する

はじめに

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)

1. sklearnで学習 -> ONNXファイルに変換する時

1-1. zipmapの削除

Windows Machine LearningのUWPアプリでONNXモデルを利用する際、どうやらモデルに型不明な経路(?)があると、ロードに失敗します。 f:id:stopengin0012:20210207141018p:plain

これを防ぐために、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モデルは以下のようになります。 f:id:stopengin0012:20210207141445p:plain

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上で実行できたらいいな....)