황새 걷기 게임
황새걷기게임은 좌우 방향키로 귀여운 황새를 걷게 만들어주는 간단한 게임입니다.
다만 시간이 지날 수록 하체가 부실한 황새는 몸을 못 가누게 되고 잠깐만 한 눈을 팔면 쓰러져버리게 되는, 나름 집중력을 요하는 게임입니다.
https://www.youtube.com/watch?v=zXW_OHYAwEY
저도 해봤는데, 60m 까지는 상대적으로 순조롭게 가도 그 이상 가면 너무 잘 쓰러져서.. 저는 97m 기록까지만 세웠습니다.
페이커 선수는 개인방송에서 111m까지 달렸다고 하니, 그 이상을 뛰어넘는 AI를 만들어보고자 하였습니다.
그 방법으로는 강화학습을 택했습니다.
강화학습
고등학교 시절 강화학습 책을 읽으며 조금 공부해봤었는데, 생각해보니 황새 게임은 예전에 openai의 gym에서 경험해보았던 강화학습의 대표적인 예제인 Cartpole과 유사한 것 같았습니다. 그래서 아마도 학습이 수월할 것으로 예상했습니다.
황새게임은 Cartpole과 다르게 내장되어 있는 게임이 아니기 때문에 직접 환경(environment)을 만들어줬습니다. environment는 편의를 위해 gym 라이브러리의 Env 클래스를 상속받아 BirdEnv를 만들었습니다.
Env에서 구현해야하는 메소드는 step, reset, render 입니다.
step은 action을 인자로 받는 메소드입니다.
먼저 받은 action을 황새 게임에 적용합니다. 좌우 방향키를 누르거나 가만히 있거나의 행동을 취할 것입니다.
그 이후 state(≒observation)를 관찰하고
observation과 함께 게임이 끝났는 지 파악하는 is_over 변수를 리턴합니다. (추가로 메시지도 리턴 가능합니다.)
reset은 말 그대로 게임을 reset 하는 메소드입니다.
render는 데이터 상태의 state를 시각화하여 보여줄려고 할 때 사용하는 메소드인데, 딱히 필요 없으니 pass 합니다.
강화학습 모델은 stable-baselines3 라이브러리의 이미 만들어진 모델을 사용하려고 했습니다. stable-baselinees3에서는 다양한 모델을 지원하는데 그 중 DDPG를 사용해보았습니다.
DDPG는 일반적인 DQN과 달리 action space가 연속적이라는 특징이 있습니다. Agent가 게임을 할 때 특정 방향키를 누르는 시간을 조절할 수 있게 하려고 했었는데, 이에 적합할 것으로 보였습니다.
구현
게임 실행을 위해서는 플래쉬 플레이어가 필요한데, ruffle 이라는 플래쉬 에뮬레이터를 사용했습니다.
state를 얻기 위해서는 ruffle 에뮬레이터의 화면을 실시간으로 캡처해야 했는데, 예전에 써본 pyautogui 라이브러리를 사용하려 했으나 생각보다 프레임이 끊겨서 mss라는 더 빠른 라이브러리를 사용했습니다.
그리고 처음에는 프레임 자체를 state로 넘겨줘 CNN을 통해 학습하게 할까 생각했지만, state는 단순하게 하는게 학습이 금방 되지 않을까 하여, 황새의 머리의 좌표를 opencv의 matchTemplate 함수를 통해 인식하여 state로 사용하게 하였습니다.
observation_space는 3개의 요소로 이루어지게 했습니다. (황새 머리의 x좌표와, 황새 머리 x좌표의 5프레임 전과 비교했을 때의 변위차(≒속도), 현재 게임이 몇 프레임 진행되었는지)
action을 agent가 실행할 때는 받은 action 값에 따라 누르는 키보드의 방향키와 키보드를 누르고 있는 시간을 달리하게 했습니다.
if -0.3 < action[0] < 0.3:
pass
else:
self.shell.AppActivate(self.window_name)
action_type = 1 if action[0] < 0 else 2
win32api.keybd_event(self.key_map[action_type], 0, 0, 0)
time.sleep((abs(action[0]) - 0.3) / 70 + 0.01)
win32api.keybd_event(self.key_map[action_type], 0, win32con.KEYEVENTF_KEYUP, 0)
time.sleep(0.015)
state에 대한 reward를 줄 때는 황새의 머리가 중심부 근처에 있을 때는 4점을, 아니면 중심부에서 멀어진 정도의 제곱에 반비례하게 reward가 깎이도록 하였습니다.
if observation[0] > self.center:
if observation[0] < self.center + (self.right_end - self.center) * 0.25:
reward = 4
else:
reward = 3 - ((observation[0] - self.center) ** 2) * self.right_coef
else:
if observation[0] > self.center - (self.center - self.left_end) * 0.25:
reward = 4
else:
reward = 3 - ((self.center - observation[0]) ** 2) * self.left_coef
결과
우선, 페이커 선수의 111m를 넘는 것 자체는 성공했습니다.
무려 226m까지 황새가 걸을 수 있게 되었습니다. (아쉽게도 영상은 못 찍었지만)
다만 황새가 걷는 것의 편차가 매 게임마다 많이 심하고, reward-episode 그래프가 우상승 곡선을 그리지는 않았습니다.
아래 사진의 31 episode가 226m를 걸었던 지점인데, 바로 다음 에피소드에서 급격한 하락을 보여주었습니다. (그래프는 로그스케일 눈금입니다.)
31episode의 모델을 저장해서 load하고, learning_rate를 낮춰 재학습을 시켜봤지만, 향상이 보이지 않았습니다.
시간이 많지 않아 다양한 시도를 해보진 못했지만, 이후 시간이 된다면 더 다양한 방식을 시도해봐야할 것 같습니다. 하이퍼파라미터 튜닝, reward&action 방식 변경, CNN으로 변경 등등..
아래 136m를 달린 플레이 영상을 첨부하며 글은 마무리하겠습니다.
Github
https://github.com/woduq1414/RL-walk-the-stork
GitHub - woduq1414/RL-walk-the-stork: 황새걷기게임 강화학습하기
황새걷기게임 강화학습하기. Contribute to woduq1414/RL-walk-the-stork development by creating an account on GitHub.
github.com
참고
https://github.com/YBIGTA/AlphaChu
GitHub - YBIGTA/AlphaChu: Implementation of reinforcement learning on Pikachu Volleyball game
Implementation of reinforcement learning on Pikachu Volleyball game - GitHub - YBIGTA/AlphaChu: Implementation of reinforcement learning on Pikachu Volleyball game
github.com
https://github.com/MattYoon/Autonomous-Kartrider
GitHub - MattYoon/Autonomous-Kartrider: 건국대 2020 드림학기제 [자율주행 카트라이더]
건국대 2020 드림학기제 [자율주행 카트라이더]. Contribute to MattYoon/Autonomous-Kartrider development by creating an account on GitHub.
github.com
https://ropiens.tistory.com/96
강화학습 논문 정리 2편 : DDPG 논문 리뷰 (Deep Deterministic Policy Gradient)
작성자 : 한양대학원 융합로봇시스템학과 유승환 석사과정 (CAI LAB) 이번에는 Policy Gradient 기반 강화학습 알고리즘인 DDPG : Continuous Control With Deep Reinforcement Learning 논문 리뷰를 진행해보겠습니다~!
ropiens.tistory.com