Unity ML-Agentsは、Unityで機械学習の学習環境を構築するためのフレームワークです。
Unity ML-Agentsでの2プロセスに関して説明します。
学習プロセス
学習用Pythonスクリプトが学習環境となるUnityで強化学習を行います。
学習結果は推論モデルとして保存されます。
推論プロセス
学習結果となる推論モデルをつかってUnityで動作します。
推論モデルは与えられたデータから推論結果を導き出すものです。
Unity ML-Agentsは、Unityで機械学習の学習環境を構築するためのフレームワークです。
Unity ML-Agentsでの2プロセスに関して説明します。
学習用Pythonスクリプトが学習環境となるUnityで強化学習を行います。
学習結果は推論モデルとして保存されます。
学習結果となる推論モデルをつかってUnityで動作します。
推論モデルは与えられたデータから推論結果を導き出すものです。
まだ見たことのない場面に対する好奇心を報酬として学習させる手法です。
ICMでは次の2つのモデルを同時に学習します。
これらによってエージェントにとって未知である行動を取るほど報酬を多く受け取ることになります。
迷路を探索してさまざまな行動をとる必要があるゲーム等に最適な学習方法です。
時系列を扱えるニューラルネットワークです。
強化学習では通常「現在の環境」に応じて行動を決定しますが、RNNを利用することで「過去の環境」の状態も踏まえて行動を決定することができるようになります。
エージェントが記憶を持つようなイメージです。
ただRNNでは長期記憶の学習がうまくできないという問題があるため、次で説明するLSTMで長期記憶ができるように改善します。
長期的な依存関係を学習することのできるRNNの特別な一種で、1つ前の入力データをうまく扱うことに特化した「LSTMブロック」を組み込みます。
多種多様な問題にとてもよく動作し、現在では広く使用されています。
カリキュラム学習はタスクの難易度を徐々に上げていくことにより、効率的な学習を可能にする手法です。
例としましては「足し算・引き算」を学んだあと、「掛け算・引き算」を学び、そのあとで「面積の計算」を学習します。
学んだ知識をその後の学習に生かすことで、より難しい問題を解くことが可能になります。
この手法は機械学習にも適用可能で、簡単なタスクを訓練することでより困難なタスクを達成することを目指します。
強化学習を実践していく上でシミュレータが必要なことがわかり、シミュレータとしてはUnityが便利だということがわかり、さらにUnity ML-Agentsを使うとPythonからUnityを動作させることが分かりました。
そして参考文献を探したところ目的にはまった下記の書籍を見つけましたがバージョンが古いせいでしょうか、まったく動作させることができずしばらく放置していました。
しかしなんとか動作させることができるようになったので備忘録としてまとめておきます。
Pythonで学ぶ強化学習 -入門から実践まで- サンプルコード
書籍(P.41)にしたがってUnityをインストールします。
私の環境ではUnityのバージョンは2017.3.1f1 (64-bit)を使用しました。
サポートサイトに記載されていますが、下記のリンクからUnity ML-Agents v0.4.0bをダウンロードします。
https://github.com/Unity-Technologies/ml-agents/tree/0.4.0b
※2019/11/16現在の最新バージョンは0.11なのでかなり古いバージョンです。
書籍(P.42)にしたがってTensorFlowSharpプラグインをダウンロードをインストールします。
書籍(P.43)にしたがってPythonをインストールし、仮想環境を構築します。
Pythonバージョンは3.6で問題ありません。
書籍(P.44)に該当する箇所ですが、【手順2】でダウンロードしたファイルを使ってPythonパッケージをインストールします。
ダウンロードしたものの中にpythonフォルダがありますのでそのフォルダに移動してインストールコマンドを実行します。
1 | cd (ダウンロードした中のpythonフォルダ) |
ここが一番はまったポイントでした。
Numpyのバージョンは1.17.4がインストールされていたのですがこれを1.14.5に落とします。
1 | pip uninstall numpy |
(動作確認時に配列関連エラーでExceptionが発生していたのでnumpyのバージョンを疑い、結果動作させることができるようになりました。)
書籍(P.47~P.49)にしたがってプロジェクトの設定を行います。
書籍(P.50~P.52)のexeを作っての実行はうまくいかないのであきらめました。
書籍(P.63)「Unity Editor上での学習」の方を実行したところ問題なく動作確認できました。
以上で一通り書籍に書かれているサンプルを実行させることができるようになります。
もしこれでもうまくいかない場合のため、動作確認ができた環境のライブラリバージョン一覧を書いておきますので、参考にして頂ければと思います。
1 | > pip list |
私と同じように動作確認をあきらめてしまった方の一助になれば幸いです。
経験の蓄積と活用のトレードオフのバランスをとる手法としてEpsilon-Greedy法を実装します。
何枚かのコインから1枚を選んで、投げた時表が出れば報酬が得られるゲームを考えます。
各コインの表が出る確率はバラバラです。
必要なパッケージをインポートします。
1 | import random |
コイントスゲームの実装を行います。
head_probsは配列のパラメータで各コインの表が出る確率を指定します。
max_episode_stepsはコイントスを行う回数で、この回数の実行して表がでた回数が報酬となります。
1 | class CoinToss(): |
エージェントを作成します。
policy関数で、epsilonの確率でランダムにコインを選択し(探索)、それ以外の確率で各コインの期待値にそってコインを選択します(活用)。
play関数は、コイントスを行う処理です。
1 | class EpsilonGreedyAgent(): |
5枚のコインを用意し、コイントスの回数を変えながら、各エピソードにおける1回のコイントスあたりの報酬を記録していきます。
1 | if __name__ == "__main__": |

