【AI】自作ゲームに深層強化学習(DDPG)を適用してみた。

こんにちは、ヒガシです!

 

今回は、前回作成した車の走行風のゲームにこれまた以前紹介した深層強化学習アルゴリズムであるDDPGを適用してみようと思います。

 

ちなみに私がやるとこんな感じでわりと上手に走らせることができました。

 

果たしてAIは私を超えられるのか?!

さっそくやっていきましょう!

 

スポンサーリンク

ゲームプログラムを強化学習用に修正する

今回の強化学習はKeras-RL2のDDPG-Agentを使用していきます。

というわけでDDPG-Agentがうまく飲み込める形にまずはゲームプログラムをClass化していく必要があります。

 

また、強化学習特有の報酬の設定なども前回の記事から追加する必要がありますね。

 

というわけで、まずはそのプログラムをご紹介します。

#ライブラリインポート
import numpy as np
class car_game():
    def __init__(self):
        self.img=self.make_course()
        self.dt=0.2
        self.vmax=30
        self.action_space=np.zeros(2)
        self.observation_space=np.zeros(4)
    def make_course(self):
        img1=np.zeros((1000,1000),np.uint8)
        cv2.rectangle(img1,(140,140),(860,860), color=255,thickness=120)
        img1[:500,:]=0
        img2=np.zeros((1000,1000),np.uint8)
        cv2.circle(img2,(500,500),radius=360,color=255,thickness=120)
        img2[500:,:]=0
        img=img1+img2
        return img
    def reset(self):
        self.L=0
        self.counetr=0
        self.x1,self.y1=500,140
        self.vx,self.vy=-10,5
        self.obs1=np.array([self.x1,self.y1,self.vx,self.vy])
        return self.obs1
    def step(self,action):
        x=min(max(action[0]*100+self.x1,0),999)
        y=min(max(action[1]*100+self.y1,0),999)
        ax,ay=(x-self.x1)*0.1,(y-self.y1)*0.1
        self.counetr+=1
        for i in range(8):
            self.vx,self.vy=self.dt*ax+self.vx,self.dt*ay+self.vy
            vabs=np.sqrt(self.vx**2+self.vy**2)/self.vmax
            self.vx,self.vy=min(max(self.vx/vabs,-self.vmax),self.vmax),min(max(self.vy/vabs,-self.vmax),self.vmax)
            self.x1,self.y1=self.vx*self.dt+self.x1,self.vy*self.dt+self.y1
            self.L+=np.sqrt((self.vx*self.dt)**2+(self.vy*self.dt)**2)
            self.x1=min(max(self.x1,0),999)
            self.y1=min(max(self.y1,0),999)
        if self.img[int(self.y1),int(self.x1)]==0:
            done=True
            print(self.L)
        else:
            done=False
            print(action)
        self.reward=self.L
        self.obs1=np.array([self.x1,self.y1,self.vx,self.vy])
        return self.obs1,self.reward,done,{}

 

基本的にはresetで初期の状態を返し、stepで各アクションを受け取ったあとの状態(obs1)

、報酬(reward)、一回のゲームが終了したかの判定(done)を返してあげればOKです。

stepの{}はまぁ作法みたいなものです。

 

また、今回の報酬は合計走行距離(L)としました。

基本的に強化学習のエージェントはこの走行距離をなるべく長くするように操作を頑張っていくことになります。

 

スポンサーリンク

作成したゲームを強化学習に適用する

それでは先ほど作成したゲームプログラムを深層強化学習アルゴリズムであるDDPGに適用してみましょう。

 

Keras-rlのDDPGの使い方は以下のサイトがわかりやすかったので今回はこちらのプログラムを参考にさせていただいております。

【深層強化学習、keras-rl】 keras-rlで連続値の行動を扱えるDDPGを試す
深層強化学習ライブラリであるkeras-rlを用いて、 DDPGを動かしてみます。Open AI gym で提供されているPendulumという問題を解きます。基本的にはkeras-rlのexmpleコードを用います。適宜、日本語のコメント

 

というわけで以下が私が実際に使用したプログラムです。

