안녕하세요! 오늘은 gymnasium에서 제공하는 frozen lake 문제에 대한 설명에 대해 포스팅 하겠습니다.
- 강화 학습이란?
행동을 통해 얻는 보상을 기반으로 학습하는 AI의 한 분야입니다.
흔히 Reinforcement Learning 줄여서, RL이라고 부르는 강화 학습은 컴퓨터가 스스로 경험을 쌓으면서 어떤 행동이 가장 좋은 보상을 얻는지 배우는 과정이라고 볼 수 있습니다.
저는 frozen lake 문제를 Q-learning과 SARSA 두 가지 방법으로 풀어보았는데요!
각각 전체 코드는 포스팅 가장 아래에 있습니다.
- frozen lake 규칙
우선 gymnasium에서 제공하는 frozen lake 문제는 아래 링크에서 자세하게 보실 수 있습니다.
https://gymnasium.farama.org/environments/toy_text/frozen_lake/
Gymnasium Documentation
A standard API for reinforcement learning and a diverse set of reference environments (formerly Gym)
gymnasium.farama.org
frozen lake의 기본 맵은 아래 사진처럼 생겼습니다.
- frozen lake의 기본 맵은 4x4 혹은 8x8로 존재
- 맵 내 구멍이 존재
→ 구멍의 수나 위치는 조절할 수 없음 - 선물에 있는 곳에 도착하거나, 구멍에 빠지면 에피소드 종료
→ 선물에 있는 곳에 도착해야만 보상 1을 획득할 수 있음 - 움직임은 상, 하, 좌, 우 존재
- 얼음 내 미끄러짐을 키고 끌 수 있음
→ 미끄러짐을 킬 경우, 각 얼음마다 특정 확률로 다른 곳으로 움직이는 확률이 존재
→ 각 얼음마다 존재하는 미끄러질 확률을 조절할 수 없음
저희는 위의 규칙을 잘 생각하여, 구멍에 빠지지 않고 선물에 도착하는 경로를 학습해주어야 합니다.
- 필요한 라이브러리 설치
frozen lake는 gymnasium에서 제공하고 있기 때문에 가장 먼저 gymnasium을 설치해주시면 됩니다!
그리고 render 모드 활성화를 진행하기 위해 gymnasium[toy-text] 설치도 같이 진행해주세요.
두 패키지 모두 pip install로 설치해주시면 금방 설치할 수 있습니다.
import gymnasium as gym
from collections import defaultdict
import numpy as np
- frozen lake 환경 세팅
필요한 라이브러리를 설치한 후에는 frozen lake 환경을 세팅해봅니다.
우선 환경 세팅을 하는 코드는 아래와 같습니다.
# 미끄러지는 얼음을 만들지 결정하는 변수
is_slippery = False
# 맵 사이즈
map_size = '4x4'
# frozen lake 환경 설정
# render 활성화 환경
env = gym.make('FrozenLake-v1', desc=None, map_name=map_size, is_slippery=is_slippery, render_mode='human')
# 환경을 초기화하는 함수
env.reset()
env.reset()의 경우 기본 기능은 환경을 초기화하는 함수지만, 환경을 세팅한 다음에 해당 코드를 부르지 않으면 오류가 발생하니 반드시 환경 사용 전에 env.reset()을 먼저 불러주세요!
- frozen lake 테스트 진행하기
이제 만든 환경을 바탕으로 gymnasium에서 제공하는 frozen lake 테스트를 진행해봅시다!
테스트를 진행하는 코드는 아래와 같습니다.
while True:
# 0 : 왼쪽, 1 : 아래, 2 : 오른쪽, 3 : 위
action = input("이동할 방향: ")
if action not in ['0','1','2','3']:
continue
action = int(action)
# step() : 환경에 액션을 넣고 실행하는 함수
state, reward, done, info, prob = env.step(action)
print("위치: ", state, "행동: ", action, "보상: ", reward)
print()
if done:
print("에피소드 종료", reward)
break
해당 코드를 실행해보면, 4x4 맵이 있는 창에 입력한 행동대로 움직이는 것을 확인할 수 있습니다.
구멍에 빠지거나 선물에 도착하기 전에는 계속 움직일 수 있으니, 환경을 이해하기 위해 편하게 테스트 진행해보세요!
맵을 키우거나 미끄러지는 얼음을 키고 테스트 해보시는 것도 추천드립니다.
여기까지가 frozen lake 환경 세팅이었습니다.
이번 포스팅에서는 Q-learning과 SARSA에 관한 model-free 전체 코드만 업로드 되어 있습니다.
두 가지 모두 is_slippery가 False일 경우에는 1.0 만점을 받았고, is_silppery가 True일 경우에는 0.8 이상의 보상을 획득했습니다.
Q-learning에 관한 자세한 내용이 궁금하신 분들은 아래 링크에서 확인해주세요!
https://yhj9855.com/entry/RL-gymnasium-frozen-lake-%EA%B0%95%ED%99%94-%ED%95%99%EC%8A%B5-2
[RL] gymnasium frozen lake 강화 학습 - 2
안녕하세요! 오늘은 기존에 작성한 frozen lake 문제를 Q-learning으로 진행하는 방법에 대해 포스팅 하겠습니다. Q-learning이란?강화 학습의 한 방법으로, Q라는 테이블을 이용하는 것입니다.Q 테이블
yhj9855.com
SARSA에 관한 자세한 내용이 궁금하진 분들은 아래 링크에서 확인해주세요!
https://yhj9855.com/entry/RL-gymnasium-frozen-lake-%EA%B0%95%ED%99%94-%ED%95%99%EC%8A%B5-SARSA
[Q-learning 전체 코드]
import gymnasium as gym
from collections import defaultdict
import numpy as np
is_slippery = True
map_size = '8x8'
env = gym.make('FrozenLake-v1', desc=None, map_name=map_size, is_slippery=is_slippery)
env.reset()
action_size = env.action_space.n
Q = defaultdict(lambda: np.zeros(action_size))
alpha = 0.1
gamma = 0.99
epsilon = 1.0
train = True
max_episode = 100000
def select_action(state) :
if np.random.rand() < epsilon and train :
action = np.random.choice([0, 1, 2, 3])
else :
action = np.argmax(Q[state])
return action
def learn() :
global epsilon
reward_list = []
for i in range(1, max_episode+1) :
# 100번째 마다 학습이 진행되고 있음을 출력
if i % 100 == 0 :
# 해당 에피소드까지 진행된 모든 보상의 평균을 구함
avg_reward = sum(reward_list)/100
print("\rEpisode {}/{} || average reward {}".format(i, max_episode, avg_reward), end="")
reward_list = []
# 에피소드를 처음 시작할 때는 reset을 해줘야 함
state, _ = env.reset()
done = False
all_reward = 0
# 에피소드가 종료될 때까지 반복
while not done :
action = select_action(state)
new_state, reward, done, _, _ = env.step(action)
# Q 러닝
Q[state][action] = (1-alpha)*Q[state][action] + alpha*(reward + gamma*np.max(Q[new_state]))
all_reward += reward
state = new_state
if i % 50 == 0 :
epsilon *= 0.99
reward_list.append(all_reward)
def testing_after_learning():
env = gym.make('FrozenLake-v1', desc=None, map_name=map_size, is_slippery=is_slippery, render_mode='human')
total_test_episode = 10
rewards = []
for episode in range(total_test_episode):
state, _ = env.reset()
episode_reward = 0
while True:
action = select_action(state)
new_state, reward, done, _, _ = env.step(action)
episode_reward += reward
if done:
rewards.append(episode_reward)
break
state = new_state
print("")
print("avg: " + str(sum(rewards) / total_test_episode))
if __name__ == "__main__" :
learn()
testing_after_learning()
결과물
[SARSA 전체 코드]
import gymnasium as gym
from collections import defaultdict
import numpy as np
is_slippery = True
map_size = '4x4'
env = gym.make('FrozenLake-v1', desc=None, map_name=map_size, is_slippery=is_slippery)
env.reset()
action_size = env.action_space.n
Q = defaultdict(lambda: np.zeros(action_size))
alpha = 0.1
gamma = 0.99
epsilon = 1.0
train = True
max_episode = 100000
def select_action(state) :
if np.random.rand() < epsilon and train :
action = np.random.choice([0, 1, 2, 3])
else :
action = np.argmax(Q[state])
return action
def learn() :
global epsilon
reward_list = []
for i in range(1, max_episode+1) :
# 100번째 마다 학습이 진행되고 있음을 출력
if i % 100 == 0 :
# 해당 에피소드까지 진행된 모든 보상의 평균을 구함
avg_reward = sum(reward_list)/100
print("\rEpisode {}/{} || average reward {}".format(i, max_episode, avg_reward), end="")
reward_list = []
# 에피소드를 처음 시작할 때는 reset을 해줘야 함
state, _ = env.reset()
done = False
all_reward = 0
# 에피소드가 종료될 때까지 반복
while not done :
action = select_action(state)
new_state, reward, done, _, _ = env.step(action)
next_action = select_action(new_state)
# SARSA
Q[state][action] = (1-alpha)*Q[state][action] + alpha*(reward + gamma*Q[new_state][next_action])
all_reward += reward
state = new_state
if i % 50 == 0 :
epsilon *= 0.99
reward_list.append(all_reward)
def testing_after_learning():
env = gym.make('FrozenLake-v1', desc=None, map_name=map_size, is_slippery=is_slippery, render_mode='human')
total_test_episode = 10
rewards = []
for episode in range(total_test_episode):
state, _ = env.reset()
episode_reward = 0
while True:
action = select_action(state)
new_state, reward, done, _, _ = env.step(action)
episode_reward += reward
if done:
rewards.append(episode_reward)
break
state = new_state
print("")
print("avg: " + str(sum(rewards) / total_test_episode))
if __name__ == "__main__" :
learn()
testing_after_learning()
결과물
코드에 궁금한 부분이 있으신 분들은 댓글로 남겨주시면, 답변 드리도록 하겠습니다.

★읽어주셔서 감사합니다★
'Python(파이썬) > RL (강화 학습)' 카테고리의 다른 글
[RL] gymnasium cart pole 강화 학습 - 1 (0) | 2025.02.18 |
---|---|
[RL] gymnasium frozen lake 강화 학습 - SARSA (1) | 2025.02.11 |
[RL] gymnasium frozen lake 강화 학습 - 2 (2) | 2025.02.03 |