UE4で強化学習環境を動かし、学習状況を可視化する(Part2)
はじめに
ご無沙汰しております。iPXのabikoです。
あれよあれよという間に、気がつけば年の瀬が近づいて参りました。
皆さまお体に気をつけて、よいお年をお迎えください。
前回までのあらすじ
前回強化学習の学習状況の可視化をやってみようとUnrealEnginePythonを導入しました。
そして、UnrealEnginePython付属のPythonEditorでコードを実行し、いつものアニメーションが再生するところまで確認できました。
今回はUE4内にオブジェクトを作成して、学習中のカートの位置・ポールの角度を反映し、実際に可視化まで行っていきます。
※前回に引き続き、学習自体は行いません。可視化がメインです。
強化学習環境にはOpenAI Gymを使用し、行動はランダムで与えます。
では、張り切っていきましょう!
PyActorと連携して、ゲームプレイで動作させる
1. PythonEditorを開き、新規にファイルを作成して次のコードを記述します。
import unreal_engine as ue ue.log('Hello UnrealEnginePython!') class ViewGym: def begin_play(self): ue.log('ViewGymClass begin play') def tick(self, delta_time): ue.log('delta_time: %s' % delta_time)
2. PyActorクラスを作成して、1. で作成したファイル名とコード内のクラス名を指定します。
ここでは、ファイル名はPythonScript3、クラス名はViewGymです。
(PyActorクラスの名前はBP_ViewGymとしました)
3. 連携できているかを確認します。
作成したPyActorクラス(BP_ViewGym)をレベル内に配置します。
アウトプットログウィンドウを表示し、ゲームプレイを実行してみます。
ログを"LogPython"でフィルタし、下記のような結果が得られていれば正しく連携できています。
表示しているのは前回フレームからの経過時間です。
60fpsで動作していれば、下記のように16ms付近の値が出力されます。
LogPython: Hello UnrealEnginePython! LogPython: ViewGymClass begin play LogPython: delta_time: 0.01666729897260666 LogPython: delta_time: 0.14368070662021637 LogPython: delta_time: 0.016666699200868607 LogPython: delta_time: 0.0166671983897686 LogPython: delta_time: 0.01666710153222084 LogPython: delta_time: 0.016667399555444717 …
Gymのコードをゲームプレイで実行できるように変更
つづいて、PythonScript3の記述を以下のように変更します。
import unreal_engine as ue import gym ue.log('Hello UnrealEnginePython!') class ViewGym: def begin_play(self): ue.log('ViewGymClass begin play') self.env = gym.make('CartPole-v0') self.observation = self.env.reset() self.done = False def end_play(self, reason): ue.log('ViewGymClass end play') self.env.close() def tick(self, delta_time): ue.log('ViewGymClass event tick') if self.done: self.observation = self.env.reset() self.done = False self.env.render() action = self.env.action_space.sample() self.observation, reward, self.done, info = self.env.step(action)
ゲームプレイの実行によって、いつものアニメーションが再生されるようになれば成功です。
UE4にCartPole(台車と棒)を作成
1. BP_ViewGymに次のようにキューブとシリンダーコンポーネントを追加して簡易な外観を作成します。
2. スケールを変更してそれらしい形に変更します。
また、今回Poleの角度はオブジェクトのRotatorで表現します。
オブジェクトの中心が回転軸になるため、適当な位置に配置しましょう。
※台車を突き抜けてしまってますが、床上に配置すれば隠れて見えないのでよしとします(笑)
いざ可視化へ
Python側からコールする可視化イベントをBPで記述します。
環境で観測できる値(台車の位置、棒の角度)を引数で渡すと、アクター自身の位置・棒の角度が変更されるように書いています。
※環境で扱われている角度の単位がradianなので注意が必要です。(R2Dでdegreesへ変換)
また、位置の値をそのまま利用すると値が小さすぎて変化がわからない(±2.4)ので100倍して利用しています。
PythonScript3の最後の部分にBPのイベントを呼び出す連携コードを追記します。
self.env.render() # ↓ この行を追記 self.uobject.Render(self.observation[0], self.observation[2]) # ↑ action = self.env.action_space.sample() self.observation, reward, self.done, info = self.env.step(action)
ゲームプレイ実行します。
.....
無事可視化できました!
いつものアニメーションと同じように動いていることがわかります。
結び
次は別の環境についても可視化してみたいですね。
行動が連続空間である場合の基本的な環境、Pendulumなどはぜひ挑戦してみたいところです。
最後まで読んでいただき、ありがとうございました。
よいお年を。2020年にまた、お会いしましょう。