こんにちは、アンゴです
みなさんは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で学習済みモデルを使う手順に関しては
下記のリンク先がわかりやすかったです!

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内で実行してみると、、、

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”から名前が変わってしまっています

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のモデルが動きました!

動きました!
(上のキャプチャは、画像から数字を判別するプログラムでして
0と出力されるのが正常な動作です)
まとめ
Kerasで作った学習済みモデルは
出力ノードの名前が書き換わっており
それに対応したプログラムを書く必要があるみたいです
こちらの記事は2019/1/13公開です
お読みになる時期によっては
すでに情報が古い、あるいはKeras側で修正されている可能性もあります
Fairy Tale Technologyでも引き続き調査していきます!
コメント