おもちゃラボ

Unityで遊びを作ってます

AR Studioを使ったらARアプリが超簡単に作れた

Facebookから提供されている「AR Studio」という開発環境を使ってARアプリを作ってみたので、その使い方をまとめてみました!

f:id:nn_hokuson:20180118202935j:plain

この記事ではAR Studioを使って2Dと3Dのモデル表示までを一通りのことをやってみたいと思います。今回の内容は次のとおりです。

AR Studioとは

AR StudioとはFacebookから提供されている開発環境で、「AR Studio」という名前の通りAR(とくに顔をつかったAR)に特化した開発が簡単に行えるものです。

UnityであればDlibなどのAssetを購入してプログラムを作成する必要がありますが、AR Studioでは標準機能だけで簡単にARアプリを作ることができます。

このAR Studioの使い勝手は、次のように良くも悪くもUnityに非常に似ています。Unityを使ったことがあるのであれば、数分で使い方はマスターできると思います。

では、早速AR Studioのインストールから始めましょう!

AR Studioのインストールとプロジェクト作成

AR StudioはFacebookのDevelopperサイトからダウンロードすることができます。次のページからダウンロードしてインストールしましょう。

developers.facebook.com

AR Studioを起動したら、右下の「Create New Project」をクリックしてください。

f:id:nn_hokuson:20180118194523j:plain:w500

するとUnityっぽい画面が表示されます(笑)

f:id:nn_hokuson:20180118194406j:plain

Face Trackerを使ってみる

まずは顔の向きなどを追跡する「Face Tracker」を追加しましょう。画面左上の「Insertボタン」をクリックし、「Face Tracker」を選択してください。

f:id:nn_hokuson:20180118194701j:plain

すると真ん中のビューに顔に追従して動くマニュピレータが追加されたと思います。

f:id:nn_hokuson:20180118194735g:plain:w400

あとは今追加したFace Trackerの子要素に、2Dの画像なり、3Dオブジェクトなりを追加していくだけで、顔に追従してオブジェクトが動くようになります!超簡単!

2Dの画像を使ってARを表示する

2Dのスプライトを顔に合わせて動かすには、スプライトを張るためのポリゴン(板ポリ)が必要になります。AR Studioには次の2種類のポリゴンが用意されています。

  • Face Mesh
  • Plane

名前の通りFace Meshは顔の形状をした3Dモデル、Plane はただの板ポリです。今回はPlane Meshを使ってみましょう。

左ペイン(Unityでいうことろのヒエラルキービュー)でfacetracker0を右クリックして、「Insert→Plane」をクリックしてください。

f:id:nn_hokuson:20180118194908j:plain

Face Meshの子要素にPlane0が 追加され、顔にも市松模様の板ポリが表示された状態になります。

f:id:nn_hokuson:20180118195121j:plain

次に、市松模様のテクスチャのかわりにヒゲのテクスチャを貼り付けてみましょう。
f:id:nn_hokuson:20180118194958p:plain:w200
ポリゴンにテクスチャを貼るための流れは次の3ステップになります。

  1. マテリアルを作成
  2. マテリアルにテクスチャを設定
  3. モデルにマテリアルを設定

左ペインでAssetsの横の「+ボタン」をクリックして「Create New Material」を選択します。作成したマテリアル名は「bin_mat」に変更しておきましょう。

f:id:nn_hokuson:20180118195412j:plain:w400

次に作成したマテリアルにテクスチャを設定します。右ペイン(Unityで言う所のインスペクタ)から「Diffuse→Texture→Choose Files...」をクリックしてヒゲの画像を選択してください。

f:id:nn_hokuson:20180118195910j:plain

これで、マテリアルにテクスチャが設定できたので、最後にPlane(板ポリ)にマテリアルを設定します。左ペインからfacetracker0の子要素であるplane0を選択し、右ペインのMaterialの横の「+ボタン」をクリック、作成した「bin_mat」を選択します。

f:id:nn_hokuson:20180118195739j:plain

これで、画面上の人にヒゲがAR表示されたと思います!結構簡単じゃなかったですか?

f:id:nn_hokuson:20180118195751g:plain:w400

3Dオブジェクトを使ってARを表示する

次に帽子の3Dモデルを頭の上に表示してみましょう。3Dモデルのフォーマットは今のところ(2018年1月現在)「.dae」の必要があります。daeフォーマットはBlenderで書き出すことができます。

本記事で使用する帽子のモデルテクスチャは↓に置いておきます。自由にご利用下さい。

www.dropbox.com

先ほど、Planeを設定したときと同じようにして、facetracker0の上で右クリックし、「Insert」→「3D Object」を選択し、hat.daeをインポートします。

f:id:nn_hokuson:20180118200014j:plain

