강화학습/OpenAI gym

OpenAI gym을 이용해 PolicyIteration 구현하기

APinCan 2020. 3. 8. 14:32

OpenAI gym의 FrozenLake-v0를 이용해 PolicyIteration을 구현해보자

 

 

import gym
import numpy as np

GAMMA=0.9
THRESHOLD = 1e-10
INIT_POLICY=[0.25,0.25,0.25,0.25]
EPSIODE = 100

일단 다음과 같이 선언함

감가율인 감마는 0.9로

업데이트하기 전의 가치함수와 업데이트 후의 가치함수를 비교해 임계값보다 같거나 낮으면 반복 중단

각 상태의 초기 정책은 모두 동일하게 설정

 

 

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

다음으로 환경을 만들자

 

 

# 현재 정책에 대한 참 가치함수를 리턴
def policy_evaluation(env, value_func, policy):
    after_value_func = np.copy(value_func)
    
    for t in range(1000):
        for state in range(env.observation_space.n):
            state_value = 0
            
            for action in range(env.action_space.n):
                q_value = 0
                
                for state_st in env.P[state][action]:
                    trans_prob, next_state, reward, _ = state_st
                    q_value += trans_prob*(reward + GAMMA*value_func[next_state])
                
                state_value += policy[state][action]*q_value
            
            after_value_func[state] = state_value
        
        # 모든 state에 대해서 계산 한번 끝냄  
        # 타임스텝이 조기 종료되는 조건, 큰 차이가 없는 경우
        if np.sum(np.fabs(value_func - after_value_func)) <= THRESHOLD:
            print('complete timestep t={}'.format(t+1))
            break
        
        value_func = np.copy(after_value_func)
        
    return value_func

정책 평가과정의 코드.

현재 정책과 가치함수 그리고 환경을 인자로 줘서 현재 정책에 대한 참 가치함수를 구해냄

모든 상태에 대해서 가치함수를 구하는게 한번의 타임스텝이고 이걸 계속 반복하는 거임. 그리고 중간에 이전의 가치함수와 업데이트한 가치함수의 차이가 별로 없다면 반복을 break로 조기 종료시킴

 

참고로 FrozenLake는 확률적인 환경인 듯. 그래서 env.P[state][action]으로 갈 수 있는 다른 상태들에 대해서 모두 계산을 함

계산을 할때는 벨만방정식을 사용해 계산

 

 

def policy_exploitation(env, value_func, policy):
    for state in range(env.observation_space.n):
        near_value = []
        new_policy = [0, 0, 0, 0]

        for action in range(env.action_space.n):
            q_value = 0
            
            for state_st in env.P[state][action]:
                trans_prob, next_state, reward, _ = state_st
                q_value += trans_prob*(reward + GAMMA*value_func[next_state])
            
            # 주변 q함수들 비교
            near_value.append(q_value)
        
        greedy_action = np.argmax(near_value)
        new_policy[greedy_action] = 1
        
        policy[state] = new_policy
        
    return policy

그 다음으로 계산한 참 가치함수를 가지고 새롭게 정책을 계산하는 정책 발전부분

앞이랑 별차이는 없는데 앞에서 계산한 가치함수를 기반으로 삼음

 

 

value_func = np.zeros(env.observation_space.n)
policy = [INIT_POLICY for i in range(env.observation_space.n)]

for epi in range(EPISODE):
    true_value_func = policy_evaluation(env, value_func, policy)
    policy = policy_exploitation(env, true_value_func, policy)
    
    if np.sum(np.fabs(true_value_func - value_func)) <= THRESHOLD:
        break
    
    value_func = true_value_func

 

가치함수와 정책을 초기화하고 최적 정책을 찾을때까지 루프를 돌게함

여기서도 비슷하게 이전 가치함수와 업데이트된 가치함수를 비교해서 break

 

 

69+157 = 226스텝만에 최적 정책을 찾아갔음을 알 수 있음(t=1은 제외)

 

그때의 참 가치함수는 다음과 같음

 

그리고 최적 정책까지 찾았음, 총 16개의 행으로 각 상태마다 선택해야하는 action들임

 

 

 

Reference

파이썬 예제와 함께하는 강화학습

파이썬과 케라스로 배우는 강화학습