既存のコードをUnity Sentis 1.6からUnity Sentis 2.1へ移行する

概要

Unity公式のディープラーニング推論フレームワークのSentis 2.xがリリースされました。Sentis 2.0にて正式リリースとなります。
この記事を書いている途中でいくつかのバグが修正されたSentis 2.1がリリースされており、現時点ではこちらがUnity Sentisの最新バージョンとなります。 Sentis 1.6からSentis 2.xへはAPIの破壊的な変更が含まれており、既存のコードをいくつか修正する必要があります。 この記事ではSentis 2.xの主な既存のコードの書き換え事例を紹介していきます。

docs.unity3d.com

ChangeLog

Unity Sentis 2.0および2.1のWhatNewとChangeLogは以下のページで公開されいます。
Sentis 2.1はバグが修正が主なのでSentis 2.0のChangeLogを読むと変更が把握できると思います。

既存のコードの書き換え

Unity Sentis 1.6からUnity Sentis 2.0へのアップグレードガイドは以下で公開されています。 ここではUnity Sentis 1.6の既存のコードをUnity Sentis 2.1に書き換えるポイントをいくつか紹介します。 おそらく、Unity Sentisを利用している誰もが書き換えることになる部分をピックアップしました。

docs.unity3d.com

IBackend APIの廃止、Functional APIへの移行

Unity Sentisでは1.4からIBackendクラスに定義されたメソッドでテンソルの演算を行っていました。 これは後からテンソルに対して1つ1つ処理をしていくものでした。 Unity Sentisでは1.4からFunctionalクラスも追加されました。 これは先にモデルを編集してテンソルに対する処理を組み込んだ新しいモデルを生成するものです。

これまではIBackend APIとFunctional APIはどちらも使える状態でしたが、Unity Sentis 2.0からIBackend APIの廃止されFunctional APIへ移行が必須になりました。 この変更がSentis 1.6からSentis 2.xへの移行で開発者にとって一番大きな書き換えになると思います。

Functional APIは既存のモデルを編集して後処理を加えるような使い方が多いかと思います。 以下の例では既存のモデルの出力に対してSoftmaxレイヤーを加えて新たなモデルを生成しています。 このモデルの利用するとはじめからSoftmaxが適用されたテンソルを得ることができます。

docs.unity3d.com

// Unity Sentis 1.6
var worker = WorkerFactory.CreateWorker(backend_type, model);
var backend = WorkerFactory.CreateBackend(backend_type);

/* input tensor and execute */

var output_tensor = worker.PeekOutput(model.outputs[0].name);
var confidences_tensor = TensorFloat.AllocNoData(output_tensor.shape);
backend.Softmax(output_tensor, confidences_tensor, -1);
// Unity Sentis 2.0 or later
var graph = new FunctionalGraph();
var input_tensors = graph.AddInputs(model);
var output_tensor = Functional.Forward(model, input_tensors)[0];
var confidences_tensor = Functional.Softmax(output_tensor);
var model_with_softmax = graph.Compile(confidences_tensor);

var worker = new Worker(model_with_softmax, backend_type);

/* input tensor and schedule */

var confidences_tensor = worker.PeekOutput(model_with_softmax.outputs[0].name);

その他

Unity SentisではこれまでIWorkerクラスを利用して推論を実行していました。 Unity Sentis 2.0からはインスタンス可能なWorkerクラスに変更されました。 また、推論の実行もExecute()からSchedule()になりました。

// Unity Sentis 1.6
var worker = WorkerFactory.CreateWorker(backend_type, model);
worker.Execute(input_tensor);
// Unity Sentis 2.0 or later
var worker = new Worker(model, backend_type);
worker.Schedule(input_tensor);

Unity Sentisではこれまでfloat型のデータを持つテンソルはTensorFloatクラス、int型のデータを持つテンソルはTensorIntクラスで扱ってきました。 Unity Sentis 2.0からはジェネリッククラスのTensorの導入され、Tensor<float>Tensor<int>のように扱うようになりました。

// Unity Sentis 1.6
var tensor_float = tensor as TensorFloat;
var tensor_int = tensor as TensorInt;
// Unity Sentis 2.0 or later
var tensor_float = tensor as Tensor<float>;
var tensor_int = tensor as Tensor<int>;

また、テンソルからArrayやSpan、NativeArrayを取得する関数が少し異なります。

// Unity Sentis 1.6
var span = tensor_float.ToReadOnlySpan();
var array = tensor_float.ToReadOnlyArray();
var native_array = tensor_float.ToReadOnlyNativeArray();
// Unity Sentis 2.0 or later
{
    /* Shallow Copy */
    var span = tensor_float.AsReadOnlySpan();
    var native_array = tensor_float.AsReadOnlyNativeArray();
}
{
    /* Block and Deep Copy */
    var array = tensor_float.DownloadToArray();
    var native_array = tensor_float.DownloadToNativeArray();
}

まとめ

この記事ではUnity Sentis 2.xに既存のコードを書き換える事例を紹介しました。
Unity Sentisをベースにした画像認識パッケージであるHoloLab DNN Packagesは最新のUnity Sentis 2.1に対応済みです。 Unity Sentisの破壊的な変更に伴っていくつかのAPIが変更せざるを得ませんでしたが、ユーザーコードの変更を最小限に抑えて概ねこれまでと同様の使い勝手にすることができました。 ぜひ、Unityアプリにディープラーニングによる画像認識を使った機能を組み込んで遊んでみてください。

blog.hololab.co.jp