おもちゃラボ

Unityで遊びを作ってます

【Unity】Tensor Flowを使ってディープラーニングをする

Unityで簡単にTensorFlowを使ってディープラーニング(Deep Learning)したい場合は、ml-agents(Machine Learning Agents)というフレームワークを使うのが便利です。今回の記事では、ml-agentsの考え方と概要、ml-agentsを使った機械学習の方法を説明します。

記事の内容は次のようになります。

今回使用するml-agentsのサンプルは、次のようなパドルとボールを使ったものです。未学習の状態ではパドルは簡単にボールを落としてしまいます。ディープラーニングで学習後は、できるだけボールを落とさないように、自動的にパドルの傾きを調節できるようになります。

f:id:nn_hokuson:20171226205722j:plain:w600

Unityのml-agentsの概要

ml-agentsを使うとUnityでディープラーニングの学習が簡単にできます。ディープラーニングとはなにか?を手を動かしながら学習したい方は次の書籍が役に立ちました。

Unityのml-agentsは「Academy」「Brain」「Agents」の3つのコンポーネントで構成されています。それぞれのコンポーネントの役割は次のようになります。

コンポーネント名 役割
Academy TensorFlowとやり取りするためのコンポーネント
Brain Agentsを束ねるコンポーネント
Agents Reward(報酬)を計算するためのコンポーネント


色々なコンポーネントがあってややこしいですが、最初のうちはAcademyとBrainは殆ど書き換えることはないので、少しの間忘れてもOKです(たぶん・・・)

重要なのはAgentsスクリプトで、Agentsのスクリプトに「どのような場合にRewardを増やし、どのような場合に場合にRewardを減らすか」を定義します。例えば上の3DBallのデモの場合、ボールを落としたらReward=-1、ボールが保持されていればReward=0.1と定義しています。

f:id:nn_hokuson:20171226203851p:plain:w500

Agentsで報酬系の設定ができたらて、機械学習によってモデルに動きを学習させます。Unityでml-agentsを使って学習をするには次のような流れになります。

  1. アプリをExternalモードで書き出す
  2. そのバイナリを使ってディープラーニングで学習をさせる
  3. 学習結果をファイル出力
  4. アプリをInternalモードにして学習結果を読み込み実行

Unityでディープラーニングをする流れは図にすると次のような流れになります。

f:id:nn_hokuson:20171226205559j:plain

Anacondaで環境設定

TensorFlowを使うにはPython3の環境が必要になります。MacにはPythonがインストールされていますが、標準ではバージョンが2系のため、追加で3系のPythonをインストールする必要があります。

Homebrewなどを使ってインストールすることもできますが、何かとハマリポイントが多いため、ここではAnaconda(蛇つながり!?)と呼ばれるパッケージを使ってインストールすることにします。

以下のサイトからインストーラをダウンロードしてインストールを進めて下さい。

www.anaconda.com

インストール終了後、ターミナルを起動して次のコマンドを入力してみて下さい。

python --version

次のように、「Python 3.6.3 :: Anaconda, Inc.」など、3系の表示になっていればOKです。

f:id:nn_hokuson:20171223132846p:plain:w600

ml-agentsをインポートする

続けてUnityでディープラーニングをするための本体パッケージ「ml-agents」をダウンロードします。

github.com

上のサイトから「Clone or Download」→「ZIP Download」を選択して、ml-agentsパッケージをダウンロードしてください。

f:id:nn_hokuson:20171223133153j:plain:w570

ダウンロードできたら、ml-agents-masterフォルダの「unity-environment/Assets/ML-Agents/Examples/3DBall/Scene.unity 」をダブルクリックして起動して下さい。3DBallのプロジェクトが表示されます。

f:id:nn_hokuson:20171223133341j:plain:w570

TensorFlowが使えるようにセットアップする

UnityでTensorFlowが使えるようにするためのプラグインをプロジェクトにインポートします。次のサイトからプラグインをダウンロードしてインポートして下さい。

https://s3.amazonaws.com/unity-agents/TFSharpPlugin.unitypackage

インポートしたTensorFlowのプラグインが使えるようにするための設定を行います。メニューバーから「Edit→Project Settings→Player」を選択し、インスペクタの「Other Settings」→「Scripting Runtime Version」を「Experimental(.NET 4.6 Equivalent)」に設定します。

また、「Scripting Define Symbols」の欄に「ENABLE_TENSORFLOW」と入力して下さい。

f:id:nn_hokuson:20171223133855p:plain:w400

ここまでで、UnityでTensorFlowを使うための準備は完了です。次はTensorFlowを使ってディープラーニング学習をしていきます。

トレーニング用のバイナリを書き出す

続いて、機械学習によってパドルがボールを落とさないように学習させます。ml-agentsを使って学習をするには、一旦アプリをExternalモードで書き出し、そのバイナリを使って学習を進めます。

f:id:nn_hokuson:20171226210544j:plain

ヒエラルキービューからBall3DAcademy/Ball3DBrainを選択し、インスペクタでBrain Typeを「External」に変更します。これにより、TensorFlowを使った入力を受け付けるようになります。

f:id:nn_hokuson:20171223135110p:plain:w400

続いてメニューバーから「File」→「Build Settings」を選択し、Scenes in Buildに3DBallのシーンが選択されていることを確認してから、Buildボタンを押してアプリを書き出します。書き出すアプリ名は任意のもので構いませんが、ここでは「3dball」にしました。アプリを書き出す場所はダウンロードしたml-agents-masterの中のpythonフォルダを選択して下さい。