帽子のオブジェクトを読み込むとfacetracker0の子要素としてhat.daeが左ペインに表示されます。読み込んだ初期状態では帽子がかなり大きいと思います。

f:id:nn_hokuson:20180118200110j:plain

そこで、うまく頭の上に帽子がのるように、右ペイン(インスペクタ的なところ)でPosition、Scale、Rotationを調節して下さい。これらのパラメータ調整は真ん中のマニュピレータを操作することもできますし、インスペクタで設定することもできます。

f:id:nn_hokuson:20180118200458j:plain

最後に帽子のテクスチャを設定します。こちらもPlaneにヒゲ画像を表示したときと同じように、次の3ステップで進めます。

  1. マテリアルを作成
  2. マテリアルにテクスチャを設定
  3. モデルにマテリアルを設定

右ペインのAssets横の「+ボタン」を押し「Create New Material」を選択して下さい。できたマテリアル名を「hat_mat」に変更します。

f:id:nn_hokuson:20180118200606j:plain:w250

左ペインで「hat_mat」のマテリアルを選択した状態で、右ペインの「Diffuse→Texture→Choose Files...」をクリックし、hattex.pngを選択して下さい。

f:id:nn_hokuson:20180118201218j:plain

最後にhat.daeの子要素のCylinderを選択して、右ペインのMaterial欄に「hat_mat」を設定して下さい。これで帽子のモデルにテクスチャが表示されます。

f:id:nn_hokuson:20180118201223j:plain

これで帽子の3DモデルもAR表示することができました!

f:id:nn_hokuson:20180118201558g:plain:w300

まとめ

Unityで顔を使ったARを作ろうとすると、dlibやOpenCVなどのアセットを使うことになると思います。このAR Studioを使えば非常に簡単に顔を利用したARアプリケーションが作れることが分かりました。

【Arduino】BLE NanoでスマートフォンとBLE通信する

Arduinoとスマートフォンの間でデータのやり取りをしたい場合、Wifi通信を使う方法やBLE通信を使う方法が一般的です。ここではBLE Nanoと呼ばれるモジュールを使ってArduinoとiPhoneの間でデータ通信をしてみたいと思います。

f:id:nn_hokuson:20180110204246j:plain:w550

Wifiを使って通信をする場合はESP-WROOM-02というモジュールを使うのが簡単です。このモジュールの使い方は次の記事にまとめているので参考にして下さい。

nn-hokuson.hatenablog.com

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

BLEモジュールを選定する

Arduinoには標準ではBLEがついていないため、次の3つの方法のいずれかでBLEを使うことになります。

  • BLEつきのArduinoを使う
  • BLEモジュールをArduinoに追加する
  • BLEモジュールをArduinoとして使う

BLEつきのArduinoを使う

1つ目のBLE付きのArduinoですが、Genuino 101が有名ですが、既に生産を終了しており在庫限りのようです。(Genuino UnoにはBLEモジュールは搭載されていないので注意して下さい)使い勝手はArduinoと変わらないため便利ですが、4980円と少々お高いのがネックです・・・

http://akizukidenshi.com/catalog/g/gM-10413/akizukidenshi.com

もう少し安価な商品としてはBlunoやBLEduinoなどがあります。こちらは3800円程度でGenuino 101と比べると少しお安くなっています。

[asin:B00TH02SWW:detail]

BLEモジュールをArduinoに追加する

こちらはArduinoに外付けでBLEモジュールを追加する方法です。スマートフォンと通信する場合は浅草ギ研のBLE Serialモジュールが良さそうです。ホームページでもスマートフォンとの接続方法やプログラムなども公開されており、簡単に始められます。お値段は4000円。

www.robotsfx.com

BLEモジュールをArduinoとして使う

最後の選択肢は、BLEモジュールをArduinoとして使う方法です。これはRedBearLabのBLENano キット V2を使用します。このモジュールはArduinoのエディタからプログラムを書き込むことができ、プログラムもArduinoと同じように作ることができます。この記事ではこのBLENanoを使ってスマートフォンと通信する方法を紹介します。BLENanoは2018年1月現在、SWITCH SCIENCEから3888円で販売されています。

www.switch-science.com

ArduinoでBLENanoを使う準備

BLENanoのキットを使うことで簡単にiPhoneやAndroidと通信するプログラムを作ることができます。BLENanoのキットはライター(DAPLink)とBLEモジュールの2つで構成されています。使用するときはライターから取り外してBLEモジュールのみで使うことができます。

f:id:nn_hokuson:20180110204915j:plain:w350

BLENano v2をArduinoの開発環境で使うために、まずはパッケージをインストールする必要があります。使用するパッケージはnRF52832用のもので、BLENano v1で使用しているnRF51822とは異なるので注意して下さい。

少し古いサイトだとnRF51822のパッケージを使用する方法がかかれていますが、このパッケージではBLENanoにプログラムを正しく書き込むことはできないので注意して下さい。

