강화학습/RL 강의 정리

모두를 위한 RL강좌 정리하기(Lecture 5 ~ Lab 5)

APinCan 2020. 8. 16. 16:38

사실 Frozen Lake라는 환경은 바람도 많이 불고 빙판길을 걸어가다가 미끄러질 수 있는 변수가 많은 환경이다. 그래서 에이전트는 자신이 원하는 곳으로 마음껏 갈 수 있는 것이 아니다. 그러니까 에이전트가 오른쪽으로 가고 싶다고 해서 항상 오른쪽으로 가는 것이 아니라 갑자기 왼쪽으로도 갈 수 있는 환경이 Frozen Lake라는 환경이다.

이번에는 이런 변수가 많은 환경에서 큐러닝을 적용시켜 본다.

 

위와 같이 변수가 많은 Frozen Lake 환경은 stochastic model이다. 대충 확률론적인 모델이라고 번역할 수 있는데 말했다시피 에이전트가 오른쪽으로 가는 action을 취했다고 해서 반드시 오른쪽으로 갈 수 있는 것이 아니다. 이와 반대로 deterministic model은 변수가 없는 모델로 오른쪽으로 가려고 했으면 반드시 오른쪽으로 가는 모델이다.

실제로 stochastic 환경을 이용해보면 다음과 같이 내가 오른쪽 방향키를 누른다고 해서 반드시 거기로 가는 것이 아님을 볼 수 있다.

안타깝게도 이런 stochastic world에서는 그동안 배웠던 큐러닝을 사용하면 안된다. 실제로 그 전까지 공부한 큐러닝을 가지고 학습을 시켜보니 에이전트가 목표지점을 제대로 찾아간 경우는 단 0.0165%였다. 상당히 낮은 수치이다. 그래서 이 큐러닝 알고리즘을 다시 써야한다.

 

큐러닝을 거의 그대로 사용하지만 우리가 새롭게 얻을 큐 값을 감가시키고 기존에 있던 큐값에 좀 더 가중치를 주는 방식으로 한다. 그래서 learning rate \(\alpha \)가 0.1이라면 에이전트가 새롭게 얻을 큐값은 0.1만큼만 더해주고 기존의 큐값에 0.9로 좀 더 많은 가중치를 주겠다는 얘기가 된다.

 

이 식을 조금 다르게 쓰면 다음과 같이 쓸 수가 있다.

여기까지 배운 큐러닝 알고리즘은 다음과 같이 쓴다.

그리고 이 방식 역시 큐값은 수렴한다.

 

여기까지 큐러닝을 배우니 내가 알던 형태가 나왔다. 파이썬과 케라스로 배우는 강화학습이라는 책에서는 여기까지 오는데 몬테카를로 예측, 시간차 예측, 살사, 큐러닝으로 왔고 이 강의는 조금 다른 방식으로 큐러닝까지 왔다. 

 

이제 이 내용으로 그대로 코드를 짜보자.

import gym
import numpy as np
import matplotlib.pyplot as plt

env = gym.make('FrozenLake-v0')

Q = np.zeros([env.observation_space.n, env.action_space.n])

learning_rate = .85
dis = .99
num_episodes = 2000

여태까지 했던 것과 동일하게 하는데 여기서는 따로 env의 register를 임포트해 설정을 바꿔주진 않는다. 기본적인 is_slippery=True이므로 Frozen Lake 환경을 만들면 stochastic한 환경으로 만들어진다.

또한 learning_rate가 추가 되었는데 이는 큐값을 업데이트할 때 쓰인다.

 

rList=[]
for i in  range(num_episodes):
    state = env.reset()
    rAll = 0
    done = False
    
    while not done:
        action = np.argmax(Q[state,  :] \
                           + np.random.randn(1, env.action_space.n)/(i+1))
        
        new_state, reward, done, _ = env.step(action)
        
        Q[state, action] = (1-learning_rate) * Q[state, action] \
            +learning_rate*(reward+ dis*np.max(Q[new_state, :]))
            
        rAll += reward
        state = new_state
    
    rList.append(rAll)

action을 선택할 때는 random noise를 사용하고 큐함수를 업데이트할 때는 위에서 봤던 learning_rate를 적용해 큐값을 업데이트한다. 이는 위에 있던 큐값을 업데이트하는 식을 그대로 코드로 쓴 것이다.

 

학습을 시킨 결과를 보니 대략 44%의 비율로 에이전트는 목표지점을 찾아갔다. 그렇게 높은 비율은 아니다.

 

이건 이번에 배운 learning_rate를 적용시킨 것이 아닌 이전의 큐함수 업데이트식을 그대로 사용한 것이다. 에이전트가 목표지점을 제대로 찾아갈  확률은 대략 3%정도로 매우 낮은 것을 볼 수 있다.

 

Reference:

[1]: http://hunkim.github.io/ml/

[2]: youtu.be/6KSf-j4LL-c

[3]: youtu.be/ZCumo_6qTsU