[강화학습] chatgpt랑 공부하는 강화학습: Q-learning, FrozenLake - 3
지난번까지는 학습 코드에 대해 살펴봤다. 이번 글에서는 학습이 끝난 agent가 어떻게 행동하는지 살펴보겠다.
우선 main함수를 다시 살펴보면
def main():
train_env = gym.make("FrozenLake-v1", map_name="4x4", is_slippery=True)
play_env = gym.make("FrozenLake-v1", map_name="4x4", is_slippery=True, render_mode="human")
q_table = train_on_frozen_lake(train_env) # 학습만 수행
play_trained_agent(play_env, q_table) # 학습된 q_table로 결과 보기
if __name__ == '__main__':
main()
와 같은데, train_env와 전부 똑같은데 render_mode만 "human"으로 되어 있다. render_mode에 따른 차이는 지난 글을 참고하면 된다.
main에서 play_trained_agent를 호출하는데, agent를 실행하고 실행 과정을 확인하는 코드는 아래와 같다.
def play_trained_agent(env, q_table):
state, _ = env.reset()
done = False
print("\n🚶 에이전트 경로:")
env.render()
time.sleep(0.05)
while not done:
action = np.argmax(q_table[state])
state, reward, terminated, truncated, _ = env.step(action)
done = terminated or truncated
# print(env.render())
env.render()
time.sleep(0.05)
env.close()
if reward == 1:
print("🎉 성공적으로 Goal 도달!")
else:
print("💥 실패! 구멍에 빠졌거나 종료됨")
실행결과를 확인할 환경(env)과 학습이 끝난 q_table을 입력으로 받아 q_table을 이용해 env안에서 action을 순서대로 실행한다.
while 문 안쪽은 학습 코드와 동일하다. 실제로 실행하면 결과는 아래와 같이 나타난다.
위와 같은 실행 결과를 동영상으로도 저장할 수 있다.
받은 코드:
from gymnasium.wrappers import RecordVideo
def main():
train_env = gym.make("FrozenLake-v1", map_name="4x4", is_slippery=True)
# 영상 저장용 환경: render_mode는 'rgb_array'
play_env = gym.make(
"FrozenLake-v1",
map_name="4x4",
is_slippery=True,
render_mode="rgb_array"
)
# 영상 녹화 래퍼 적용
play_env = RecordVideo(
play_env,
video_folder="./videos", # 저장 경로
name_prefix="frozenlake_final", # 파일 이름 prefix
episode_trigger=lambda x: True # 모든 실행 저장
)
q_table = train_on_frozen_lake(train_env)
play_trained_agent(play_env, q_table)
play_env.close() # 이게 호출되어야 영상 저장됨
위 코드로 메인함수를 수정하면 되는데, RecordVideo를 사용하려면 "pip install moviepy" 로 moviepy라는걸 설치해야 한다. 최초 에러메세지에는
gymnasium.error.DependencyNotInstalled: MoviePy is not installed, run
pip install "gymnasium[other]"
라고 나오는데, chatGPT가 pip install "gymnasium[other]" 를 하면 쓸데없는 패키지도 깔리니까 그냥 pip install moviepy 로 설치하라고 한다.
어쨋든, 필요한 패키지를 설치하고 아래 코드를 실행하면 학습 후 실행 결과가 동영상으로 저장이 된다. 1편에서 올렸던 코드와 달라진 점은 main함수 부분인데, 1편에서는 학습 결과를 바로 실행하여 확인할수 있고, 이 버전은 동영상으로 저장하는 버전이다.
최종 코드 (동영상으로 저장):
import gymnasium as gym
import numpy as np
import time
import matplotlib.pyplot as plt
from tqdm import tqdm
from gymnasium.wrappers import RecordVideo
def play_trained_agent(env, q_table):
state, _ = env.reset()
done = False
print("\n🚶 에이전트 경로:")
env.render()
time.sleep(0.05)
while not done:
action = np.argmax(q_table[state])
state, reward, terminated, truncated, _ = env.step(action)
done = terminated or truncated
# print(env.render())
env.render()
time.sleep(0.05)
env.close()
if reward == 1:
print("🎉 성공적으로 Goal 도달!")
else:
print("💥 실패! 구멍에 빠졌거나 종료됨")
def train_on_frozen_lake(env):
rewards = []
# 하이퍼파라미터 설정
alpha = 0.8 # 학습률 (learning rate)
gamma = 0.99 # 할인율
epsilon = 1.0 # 탐험 확률 (epsilon-greedy)
epsilon_min = 0.1
epsilon_decay = 0.9995
episodes = 10000 # 에피소드 수
# Q-테이블 초기화: 상태 수 x 행동 수
q_table = np.zeros([env.observation_space.n, env.action_space.n])
# 학습 루프
for _ in tqdm(range(episodes)):
state, _ = env.reset()
done = False
total_reward = 0
while not done:
# 행동 선택: 탐험 or 활용 (epsilon-greedy)
if np.random.uniform(0, 1) < epsilon:
action = env.action_space.sample() # 무작위 행동
else:
action = np.argmax(q_table[state])
# 환경에 행동 적용 -> 다음 상태, 보상, 종료 여부 등 받기
next_state, reward, terminated, truncated, _ = env.step(action)
done = terminated or truncated
# Q 테이블 업데이트
q_table[state, action] = q_table[state, action] + alpha * (
reward + gamma * np.max(q_table[next_state]) - q_table[state, action]
)
# 상태 업데이트
state = next_state
# epsilon 감소
if epsilon > epsilon_min:
epsilon *= epsilon_decay
total_reward += reward
rewards.append(total_reward)
# 학습 완료 후 Q 테이블 출력
print("Q-table")
print(q_table)
# 누적 성공률 (100 에피소드마다 평균)
window = 100
moving_avg = [np.mean(rewards[i - window:i + 1]) for i in range(window, len(rewards))]
plt.plot(moving_avg)
plt.title("🎯 Moving Average of Success Rate")
plt.xlabel("Episode")
plt.ylabel("Success Rate")
plt.grid(True)
plt.show()
return q_table
def main():
train_env = gym.make("FrozenLake-v1", map_name="4x4", is_slippery=True)
# 영상 저장용 환경: render_mode는 'rgb_array'
play_env = gym.make(
"FrozenLake-v1",
map_name="4x4",
is_slippery=True,
render_mode="rgb_array"
)
# 영상 녹화 래퍼 적용
play_env = RecordVideo(
play_env,
video_folder="./result_video", # 저장 경로
name_prefix="frozenlake_final", # 파일 이름 prefix
episode_trigger=lambda x: True # 모든 실행 저장
)
q_table = train_on_frozen_lake(train_env) # 학습만 수행
play_trained_agent(play_env, q_table) # 학습된 q_table로 결과 보기
play_env.close() # 이게 호출되어야 영상 저장됨
if __name__ == '__main__':
main()