LIS (Life in Silico) のソースを読んでみる


全てを説明できているわけでは無いですが、とりあえず。

とりあえずインストール
==================

以下を参照。特に、はまるところは無いです。

[LIS (Life in Silico)をMacで動かす](http://qiita.com/morizotter/items/32274f65b2c1fa1c8351)


ソースコード構成
=============

* unity-sample-environment => Unity に import するプロジェクトのルートディレクトリ
  * Assets
     * CameraBuffer => カメラで撮影した画像をTextureとして保持する。 [こちら](https://docs.unity3d.com/ja/current/Manual/class-RenderTexture.html)または、[こちら](https://docs.unity3d.com/ja/current/ScriptReference/RenderTexture.html)参照
     * Editor => モバイル端末でジョイスティックをシュミレーションする。おそらく無関係（[参照](http://qiita.com/cabbage/items/7836efaa04bbb037b086))
     * Materials => オブジェクトの色やテクスチャを設定
     * Packages => 外部ライブラリ。messagepack を使うライブラリと、webspcketを使うライブラリが置いてある
     * Prefabs => [参照](https://docs.unity3d.com/jp/current/Manual/Prefabs.html)
     * Scenes => シーン [参照](https://docs.unity3d.com/jp/current/Manual/CreatingScenes.html)
     * Scripts => C#のソース
     * Shader => [参照](https://docs.unity3d.com/jp/current/Manual/Shaders.html) [参考](http://qiita.com/ShirakawaYoshimaru/items/5d6d8bad041c835f858a)
     * Standard Assets => 標準で入っているAsset?
  * Library => Unity でプロジェクトを読み込んだときにできるファイル。(gitには無い）
* python-agent => Pythonで書かれたサーバ。ここで、強化学習をしている

Scriptsの中身
-----------

* SceneController.cs => シーン（Hierarchyペイン -> sample-> SceneController）に設定されているスクリプト。シーンの基本的な動作はここに書かれている。
* IAIClient.cs => AIClient/AIClientAsync のインターフェース
* AIClient.cs => Websocket で通信する役割。SYNC（同期的）に動作
* AIClientAsync.cs => Websocket で通信する役割。ASYNC（非同期的）に動作
* Action.cs => アクション（Agentの行動）を保持
* Agent.cs => Agent（Hierarchペイン -> sample -> Agents -> Agent）に設定されているスクリプト。Agentから満たしてんのが増の取得が書かれている
* MyFirstpersonController.cs => Agent（Hierarchペイン -> sample -> Agents -> Agent）に設定されているスクリプト。一人称視点（FPS視点）の制御を行うコントローラ。
* Defs.cs => 定数
* Environment.cs => Environments の items（Hierarchペイン -> sample -> Environments -> items）に設定されているスクリプト。Rewordアイテムをランダムに配置
* State.cs => Agent の状態を保持
* Events
  * ResetEvent.cs => プレハブの ResetItem (Projectペイン -> Prefabs -> ResetItem) に設定されているスクリプト。ゲームがリセット（Agentが死ぬ）する。
  * RewardEvent.cs => プレハブの PlusRewardItem (Projectペイン -> Prefabs -> PlusRewardItem) に設定されているスクリプト。Reward(報酬)がもらえる。
  * RewardTriggerEvent.cs => プレハブの RewardArea (Projectペイン -> Prefabs -> RewardArea) に設定されているスクリプト。一定のエリアに入るとRewardがもらえ、でると、失うというようなことができる。


「シーン（Hierarchy-> sample->SceneController）に設定されているスクリプト。」等がどういう意味かと言うと、以下のように、Unityのオブジェクトに設定されています。SceneController.cs は、左のHierarchyペインのSceneControllerに設定されています。また、インスペクタのScriptにある設定項目は、ソースコード中に、[SerializeField]で定義されているものです。

![sc1.png](https://qiita-image-store.s3.amazonaws.com/0/38555/df28715f-0235-0166-cea4-74f7eab366f9.png "sc1.png")

pythonのコード
-------------

* cnn_dqn_agent.py => Agentの実装。bvlc_alexnet.caffemodel で画像認識し、Q Networkに入力している
* cnn_feature_extractor.py => bvlc_alexnet.caffemodel から、feature vector を取り出す
* multi_agent.py => 複数のAgentを起動するスクリプト（内部でserver.pyを呼ぶ）
* plot_reward_log.py => rewardのログ表示
* q_net.py => Q Networkのモデルを作成している
* server.py => 起動スクリプト


基本的な動作の流れ
===============

Unity側
-------

* SceneController が起動
* AIClient がInitialize
  * 別スレッドで、Queueを監視。何か入ったら、WebSocketで、MessagePackを送信
* Environment で、rewardのオブジェクトを作成
* AIClient で画像をPython側に送り、Python側からメッセージを受けり、アクションを実行、を繰り返す

Python側
-------

* server.py がメッセージを受け取り、画像を取り出す
* 画像をAgent(cnn_dqn_agent.py)に入力
* 画像をCnnFeatureExtractor(cnn_feature_extractor.py)にわたして、feature vectorに変換
* feature vector を Q(q_net.py)にわたして、actionを得る
* action を Unity側に送信