import numpy as np
import matplotlib.pyplot as plt
from keras.models import Sequential, Model
from keras.layers import Dense, Activation, Flatten, Input, Concatenate
from tensorflow.keras.optimizers import Adam
from rl.agents import DDPGAgent
from rl.memory import SequentialMemory
from rl.random import OrnsteinUhlenbeckProcess
env = car_game()#自作ゲームのプログラムを環境とする
nb_actions = env.action_space.shape[0]

actor = Sequential()
actor.add(Flatten(input_shape=(1,) + env.observation_space.shape))
actor.add(Dense(100))
actor.add(Activation('relu'))
actor.add(Dense(100))
actor.add(Activation('relu'))
actor.add(Dense(100))
actor.add(Activation('relu'))
actor.add(Dense(nb_actions))
actor.add(Activation('sigmoid'))
print(actor.summary())

action_input = Input(shape=(nb_actions,), name='action_input')
observation_input = Input(shape=(1,) + env.observation_space.shape, name='observation_input')
flattened_observation = Flatten()(observation_input)
x = Concatenate()([action_input, flattened_observation])
x = Dense(100)(x)
x = Activation('relu')(x)
x = Dense(100)(x)
x = Activation('relu')(x)
x = Dense(100)(x)
x = Activation('relu')(x)
x = Dense(1)(x)
x = Activation('linear')(x)
critic = Model(inputs=[action_input, observation_input], outputs=x)
print(critic.summary())


memory = SequentialMemory(limit=100000, window_length=1)
random_process = OrnsteinUhlenbeckProcess(size=nb_actions, theta=.15, mu=0., sigma=.3)
agent = DDPGAgent(nb_actions=nb_actions, actor=actor, critic=critic, critic_action_input=action_input,
                  memory=memory, nb_steps_warmup_critic=2000, nb_steps_warmup_actor=2000,
                  random_process=random_process, gamma=.99, target_model_update=5e-3,batch_size=256)
agent.compile(Adam(lr=.001, clipnorm=1.), metrics=['mae'])
history = agent.fit(env, nb_steps=50000, visualize=False, verbose=1, nb_max_episode_steps=200)
agent.test(env, nb_episodes=1, visualize=False, nb_max_episode_steps=200)

 

これで50000回の試行による学習と1回のテストを実行できます。

 

スポンサーリンク

DDPGにゲームをやらせてみた結果

それでは先ほどのプログラムで学習させ、テストしたときの結果を可視化してみます。

※先ほど紹介したプログラムは可視化するところまでは実装していません。可視化実装は別プログラムでゴリゴリ実装したので割愛します。

 

結果はいかに?!?!

 

以下がDDPGにやらせてみた結果です。

う~ん、微妙・・・。そんなに遠くまで走れてないですね。

※左下でショートカットしてる感じになってますが、プログラム的にこれは私のミスなのでここはOKとしましょう。笑

 

もう少し試行回数を増やすべきなのか?

それともDDPGで問題視されている不安定性の影響なのか?

 

まぁいずれにせよもとは何も知らなかったコンピュータが数時間で学習でここまでできるようになるのはすごいことですよね。

 

しかもDDPGというのは出てきてからもうかなりの年月がたっており、現在の最新アルゴリズムならもっとうまくいくと思います。

 

時間があればそのあたりも試してみようと思います。

 

スポンサーリンク

おわりに

というわけで今回は自作したゲームに強化学習アルゴリズムであるDDPGを適用して遊ばせてみました。まだまだ精度改善の余地はありそうですが、とりあえずうまく動いたということにしておきましょう。

 

このように、私のブログでは様々なスキルを紹介しています。

過去記事一覧

 

今は仕事中で時間がないかもしれませんが、ぜひ通勤時間中などに他の記事も読んでいただけると嬉しいです。
⇒興味をもった方は【ヒガサラ】で検索してみてください。

確実にスキルアップできるはずです。

 

最後に、この記事が役に立ったという方は、ぜひ応援よろしくお願いします。
↓ 応援ボタン
にほんブログ村 IT技術ブログへ
にほんブログ村

それではまた!

コメント

タイトルとURLをコピーしました