epsilon=0.1と0.2ではコイントスの回数とともに報酬が向上していることが分かります。
参考
Pythonで学ぶ強化学習 -入門から実践まで- サンプルコード
価値を再帰的かつ期待値で表現する手法をBellman Equationと呼びます。(Valueベース)
Bellman Equationを使えば各状態の価値が計算可能となります。
まず価値を返す関数を定義します。
1 | def V(s, gamma=0.99): |
報酬関数を定義します。
エピソード終了のとき”happy_end”であれば1を返し、”bad_end”であれば-1を返します。
エピソードが終了していなければ0を返します。
1 | def R(s): |
全ての行動でV(s)を計算し値が最大になる価値を返します。
評価vの計算式は確率遷移×遷移先の価値となります。
upかdownかを繰り返していき5回行動したら終了となります。
1 | def max_V_on_next_state(s): |
遷移関数を定義します。
1 | def transit_func(s, a): |
実際に価値V(s)の計算を行ってみます。
1 | if __name__ == "__main__": |

upの数が多い方が評価されます。
参考
Pythonで学ぶ強化学習 -入門から実践まで- サンプルコード
マルコフ決定過程(MDP)に従う環境を構築します。
マルコフ決定過程(MDP)は次のようなルールに従います。
今回は次のような迷路を解く環境を実装します。

まずは必要なパッケージをインポートします。
1 | import random |
状態を表すクラスを定義します。
縦位置をrow、横位置をcolumnで表します。
1 | class State(): |
行動を表すクラスを定義します。
行動は上下左右への移動4種類です。
1 | class Action(Enum): |
環境の実体となるクラスを定義します。
迷路の定義を2次元配列のgridで受け取ります。
gridの要素は次のような意味となります。
| 値 | 意味 |
|---|---|
| 0 | 移動可能な場所を表します。 |
| -1 | ダメージを受ける場所でゲーム終了となります。 |
| 1 | 報酬を得られる場所でゲーム終了となります。 |
| 9 | 壁を意味し移動することができない場所です。 |
default_rewardは基本の報酬となり、この変数をマイナスにすることで意味なく行動することを防ぎ、早くゴールに向かうことを促します。
1 | class Environment(): |
遷移関数を定義します。
選択した行動にはmove_prob(80%)の行動確率を設定し、反対の行動には0%の行動確率を設定します。
残りの2方向の移動には10%の行動確率を設定します。
(トータルの行動確率は100%になります。)
1 | def transit_func(self, state, action): |
行動できる場所(状態)かどうかを判定する関数を定義します。
1 | def can_action_at(self, state): |
ある状態である行動をすると、次にどの状態になるかを返す関数を定義します。
迷路の範囲外への移動を防いだり、壁にぶつかったかどうかはこの関数内で判断します。
1 | def _move(self, state, action): |
報酬関数を定義します。
ある状態で報酬が得られるかどうか、ダメージを受けるかどうかを判定します。
ゲームが終了するかどうかもこの報酬関数で判定します。
1 | def reward_func(self, state): |
エージェントの位置を初期化する関数を定義します。
ゲーム開始時や、ゲームが終わり再度ゲームを開始する場合に使用します。
1 | def reset(self): |
行動を行う関数を定義します。
行動を受け取り、遷移関数から遷移先を算出し、さらに報酬関数から即時報酬を取得します。
1 | def step(self, action): |
遷移関数を定義します。
行動を受け取り、遷移関数を使って行動確率を取得します。
行動確率から実際にどう行動するかどうかを最終決定します。(np.random.choice関数を使用)
決定した行動より遷移先と報酬、終了したかどうかの結果が導きだされます。
1 | def transit(self, state, action): |
エージェントを定義します。
エージェントのpolicyは状態を受け取って行動を決める関数ですが、今回は単純にランダム行動をとるようにしています。
1 | class Agent(): |
環境内でエージェントを動作させるコードを実装します。
迷路の定義(grid)を行い、それをもとにして環境(Environment)作成します。
作成した環境をエージェントに渡して、そのエージェントを行動させることでゲームが実行されます。
1 | def main(): |

単純なランダム行動ですが、10ゲーム行い10回分の報酬を取得できることを確認できます。
参考
Pythonで学ぶ強化学習 -入門から実践まで- サンプルコード
ニューラルネットワークの学習では勾配法が使われることが一般的ですが、勾配法とは違うアプローチとして「進化戦略」と「遺伝的アルゴリズム」があります。
パラメータを複数生成し、各パラメータを使った場合のモデルを評価します。
評価がよいものに近いパラメータをさらに生成し、評価を行うというプロセスを繰り返します。
(多くの候補から優秀なものを絞り込むというアプローチです)
進化戦略と基本は同じですが、評価が高かったパラメータ同士を混ぜる(交叉)、ランダムなパラメータを入れる(突然変異)という操作を行います。
模倣学習では、専門家や上手な人の行動を記録しておいてそれと近い行動をとるようにエージェントを学習させます。
少ないデータで望ましい行動を短時間で学習させることができる模倣学習はとても重要な学習手法です。
模倣学習には2つの問題があります。
模倣学習の方法として次の4つがあります。
各タイムステップの個別戦略を作っておいてそれをつなぎ合わせて全体戦略とします。
単純な教師あり学習より実際の状態遷移分布に近いデータで各戦略を学習させることができます。
複数の戦略を混合していく手法です。
最初の戦略は上手な人の行動だけから学習し、その後は学習した戦略を混ぜていきます。
戦略ではなくデータを混ぜ合わせていき、そこから学習して戦略を作成していきます。
具体的には各ステップで得られた状態とその状態における上手な人の行動のペアを学習データに足していきます。
上手な人の模倣を見破られないようにする手法です。
模倣する側と模倣を見破る側の2つのモデルが存在し、一方は模倣を行いもう一方は鑑定を行う設定で学習を行います。(敵対的学習)