해당 블로그는 유튜브 "freeCodeCampe.org" 님의 https://youtu.be/L8ypSXwyBds?si=GTo6sJqoXQU25LM6 영상을 참고했습니다.
관련 코드는 https://github.com/patrickloeber/snake-ai-pytorch 를 참고해주세요.
저는 기존 매매 알고리즘으로는 좋은 수익률의 매매 알고리즘이 찾기에는 한계가 있다는 것을 깨닫고 강화학습을 매매 알고리즘에 적용 해야겠다고 마음 먹었습니다.
그러기 위해서는 간단한 게임에 강화학습을 적용시켜본 후, 강화학습의 개념을 먼저 익혀보도록 하겠습니다.
이번 포스팅에서는 강화학습의 개념들을 먼저 소개시켜 드리겠습니다.
강화학습을 적용 시켜 볼 그 게임은 snake 게임 입니다.
# 게임 설명
사용자가 방향키로 저 파란색 snake를 조종하여 빨간색 박스에 부딛히면 점수를 얻게 됩니다.
점수를 얻게 되면 자신의 몸 길이는 한 칸 증가하게 됩니다.
다만 벽에 부딛히거나 조종하던 중 자신의 파란색 박스 몸에 부딛히면 게임 오버가 됩니다.
위의 github링크에 코드를 찾아서 실행시켜 보면 직접 게임을 해보실 수 있습니다.
이 게임을 강화학습을 통해 학습시켜 보겠습니다.
시작하기 전에 최종 프로젝트 결과 모습을 먼저 보여드리겠습니다.
# 결과 미리보기
왼쪽 창은 게임 횟수에 따른 현재 점수와 평균 점수를 보여줍니다.
게임 횟수가 적을 때에 게임 속 뱀은 게임에 대해 전혀 모르지만 환경을 알고 무작위적인 움직임을 시도하였을 겁니다.
그러나 게임이 진행되면서 더 많이 배우고 어떻게 플레이 해야하는지 알게 될 것입니다.
약 80~100 게임이 진행되었을때 인공 지능이 좋은 게임 전략을 갖게 되었습니다.
# 코드 구성
저희가 만들 강화학습 코드는 총 세가지로 구성되어있습니다.
-게임파트: pygame으로 구현할것입니다. 루프를 돌면서 게임이 진행됩니다. 한 루프가 돌 때 마다 액션을 수행해나가고, 수행결과를 스테이트로 리턴합니다. 스테이트는 뱀이 움직인 후 현재 보상, 게임오버 여부 그리고 현재 점수를 반환합니다.
-모델파트: 강화학습에서 에이전트를 학습시키는 모델입니다. 모델의 방식은 다양하지만 저희는 파이토치를 통해 딥 q러닝 방식을 사용할 것입니다. 순방향 신경망(feedforward neural network) 이며 심층 신경망을 사용하여 행동을 예측함으로써 강화학습을 진행해나갑니다.
-에어전트 파트: 에이전트는 기본적으로 모든 것을 종합하기 때무에 게임에 대해 알아야 하고 모델에 대해서도 알고 있어야 합니다. 그래서 에이전트에 위의 두가지 파트 모두 저장합니다.
# 변수
이제 동작, 상태, 보상과 같은 변수에 대해서 자세히 얘기 해보겠습니다.
-보상(reward): 뱀이 빨간 박스를 먹을 때마다 10 보상을 받습니다. 게임이 끝날 때, 즉 뱀이 죽을 때는 -10을 얻습니다. 그리고 나머지 모든 경우에는 단순히 0에 머무릅니다.
-동작(action): 동작은 뱀의 다음 움직임을 결정합니다. 상, 하, 좌, 우로 네 가지의 다른 동작이 있습니다. 이때 뱀이 만약 오른쪽으로 가다가 바로 왼쪽으로 가면 자기 자신의 몸을 건들이면서 게임 오버가 됩니다. 180도 회전하게 된 것입니다.
저희는 이러한 상황을 막아야 합니다. 그래서 상하좌우 방법보다 더 좋은 것은 오직 3가지 방향만 주는 것입니다.
1,0,0 은 현재 방향을 유지하는 것입니다. 상하좌우에 상관없이 현재 방향을 유지하는 것입니다.
0,1,0은 우측으로 회전, 0,0,1은 좌측으로 회전하는 것입니다.
이러한 접근 방식으로 저희는 180도로 바로 돌게 되는 문제를 예방할 수 있습니다.
-상태(state): 상태는 뱀에게 몇가지 정보를 알려줘야 합니다. 총 11개의 값을 알려줄 것입니다.
우선 위험이 바로 앞, 오른쪽, 왼쪽에 있는지에 대한 정보 3개가 있습니다.
여기서 위험은 자기 자신이랑 부딛히는 경우 또는 벽이랑 부딛히는 경우가 있을 수 있습니다.
그 다음은 현재 뱀의 방향 4가지가 있습니다.
마지막으로 음식(빨간색 박스)의 뱀에 대한 상대적 위치 정보 4가지가 있습니다.
이 모든 것은 boolean 값입니다.
# 모델 설명
이제 상태와 동작이 있으면 저희의 모델을 설계할 수 있습니다.
input layer는 앞서 말한 11개의 state가 될 것입니다. 그 다음에 hidden layer가 있고 마지막으로 output layer가 있습니다.
output layer는 뱀의 action을 나타낼 것입니다. 그러므로 마지막 output layer 값은 확률이 될 필요가 없고, 3개의 값 중 가장 큰 값을 선택하게 될것입니다. 위의 그림에서 action 박스 밑에 예시처럼 말입니다. [5.0, 2.7, 0.1] -> [1, 0, 0]
# 모델 학습 방법
이제 모델을 학습시키는 방법에 대해 설명 드리겠습니다. 먼저 deep q learning에 대해 설명드리겠습니다.
여기서 q는 action의 퀄리티를 의미합니다. 이것이 저희가 향상시키고 싶은 부분입니다.
각각의 action은 뱀의 퀄리티를 개선해야 할 것입니다.
0. 우선 q value를 초기화를 하며 시작을 합니다. 저희의 경우 저희의 모델을 랜덤한 파라미터로 초기화 시킵니다.
1. model.predict(state) 를 호출하여 action을 선택합니다. 가끔씩 랜덤한 action을 선택할 수 도 있습니다.
특히 게임에 대해 아직 많이 알지 못할 때인 초반 부분에 랜덤한 action을 선택하는 경우가 많습니다.
그리고 나중에는 trade-off를 합니다. action의 무작위성은 낮아지고 model.predict를 호출하는 경우가 많아질 것입니다.
이것이 trade-off입니다.
2. 얻게된 새로운 action을 수행하게 됩니다.
3. action에 따른 보상을 얻게 됩니다.
4. 이러한 정보들을 가지고 저희는 q 값을 업데이트하게 되고 모델을 훈련시키게 됩니다.
1~4번을 반복하게 됩니다.
#벨만 방정식(Bellman Equation)
모델을 훈련시키기 위해서는 일반적으로 최적화하거나 최소화시켜주는 어떤 '손실 함수'가 필요합니다. 따라서 손실 함수의 수학적인 내용을 알아보겠습니다. 여기에서는 '벨만 방정식'이라는 것을 소개해 드리겠습니다.
모델을 학습시키기 위해서는 q값을 업데이트 해줘야 합니다. 벨만 방정식이 q값을 업데이트 해주는 방정식입니다.
위의 식은 조금 복잡해 보일 수 있으니 조금 더 간단한 식으로 보여 드리겠습니다.
state0는 get_state(game)함수를 통해 구할 수 있습니다.
q값은 model.predict에 현재 state인 state0를 취해서 구할 수 있습니다.
state1은 game.play_step함수를 통해 게임이 진행된 후 다시 get_state함수를 호출하면 new_state인 state1을 얻을 수 있습니다.
R(reward)는 위의 문장에서처럼 game.play_step에서 얻을 수 있습니다.
new q는 보상R과 할인율r에 state1에서 얻을 수 있는 미래의 최대 보상값을 곱한것을 더한 것이 됩니다.
손실 함수는 Qnew와 Q의 mean squared error로 계산할 수 있습니다.
'파이썬으로 퀀트 프로그램 만들기 project > 강화학습' 카테고리의 다른 글
강화학습으로 비트코인 차트 학습시키기 (0) | 2024.03.03 |
---|---|
강화학습으로 snake game 학습시키기_2 (0) | 2024.03.02 |