Arduinoを起動し、メニューバーから「Arduino→Preferences」を選択、追加のボードマネージャーのURLの欄に次のURLを入力して下さい。

https://redbear.github.io/arduino/package_redbear_nRF5x_index.json.

f:id:nn_hokuson:20180109210254j:plain:w550

続いてメニューバーから「ツール→ボード→ボードマネージャー」を選択して、ボードマネージャウインドウを開いて下さい。リストから「RedBear nRF52832 Boards」を選択し、インストールして下さい。

最後にメニューバーから「ツール→ボード」から「BLENano2」、「ツール→書き込み装置」から「RBL_DAPLINK」を選択します。

f:id:nn_hokuson:20180109214509p:plain:w250

これでBLENano v2を使う準備は完了です。いよいよArduinoとスマートフォンを繋ぐBLE通信システムを作っていきましょう!

今回作成するBLE通信システム概要

今回はBLENano(Arduino)がペリフェラル、iPhoneがセントラルになるようなシステムを作ります。ペリフェラル側(BLENano)のボタンを押したら、1byteのデータがセントラル(iPhone)に送信されます。

f:id:nn_hokuson:20180110205949p:plain:w400

ペリフェラル・セントラルというのはBLE通信でよく使われる言葉で、ペリフェラル=クライアント、セントラル=サーバみたいなものです。BLE通信の概要はクラゲのIoTテクノロジーさんの「開発視点の超簡単BLE入門」で非常にわかりやすく説明されているので、一度読んでおくと、BLE開発の主要な用語と流れがつかめると思います。

jellyware.jp

ペリフェラル側を作る

まずはBLENanoにペリフェラルのプログラムを書き込みましょう。Arduinoを開いて次のプログラムを入力してください。

#include <nRF5x_BLE_API.h>
#define DEVICE_NAME            "Simulated RFduino"
#define TXRX_BUF_LEN           20

BLE                            ble;
Timeout                        timeout;
Ticker                         ticker_task1;
int prev = HIGH;

static const uint8_t service1_uuid[]        = { 0x00, 0x00, 0x22, 0x20, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x80, 0x5f, 0x9b, 0x34, 0xfb } ;
static const uint8_t service1_tx_uuid[]     = { 0x00, 0x00, 0x22, 0x22, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x80, 0x5f, 0x9b, 0x34, 0xfb } ;
static const uint8_t service1_rx_uuid[]     = { 0x00, 0x00, 0x22, 0x21, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x80, 0x5f, 0x9b, 0x34, 0xfb } ;
static const uint8_t service1_uuid_rev[]    = { 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80, 0x00, 0x10, 0x00, 0x00, 0x20, 0x22, 0x00, 0x00 } ;

uint8_t tx_value[TXRX_BUF_LEN] = {0,};
uint8_t rx_value[TXRX_BUF_LEN] = {0,};

GattCharacteristic  characteristic1(service1_tx_uuid, tx_value, 1, TXRX_BUF_LEN, GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE_WITHOUT_RESPONSE );
GattCharacteristic  characteristic2(service1_rx_uuid, rx_value, 1, TXRX_BUF_LEN, GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY);
GattCharacteristic *uartChars[] = {&characteristic1, &characteristic2};
GattService         uartService(service1_uuid, uartChars, sizeof(uartChars) / sizeof(GattCharacteristic *));

void periodicCallback() 
{
  static uint8_t value = 0x30;
  
  int v = digitalRead(D2);
  if( v == LOW && prev == HIGH){
      ble.updateCharacteristicValue(characteristic2.getValueAttribute().getHandle(), (uint8_t *)&value, 1);
      value++;
  }
  prev = v;
}
    
void setup() 
{
  Serial.begin(9600);

  pinMode(D2, INPUT_PULLUP);
  ticker_task1.attach(periodicCallback, 0.1);

  ble.init();
  ble.accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED);
  ble.accumulateAdvertisingPayload(GapAdvertisingData::SHORTENED_LOCAL_NAME,
                                   (const uint8_t *)"TXRX", sizeof("TXRX") - 1);
  ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_128BIT_SERVICE_IDS,
                                   (const uint8_t *)service1_uuid_rev, sizeof(service1_uuid_rev));

  ble.setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
  ble.addService(uartService);
  ble.setDeviceName((const uint8_t *) DEVICE_NAME);
  ble.setTxPower(4);
  ble.setAdvertisingInterval(160);
  ble.setAdvertisingTimeout(0);
  ble.startAdvertising();
  Serial.println("Advertising Start!");
}

void loop() {
    ble.waitForEvent();
}

ここではサービスとキャラクタリスティクスのUUIDを次のように定義しました。

