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

概要

Unity公式のディープラーニング推論フレームワークのSentis 1.4がリリースされました。
Sentis 1.3からSentis 1.4へはAPIの破壊的な変更が含まれており、既存のコードをいくつか修正する必要があります。 まだ公式のサンプルが更新されていなかったりと時期尚早な感じはありますが、この記事ではSentis 1.4の新機能をピックアップして紹介、主な既存のコードの書き換え事例を紹介していきます。

Unity Sentis 1.4

ChangeLog

Unity Sentis 1.4のWhatNewとChangeLogは以下のページで公開されいます。
ここでは注目したい新機能をピックアップします。

docs.unity3d.com docs.unity3d.com

・量子化のサポート

  • Quantization API for quantizing model weights to Float16 or Uint8.
  • TensorByte and TensorShort tensor types for quantization.

Unity Sentisでモデルの量子化がサポートされました。 半精度浮動小数点数(float16)と符号なし整数(uint8)がサポートされているみたいです。 これに伴い、新しくTensorShortTensorByteのテンソル型が定義されました。

Unity Sentisでは強制的に単精度浮動小数点数(float32)で学習済みモデルが読み込みます。 これをあとからModelQuantizer.QuantizeWeights()で半精度浮動小数点数(float16)や符号なし整数(uint8)に量子化するようです。

docs.unity3d.com

・NMSの改善

  • Improved NonMaxSuppression inference drastically and added GPUCompute backend.

Unity Sentisではオブジェクト検出などで利用されるNMSオペレーターをサポートしていますが、これまではCPUで実行されていました。 フォーラムでもこれがオブジェクト検出のパフォーマンスに悪影響していることが議論されていました。 Unity Sentis 1.4ではNMSオペレーターがGPUで実行できるようになり、パフォーマンスが改善したようです。

  • Non-working NonMaxSuppression GPUCompute optimizations.

なんらかの問題があったのか、Unity Sentis 1.4.0-pre.3で削除されたようです。

・FlatBufferベースのシリアル化

  • Reworked model serialization to use flatbuffers.

これまでUnity Sentis 1.3以前ではバイナリでシリアル化をしていましたが、Unity Sentis 1.4以降はFlatBuffersでシリアル化されるようになります。
これによりシリアル化されたモデルのUnity Sentis 1.4以降のバージョン間の互換性、速度、セキュリティの向上が期待できるそうです。
この変更により、Unity Sentis 1.3以前でシリアル化または暗号化されたモデル(*.senttis)は互換性が無くなるので、再シリアル化が必要になるので注意しましょう。

既存のコードの書き換え

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

docs.unity3d.com

・テンソルからデータを取り出す

Unity Sentis 1.3ではテンソルからデータを取り出す前にtensor.MakeReadable()を呼び出していました。 Unity Sentis 1.4ではtensor.CompleteOperationsAndDownload()に変更されました。
また、tensor.CompleteOperationsAndDownloadAsync()という非同期メソッドも新たに用意されています。

// Unity Sentis 1.3
tensor.MakeReadable();
var span = tensor.ToReadOnlySpan();
// Unity Sentis 1.4
tensor.CompleteOperationsAndDownload();
var span = tensor.ToReadOnlySpan();

・テンソルの演算

Unity Sentis 1.3ではテンソルの演算にOpsクラスに定義されたメソッドを呼び出していました。 Unity Sentis 1.4ではOpsクラスの代わりにIBackendクラスを利用するようになります。
Opsクラスは出力先のテンソルは内部で自動的に作成されて戻り値で返されていました。 IBackendクラスは出力先のテンソルを自分で確保しなければなりませんが、型や形状が明確になりました。
テンソルの確保は各テンソル型にAllocNoData()AllocZeros()のメソッドが用意されています。テンソルの型と形状に注意して確保しましょう。

// Unity Sentis 1.3
var ops = WorkerFactory.CreateOps(backend_type, null);
var confidences = ops.Softmax(tensor, -1);
// Unity Sentis 1.4
var backend = WorkerFactory.CreateBackend(backend_type);
var confidences = TensorFloat.AllocNoData(tensor.shape);
backend.Softmax(tensor, confidences, -1);

・テンソルのコピー

Unity Sentis 1.3ではテンソルのディープコピーにtensor.DeepCopy()を利用していました。 Unity Sentis 1.4では以下の2つの方法があります。どちらを使ってもよさそうですが、移行ガイドでは後者のbackend.MemCopy()を使う方法で紹介されています。

// Unity Sentis 1.3
var copied_tensor = tensor.DeepCopy();
// Unity Sentis 1.4
// 1. constructor + clone
var copied_tensor = new TensorFloat(tensor.shape, tensor.dataOnBackend.Clone());

// 2. backend memcopy
var backend = WorkerFactory.CreateBackend(backend_type);
var copied_tensor = TensorFloat.AllocNoData(tensor.shape);
backend.MemCopy(tensor, copied_tensor);

まとめ

この記事ではUnity Sentis 1.4の新機能と既存のコードの書き換え事例を紹介しました。
Unity Sentisをベースにした画像認識パッケージであるHoloLab DNN Packagesは最新のUnity Sentis 1.4に対応済みです。 ぜひ、Unityアプリにディープラーニングによる画像認識を使った機能を組み込んで遊んでみてください。

blog.hololab.co.jp