f:id:nn_hokuson:20171223135303j:plain:w450

機械学習でトレーニングする

アプリをExternalモードで書き出せたところで、いよいよメインのTensorFlowを使った学習の段階に進みます。

f:id:nn_hokuson:20171226210702j:plain

まずはml-agents-master内のpythonフォルダにターミナルで移動し、次のコマンドを入力して下さい。これにより必要なライブラリがインストールされます。

pip install .

次にpythonを使って学習を行うため、次のコマンドを入力して下さい。

jupyter notebook

次のような画面がブラウザに表示されるので、PPO.ipynbをクリックして開いて下さい。

f:id:nn_hokuson:20171223135837j:plain:w450

ここからは、実際にTensorFlowを使ってディープラーニングを実行しましょう。ブラウザでテキストボックスに表示されているPythonのプログラムを選択し、画面上部の「Run」ボタンを押していきます。

f:id:nn_hokuson:20171223141321p:plain:w400

Step1. ライブラリのインポート

In [1]:では次のようなwarningが出るかもしれませんが、無視しても問題ありません。

f:id:nn_hokuson:20171223142508j:plain:w620

RuntimeWarning: compiletime version 3.5 of module 'tensorflow.python.framework.fast_tensor_util' does not match runtime version 3.6

Step2. Hyparametersの設定

ディープラーニングを使って学習するためにはHyparametersと呼ばれるパラメータを設定する必要があります。必ず変更する必要があるのは「env_name」の項目で、ここにはさきほど書き出したアプリのファイル名を指定します。先ほどは「3dball」という名前で書き出したので、「env_name = "3dball"」と書き換えて下さい。

f:id:nn_hokuson:20171223140122j:plain:w620

このハイパラメータの設定がディープラーニングの学習方針を決めるのですが、最初のうちはどう設定したら良いのか戸惑うかもしれません。デフォルトのままでも問題ないので、一旦このまま進めてみましょう。

ハイパラメータの意味とおすすめ設定は次のようになります。慣れてきたら学習させたいモデルによって変更してみて下さい。

ハイパラメータ名 値の範囲 意味
Batch Size 32〜409600 勾配下降計算するときに使用するデータ量
Beta 1e^{-4}1e^{-2} 小さくすればエントロピーの減少が早くなる
Hidden Units 32〜512 ディープラーニングで使用する隠れ層の数
Learning Rate 1e^{-5}1e^{-3} 勾配下降する場合のステップ量

ハイパラメータの意味はこちらで詳しく解説されているので、参考にして見てください。

https://github.com/Unity-Technologies/ml-agents/blob/master/docs/best-practices-ppo.mdgithub.com

こちらのサイトでは日本語で紹介されています。

qiita.com

Step3. アプリケーションのロード

ln [3]:ではアプリを起動して通信を開始するまで少し時間がかかります。次のように表示されたら正しくアプリがロードされています。もし、表示されない場合はBrain Typeが「External」になっているかを再度確認して下さい。

f:id:nn_hokuson:20171223141745p:plain:w630

Step4. TensorFlowを使ったディープラーニング

ln [4]:がディープラーニングの実体です。PCの性能によりますが、30秒〜1分くらいで次のように学習結果が表示されます。Mean Rewardが70〜80程度になれば順調に学習が進んでいます。ある程度のところで「Run」ボタンの横にある停止ボタンを押して、ディープラーニングによる学習を停止しましょう。

f:id:nn_hokuson:20171223143051p:plain:w630

Step5. 学習結果の書き出し

最後のln [5]では学習結果をファイルに書き出します。学習ファイル名は、Hyparametersの項目で設定したenv_name + ".bytes"です。今回はenv_nameを3dballにしたので、学習結果のファイル名は3dball.bytesになります。

学習結果を反映する

学習が終わるとpython/models/ppoフォルダの中にball.bytesファイルが生成されます。これがTensorFlowを使ったディープラーニングの学習結果になります。この学習結果をアプリに読み込ませて実行してみましょう。

f:id:nn_hokuson:20171226210848j:plain

ball.bytesファイルをUnityのAssets/ML-Agents/Examples/3DBall/TFModelsフォルダに配置します。続いてヒエラルキービューからBall3DAcademy/Ball3DBrainを選択し、インスペクタでBrain TypeをInternalに変更します。これにより、TensorFlowを使った入力を受け付けるようになります

f:id:nn_hokuson:20171226212711j:plain:w300

Graph PlaceholdersのSizeを「1」にして設定項目を次のように指定指定下さい。この値はTensorFlowがノイズパラメータとして使う値です。Action Space TypeがDiscrete だった場合はepsilonの設定は不要です。

パラメータ
Name epsilon
Value Type Floating Point
Min Value 0
Max Value 0


さて・・・・いよいよです。
長かったですね!

Unity画面上部の再生ボタンを押してゲームを実行してみて下さい。ちゃんと学習できていれば、ボールを落とさないようにパドルの傾きが自動的に調節されるはずです。

f:id:nn_hokuson:20171226212138g:plain:w600

ちゃんと学習できていますね〜(^^)/ 上の結果で大体Mean Rewardが80程度のものです。もう少し値が低くても正しく動くはずです。

まとめ

今回は、UnityでTensorFlowを使ってディープラーニングをしてみました。ml-agentsというフレームワークを使うことで簡単に機械学習ができました。次回はAgentsのスクリプトを書き換えて独自のモデルを学習させてみようと思います!