Service UUID 00002220-0000-1000-8000-00805f9b34fb
Characteristics1 00002221-0000-1000-8000-00805f9b34fb
Characteristics2 00002222-0000-1000-8000-00805f9b34fb

プログラムが書き込めたら、BLENanoを書き込み装置から取り外して、次のような回路を作成します。ここではボタンが押された場合にBLENanoのD2端子がLOWになるようにしています。

f:id:nn_hokuson:20180110212157j:plain:w300

回路に電源を入れたらBLENanoはペリフェラルとしての動作を自動的に開始し、アドバタイズメントのパケットを送信しはじめます。

セントラル側をつくる

続いてスマートフォンで動くセントラルアプリを作成します。ここではUnityを使ってセントラル側のプログラムを作ります。iOS/Androidのネイティブプログラムでセントラルを作りたい場合は↓を参考にしてみてください。

Unityには、「Bluetooth LE for iOS, tvOS and Android」という超便利なアセットがすでに用意されています。これは、名前の通りiOSやAndroidのBLE通信コードをラップしたPluginです。C#だけでAndroidでもiOSでも簡単にBLE通信のプログラムを作ることができます。

ここでも、「Bluetooth LE for iOS, tvOS and Android」のアセットに付属するサンプルコードを使いましょう。上記アセットをインポートした後、Asset/Example/SimpleTestにある「SimpleTest.unity」をダブルクリックしてシーンを開いてください。

f:id:nn_hokuson:20180110202109j:plain:w600

SimpleTest.csがBLE通信のプログラムです。ヒエラルキービューでMain Cameraを選択し、インスペクタからSimple Testのパラメータを設定します。先ほどペリフェラルに書き込んだDevice Name、Service UUID、Characteristicを指定しましょう。ここでは次のように設定しました。

f:id:nn_hokuson:20180110202712p:plain:w300

UUIDは短縮で記述することができます。短縮する場合はUUIDの4文字目から8文字目までを指定します。サービスのUUIDは00002220-0000-1000-8000-00805f9b34fbですので、短縮で記述すると「2220」になります。UUIDの短縮についてはこちらもクラゲのIoTテクノロジーさんの「UUID詳細」が参考になります。

jellyware.jp

サンプルについてくるSimpleTestスクリプトでは動かないことがあるようなので、UpdateメソッドのScanのcase文を次のように書き換えて下さい。

case States.Scan:
  string[] serviceIDs = { ServiceUUID };
  BluetoothLEHardwareInterface.ScanForPeripheralsWithServices (serviceIDs, (address, name) => {

    if (!_rssiOnly)
    {
      {
        BluetoothLEHardwareInterface.StopScan ();
        _deviceAddress = address;
        SetState (States.Connect, 0.5f);
      }
    }

  }, (address, name, rssi, bytes) => {

    {
      if (_rssiOnly)
      {
        _rssi = rssi;
      }
      else
      {
        BluetoothLEHardwareInterface.StopScan ();
        _deviceAddress = address;
        SetState (States.Connect, 0.5f);
      }
    }

  }, _rssiOnly); // this last setting allows RFduino to send RSSI without having manufacturer data

  if (_rssiOnly)
    SetState (States.ScanRSSI, 0.5f);
  break;

設定が完了したら、スマートフォンにアプリを書き込んでください。指定したService UUIDをアドバタイズしているペリフェラルに自動的に接続し、待機状態になります。待機状態になると次のような画面(左)がスマートフォン上に表示されます。

この状態でペリフェラル側のスイッチを押してみて下さい。スマートフォンに「30」と表示(画面右)されれば成功です!

f:id:nn_hokuson:20180110203342p:plain:w200     f:id:nn_hokuson:20180110203351p:plain:w200

トラブルシューティング

スマートフォン側が正しく動かない場合、まずはペリフェラルが動いているかをチェックしましょう。BLE Scanner 4.0などのアプリが用意されているので、ちゃんとペリフェラルに接続できるか試してみると良いです。

BLE Scanner 4.0

BLE Scanner 4.0

  • Bluepixel Technologies LLP
  • 仕事効率化
  • 無料

おまけ:ネイティブプログラムを作りたい場合のオススメ

スマートフォンをセントラルとして動かすプログラムを作るにはiOSの場合はCore Bleutoothのリファレンスが参考になります。このCoreBluetoothのリファレンス、かなーりサンプルコードがしっかりと書かれているので、このとおり作っていけば簡単にセントラルのプログラムが作成できます。

https://developer.apple.com/jp/documentation/CoreBluetoothPG.pdf

iOS用にBLEの通信プログラムを作る場合は次の「iOSxBLE Core Bluetoothプログラミング」が非常に参考になりました。

[asin:4883379736:detail]

また、AndroidでBLEの通信プログラムを作る場合はこちらのサイトが参考になります。

qiita.com

【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のスクリプトを書き換えて独自のモデルを学習させてみようと思います!