Keras(+TensorFlow)で学習したモデルをUnityで使う時の問題点と解決法

keras-unity-title 機械学習

こんにちは、アンゴです
みなさんはKeras(+TensorFlow)使ってますか?

2019年初頭の現在、アンゴはKerasとTensorFlowでモデルを作成し
Unityで使うという流れが
機械学習を用いたアプリ作成において
お手軽でいいのではないかと思っております🤔

この手順を試す中で、
Kerasで書き出したモデルがUnityで上手く動かないという問題が発生しましたので
経緯と解決した方法をまとめました!

スポンサーリンク

Keras、TensorFlowとはなにか?

Unityをメインにお使いの方の中には
KerasやTensorFlow という見慣れない単語がでてきて
「なに?」となっている方も多いかと思いますので
簡単に詳細させていただきますね

まずはTensorFlowから
TensorFlowは、Googleが作った機械学習のためのライブラリです
いま流行のAIやディープラーニングをプログラミングするための道具と思っていただければ
だいたいあっていると思います!

つづいてKerasは
TensorFlowを使いやすくするための、同じくプログラミングするための道具です

このTensorFlowとKerasを、Pythonという開発言語であつかって
機械学習を行い、その結果をUnityで利用しようというのが今回の主題です

例えば、写真に写っているものがなにか?を判別する機械学習をおこない
その結果をUnityに持っていき
写真に写っているものが何かを判別するアプリを作ったりすることもできるのですよ!

スポンサーリンク

Kerasで作った学習済みmodelをUnityへ

今回行いたい手順は
1) Kerasで学習を行ってモデルを作成します
2)学習した モデルをUnityで読み込みます

1)はpythonで
2)はUnityでの作業となります

参考:
Unityで学習済みモデルを使う手順に関しては
下記のリンク先がわかりやすかったです!

環境構築不要?今すぐ始めるTensorFlow on Unity - Qiita
# TL;DR * UnityがTensorFlowSharpを.unitypackageで配布しているから今すぐ使える! * TensorFlowはGCPのCloud Shellにインストール済みだから今すぐ使える! * Pytho...
スポンサーリンク

Kerasでのモデルの定義

Pythonの中で、Kerasのモデルを定義する時に
出力ノードの名前を設定します

下記のサンプルですと
predictions = Dense(12, activation=’softmax’, name=’y’)(x) ##出力ノード名
この部分で’y‘という名前に設定しています

inputs = Input(shape=(image_size, image_size, 3), name='x') ##入力ノード名

x = Conv2D(32, (3, 3),activation=('relu'))(inputs)
x = Dense(32, activation='relu')(x)
x = Flatten()(x)

predictions = Dense(12, activation='softmax', name='y')(x) ##出力ノード名
model = Model(input=inputs, output=predictions)

model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
スポンサーリンク

Unityでの設定

Kerasで書き出したモデルをUnityにもっていき
推論を行わせるためにコードを書きました

下記はUnity内でのコードです

runner.AddInput(graph[“x”][0], Tpix).Fetch(graph[“y”][0]);
この部分で、入力と出力ノードの名前を設定しています

      TFGraph graph = new TFGraph();
      graph.Import(model.bytes);
      TFSession sess = new TFSession(graph);


      var runner = sess.GetRunner();
      runner.AddInput(graph["x"][0], Tpix).Fetch(graph["y"][0]);
      var output = runner.Run();
スポンサーリンク

Kerasで吐き出したモデルをUnityで使おうとすると、、、

いざ、Unity内で実行してみると、、、

errorlog

NullReferenceException: Object reference not set to an instance of an object
MLTest.Start () (at Assets/MLTest.cs:72)

このようなエラーがでてしまいました😥

いろいろ調べた結果
どうやらKerasから書き出したモデルに問題があるようでした

スポンサーリンク

エラーの原因はKerasの吐き出しの問題?

Kerasから書き出された学習モデルは
出力ノードの名前が変わってしまうようです

学習モデルを.txt形式で吐き出し直して
エディタで確認してみます

ありました!
Softmaxという単語で検索したところ
下のキャプチャのように

name:”y/Softmax”

と、設定した”y”から名前が変わってしまっています

Keras-output-name
スポンサーリンク

Unityで出力ノードの名前を直します

名前がわかればこっちのものです!
Unity内にて
出力ノードの名前を”y/Softmax”に書き直します

     //モデルを読み込み 
   TFGraph graph = new TFGraph();
   graph.Import(model.bytes);
   TFSession sess = new TFSession(graph);

     //読み込んだモデルに入出力を足す
   var runner = sess.GetRunner();
   runner.AddInput(graph["x"][0], Tpix).Fetch(graph["y/Softmax"][0]); // <-この部分
   var output = runner.Run();

そして、実行すると

スポンサーリンク

UnityでKerasのモデルが動きました!

OK

動きました!
(上のキャプチャは、画像から数字を判別するプログラムでして
0と出力されるのが正常な動作です)

スポンサーリンク

まとめ

Kerasで作った学習済みモデルは
出力ノードの名前が書き換わっており
それに対応したプログラムを書く必要があるみたいです

こちらの記事は2019/1/13公開です
お読みになる時期によっては
すでに情報が古い、あるいはKeras側で修正されている可能性もあります

Fairy Tale Technologyでも引き続き調査していきます!

コメント

タイトルとURLをコピーしました