12-6. 강화 학습 실습: OpenAI Gym 환경에서 학습

1. OpenAI Gym 환경 소개와 강화 학습 실습의 중요성

강화 학습은 에이전트가 환경과 상호작용하며 특정 목표를 달성하도록 학습하는 머신 러닝의 한 분야입니다. 에이전트는 환경으로부터 상태(state)를 관찰하고, 행동(action)을 선택하며, 그 결과로 보상(reward)을 받습니다. 이 과정을 반복하면서 에이전트는 보상을 최대화하는 방향으로 학습을 진행합니다.

강화 학습의 핵심은 환경(environment)에이전트(agent)의 상호작용입니다. 환경은 에이전트에게 상태를 제공하고, 에이전트의 행동에 따라 상태가 변하며 보상을 제공합니다. 에이전트는 이러한 환경과의 상호작용을 통해 최적의 정책(policy)을 학습합니다.

강화 학습을 실습하기 위한 환경은 매우 중요합니다. 다양한 환경을 제공하는 OpenAI Gym은 강화 학습 연구와 개발을 위한 대표적인 도구입니다. OpenAI Gym은 다양한 환경을 제공하며, 각 환경은 에이전트의 행동과 그에 따른 보상을 정의합니다. 이를 통해 연구자들은 다양한 강화 학습 알고리즘을 쉽게 구현하고 실험할 수 있습니다.

본 포스트에서는 OpenAI Gym 환경을 활용하여 강화 학습 알고리즘인 Q-LearningDeep Q-Network (DQN)을 실습하는 과정을 자세히 살펴보겠습니다. 이를 통해 강화 학습의 기본적인 개념을 이해하고, 실제 문제에 적용하는 능력을 키울 수 있습니다.

2. OpenAI Gym 환경 이해

OpenAI Gym은 다양한 환경을 제공하여 강화 학습 알고리즘의 개발과 평가를 용이하게 합니다. 각 환경은 특정 과제를 나타내며, 에이전트가 그 과제를 해결하도록 학습해야 합니다.

1) Gym 환경의 구성 요소

OpenAI Gym 환경은 다음과 같은 주요 요소로 구성됩니다.

  • State (상태): 환경의 현재 상태를 나타내는 정보입니다. 예를 들어, CartPole-v1 환경에서는 막대와 수레의 위치와 속도가 상태로 제공됩니다.
  • Action (행동): 에이전트가 환경에서 수행할 수 있는 행동의 집합입니다. CartPole-v1 환경에서는 수레를 왼쪽 또는 오른쪽으로 움직이는 두 가지 행동을 사용할 수 있습니다.
  • Reward (보상): 에이전트가 특정 행동을 수행한 결과로 받는 점수입니다. CartPole-v1 환경에서는 막대가 넘어지지 않고 유지되는 시간마다 +1의 보상을 받습니다.
  • Observation Space (관측 공간): 환경 상태의 형태(예: 숫자, 벡터)를 정의합니다.
  • Action Space (행동 공간): 가능한 행동의 형태(예: 이산형, 연속형)를 정의합니다.

2) Gym 환경 사용법

OpenAI Gym 환경을 사용하기 위해서는 먼저 해당 환경을 import하고 초기화해야 합니다. 그 후, 에이전트는 환경과 상호작용하며 학습을 진행합니다.

import gymnasium as gym

# 환경 생성
env = gym.make('CartPole-v1')

# 환경 초기화
state, info = env.reset()

# 에피소드 루프
for _ in range(1000):
    # 무작위 행동 선택 (예시)
    action = env.action_space.sample()

    # 행동 수행 및 다음 상태, 보상, 종료 여부 획득
    next_state, reward, terminated, truncated, info = env.step(action)

    # 환경 렌더링 (선택적)
    # env.render()
    state = next_state

    if terminated or truncated:
        state, info = env.reset()

env.close()

위 코드는 CartPole-v1 환경을 사용하여 에이전트가 환경과 상호작용하는 기본적인 예시를 보여줍니다.

  • gym.make('CartPole-v1')을 사용하여 CartPole-v1 환경을 생성합니다.
  • env.reset()을 사용하여 환경을 초기화하고 초기 상태를 얻습니다.
  • env.action_space.sample()을 사용하여 무작위 행동을 선택합니다.
  • env.step(action)을 사용하여 선택된 행동을 환경에 적용하고, 다음 상태, 보상, 종료 여부를 얻습니다.
  • terminated 또는 truncatedTrue이면 에피소드가 종료되므로 환경을 다시 초기화합니다.
  • env.close()를 사용하여 환경을 종료합니다.

3) 주요 Gym 환경 예시

OpenAI Gym은 다양한 환경을 제공하며, 각 환경은 다양한 도전 과제를 제시합니다. 몇 가지 예시는 다음과 같습니다.

  • CartPole-v1: 수레 위에 막대(pole)를 세우는 문제로, 막대가 넘어지지 않도록 수레를 움직여야 합니다.
  • MountainCar-v0: 언덕을 올라가는 자동차 문제로, 언덕의 반대쪽으로 움직여 언덕을 올라가야 합니다.
  • FrozenLake-v1: 얼음판 위에서 에이전트가 목표 지점까지 이동하는 문제로, 구멍에 빠지지 않도록 주의해야 합니다.

3. Q-Learning 알고리즘 실습

Q-Learning은 가치 기반 강화 학습 알고리즘 중 하나로, Q-value라는 가치 함수를 학습하여 최적의 정책을 결정합니다. Q-value는 특정 상태에서 특정 행동을 했을 때 얻을 수 있는 예상 누적 보상을 의미합니다.

1) Q-Learning의 핵심 개념

  • Q-value: 특정 상태 s에서 행동 a를 취했을 때의 예상 누적 보상, Q(s, a)로 표기합니다.
  • Q-table: 모든 상태-행동 쌍에 대한 Q-value를 저장하는 테이블입니다.
  • Bellman Equation: Q-value를 업데이트하기 위한 핵심 수식입니다. $$ Q(s, a) \leftarrow Q(s, a) + \alpha [r + \gamma \max_{a'} Q(s', a') - Q(s, a)] $$
    • $\alpha$: 학습률 (learning rate), 0과 1 사이의 값으로, 새로운 정보를 얼마나 반영할지 결정합니다.
    • $r$: 즉시 보상 (immediate reward)
    • $\gamma$: 할인율 (discount factor), 0과 1 사이의 값으로, 미래 보상의 중요도를 결정합니다.
    • $s'$: 다음 상태 (next state)
    • $a'$: 다음 상태에서 최적의 행동

2) Q-Learning 알고리즘 구현

Q-Learning 알고리즘을 구현하는 과정은 다음과 같습니다.

  1. Q-table 초기화: 모든 상태-행동 쌍에 대한 Q-value를 0으로 초기화합니다.
  2. 에피소드 반복: 각 에피소드에서 다음과 같은 과정을 반복합니다.
    • 상태 초기화: 환경을 초기화하고 초기 상태를 얻습니다.
    • 행동 선택: 현재 상태에 따라 행동을 선택합니다. (예: $\epsilon$-greedy)
    • 행동 수행: 선택된 행동을 환경에 적용하고 다음 상태, 보상, 종료 여부를 얻습니다.
    • Q-value 업데이트: Bellman Equation을 사용하여 Q-table을 업데이트합니다.
    • 다음 상태로 이동: 현재 상태를 다음 상태로 변경합니다.
  3. 학습 종료: 지정된 에피소드 횟수만큼 반복하거나, 특정 조건이 충족되면 학습을 종료합니다.

3) CartPole-v1 환경에서의 Q-Learning 실습

CartPole-v1 환경에서 Q-Learning 알고리즘을 실습해 보겠습니다.

a. 환경 설정 및 Q-table 초기화
import gymnasium as gym
import numpy as np

# 환경 생성
env = gym.make('CartPole-v1')
state_space = env.observation_space.shape[0]  # 상태 공간 차원
action_space = env.action_space.n  # 행동 공간 크기

# 하이퍼파라미터 설정
learning_rate = 0.1
discount_factor = 0.95
epsilon = 1.0  # 탐험률
epsilon_decay_rate = 0.999
epsilon_min = 0.01
num_episodes = 2000

# Q-table 초기화 (상태 공간을 이산화)
num_buckets = (1, 1, 6, 3) # 각 상태 변수를 몇 개의 구간으로 나눌지 설정
q_table = np.zeros(num_buckets + (action_space,))

# 상태 공간 이산화 함수
def discretize_state(state):
    env_low = env.observation_space.low
    env_high = env.observation_space.high
    state_range = env_high - env_low
    state_scaled = (state - env_low) / state_range
    state_scaled = np.clip(state_scaled, 0, 1) # 0과 1 사이로 값 고정
    state_discrete = np.floor(state_scaled * np.array(num_buckets)).astype(int)
    return tuple(state_discrete)
  • gym.make('CartPole-v1')을 사용하여 CartPole-v1 환경을 생성합니다.
  • state_spaceaction_space를 사용하여 상태 공간과 행동 공간의 크기를 얻습니다.
  • learning_rate, discount_factor, epsilon, epsilon_decay_rate, epsilon_min, num_episodes와 같은 하이퍼파라미터를 설정합니다.
  • q_table을 초기화합니다. (CartPole-v1은 연속적인 상태 공간을 가지므로 상태 공간을 이산화해야 합니다.)
b. $\epsilon$-greedy 정책 정의
# epsilon-greedy 정책
def epsilon_greedy_policy(state):
    if np.random.random() < epsilon:
        return env.action_space.sample()  # 탐험
    else:
        return np.argmax(q_table[state])  # 활용
  • epsilon_greedy_policy 함수는 $\epsilon$-greedy 정책을 구현합니다.
  • $\epsilon$ 확률로 무작위 행동을 선택하고, $1 - \epsilon$ 확률로 현재 Q-value가 가장 높은 행동을 선택합니다.
c. Q-Learning 알고리즘 구현 및 학습
# Q-learning 학습 루프
for episode in range(num_episodes):
    state, info = env.reset()
    state_discrete = discretize_state(state) # 상태를 이산화
    done = False
    truncated = False

    while not done and not truncated:
        # 행동 선택
        action = epsilon_greedy_policy(state_discrete)

        # 행동 수행 및 다음 상태, 보상, 종료 여부 획득
        next_state, reward, terminated, truncated, info = env.step(action)
        next_state_discrete = discretize_state(next_state)  # 다음 상태 이산화

        # Q-value 업데이트 (Bellman Equation)
        q_table[state_discrete + (action,)] += learning_rate * (reward + discount_factor * np.max(q_table[next_state_discrete]) - q_table[state_discrete + (action,)])

        # 다음 상태로 이동
        state_discrete = next_state_discrete

        done = terminated
    # epsilon 감소 (탐험 감소)
    epsilon = max(epsilon * epsilon_decay_rate, epsilon_min)

    if episode % 100 == 0:
      print(f"Episode {episode}, Epsilon: {epsilon}")

env.close()
  • 각 에피소드에서 환경을 초기화하고 초기 상태를 얻습니다.
  • while 루프를 사용하여 에피소드가 종료될 때까지 반복합니다.
  • epsilon_greedy_policy를 사용하여 행동을 선택합니다.
  • 선택된 행동을 환경에 적용하고 다음 상태, 보상, 종료 여부를 얻습니다.
  • Bellman Equation을 사용하여 Q-table을 업데이트합니다.
  • 다음 상태로 이동합니다.
  • epsilon 값을 감소시켜 탐험의 비중을 줄여나갑니다.
  • 학습 과정을 모니터링하기 위해 에피소드 진행 상황을 출력합니다.
d. 학습된 Q-Learning 에이전트 평가
# 학습된 에이전트 평가
env = gym.make('CartPole-v1', render_mode="human") # 렌더링 모드 설정
state, info = env.reset()
state_discrete = discretize_state(state)
done = False
truncated = False
total_reward = 0

while not done and not truncated:
    action = np.argmax(q_table[state_discrete])  # 최적의 행동 선택
    next_state, reward, terminated, truncated, info = env.step(action)
    state_discrete = discretize_state(next_state)
    total_reward += reward
    done = terminated
    env.render() # 환경 렌더링

print(f"Total reward: {total_reward}")
env.close()
  • 학습된 Q-table을 사용하여 에이전트의 성능을 평가합니다.
  • render_mode="human" 옵션을 사용하여 에이전트의 행동을 시각적으로 확인할 수 있습니다.
  • 최적의 행동을 선택하고 환경과 상호작용하며, 총 보상을 계산합니다.
  • 평가 결과를 출력합니다.

Q-Learning 알고리즘 설명 뒤

4. Deep Q-Network (DQN) 알고리즘 실습

Q-Learning은 Q-table을 사용하여 가치를 저장하기 때문에 상태 공간이 커지면 (예: 이미지 입력) 학습이 어려워집니다. DQN은 딥러닝 모델(신경망)을 사용하여 Q-value를 근사함으로써 이 문제를 해결합니다.

1) DQN의 핵심 개념

  • Q-Network: 입력 상태를 받아 각 행동에 대한 Q-value를 출력하는 심층 신경망입니다.
  • Experience Replay: 에이전트가 경험한 데이터를 저장하고, 무작위로 샘플링하여 학습에 사용합니다. 이렇게 하면 데이터의 상관관계를 줄이고 학습 효율을 높일 수 있습니다.
  • Target Network: 학습의 안정성을 위해 Q-Network과 동일한 구조를 가지지만, 학습 파라미터를 주기적으로 복사하여 사용합니다.

2) DQN 알고리즘 구현

DQN 알고리즘을 구현하는 과정은 다음과 같습니다.

  1. Q-Network, Target Network 초기화: 입력과 출력의 크기를 환경에 맞게 설정한 딥러닝 모델을 정의합니다. Target Network는 Q-Network과 동일한 구조로 초기화합니다.
  2. Experience Replay Buffer 초기화: 경험을 저장할 버퍼를 초기화합니다.
  3. 에피소드 반복: 각 에피소드에서 다음과 같은 과정을 반복합니다.
    • 상태 초기화: 환경을 초기화하고 초기 상태를 얻습니다.
    • 행동 선택: 현재 상태를 Q-Network에 입력하여 Q-value를 예측하고, $\epsilon$-greedy 정책을 사용하여 행동을 선택합니다.
    • 행동 수행: 선택된 행동을 환경에 적용하고 다음 상태, 보상, 종료 여부를 얻습니다.
    • 경험 저장: (현재 상태, 행동, 보상, 다음 상태, 종료 여부)를 Experience Replay Buffer에 저장합니다.
    • 미니 배치 샘플링: Experience Replay Buffer에서 무작위로 미니 배치를 샘플링합니다.
    • Q-Network 학습: 미니 배치를 사용하여 Q-Network을 학습합니다. (손실 함수: MSE, Optimizer: Adam 등)
    • Target Network 업데이트: (일정 간격 또는 에피소드마다) Q-Network의 파라미터를 Target Network에 복사합니다.
  4. 학습 종료: 지정된 에피소드 횟수만큼 반복하거나, 특정 조건이 충족되면 학습을 종료합니다.

3) CartPole-v1 환경에서의 DQN 실습

CartPole-v1 환경에서 DQN 알고리즘을 실습해 보겠습니다.

a. 환경 설정 및 DQN 모델 정의
import gymnasium as gym
import numpy as np
import tensorflow as tf
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense
from tensorflow.keras.optimizers import Adam
from collections import deque
import random

# 환경 생성
env = gym.make('CartPole-v1')
state_space = env.observation_space.shape[0]  # 상태 공간 차원
action_space = env.action_space.n  # 행동 공간 크기

# 하이퍼파라미터 설정
learning_rate = 0.001
discount_factor = 0.99
epsilon = 1.0  # 탐험률
epsilon_decay_rate = 0.995
epsilon_min = 0.01
batch_size = 32
memory_size = 2000
target_update_frequency = 50
num_episodes = 500

# DQN 모델 정의
model = Sequential([
    Dense(64, activation='relu', input_shape=(state_space,)),
    Dense(action_space)  # 출력층: 각 행동에 대한 Q-value
])

# Target network 정의 (Q-network와 동일한 구조)
target_model = tf.keras.models.clone_model(model)
target_model.set_weights(model.get_weights())  # 초기 가중치 설정

# Optimizer 설정
optimizer = Adam(learning_rate=learning_rate)

# Experience replay buffer
memory = deque(maxlen=memory_size)
  • TensorFlow 및 Keras를 사용하여 DQN 모델을 정의합니다.
  • model은 Q-Network를 나타내며, Dense 레이어를 사용하여 상태를 Q-value로 매핑합니다.
  • target_model은 Target Network로, Q-Network의 가중치를 주기적으로 복사하여 사용합니다.
  • Adam 옵티마이저를 사용하여 모델을 학습합니다.
  • memory는 Experience Replay Buffer를 나타냅니다.
b. $\epsilon$-greedy 정책, Experience Replay, Target Network 업데이트 함수 정의
# epsilon-greedy 정책
def epsilon_greedy_policy(state, epsilon):
    if np.random.random() < epsilon:
        return env.action_space.sample()  # 탐험
    else:
        q_values = model.predict(np.array([state]), verbose=0)
        return np.argmax(q_values[0])  # 활용

# Experience Replay
def remember(state, action, reward, next_state, done):
    memory.append((state, action, reward, next_state, done))

# Target Network 업데이트
def update_target_model():
    target_model.set_weights(model.get_weights())
  • epsilon_greedy_policy 함수는 $\epsilon$-greedy 정책을 구현합니다.
  • remember 함수는 경험을 Experience Replay Buffer에 저장합니다.
  • update_target_model 함수는 Q-Network의 가중치를 Target Network에 복사합니다.
c. DQN 알고리즘 구현 및 학습
# DQN 학습 루프
for episode in range(num_episodes):
    state, info = env.reset()
    done = False
    total_reward = 0

    while not done:
        # 행동 선택
        action = epsilon_greedy_policy(state, epsilon)

        # 행동 수행 및 다음 상태, 보상, 종료 여부 획득
        next_state, reward, terminated, truncated, info = env.step(action)
        done = terminated or truncated
        total_reward += reward

        # 경험 저장
        remember(state, action, reward, next_state, done)

        state = next_state

        if done:
            break

    # Experience Replay 및 학습
    if len(memory) > batch_size:
        # 미니 배치 샘플링
        minibatch = random.sample(memory, batch_size)
        states, actions, rewards, next_states, dones = zip(*minibatch)

        # Q-value 계산
        states = np.array(states)
        next_states = np.array(next_states)

        q_values = model.predict(states, verbose=0)
        future_q_values = target_model.predict(next_states, verbose=0) # Target network 사용

        # 손실 계산
        for i in range(batch_size):
            if dones[i]: # 에피소드가 종료된 경우
                q_values[i][actions[i]] = rewards[i]
            else:
                q_values[i][actions[i]] = rewards[i] + discount_factor * np.max(future_q_values[i])

        # 모델 학습
        with tf.GradientTape() as tape:
            predicted_q_values = model(states)
            loss = tf.keras.losses.MSE(q_values, predicted_q_values)
        gradients = tape.gradient(loss, model.trainable_variables)
        optimizer.apply_gradients(zip(gradients, model.trainable_variables))

    # Target Network 업데이트 (주기적으로)
    if episode % target_update_frequency == 0:
        update_target_model()

    # epsilon 감소
    epsilon = max(epsilon * epsilon_decay_rate, epsilon_min)

    if episode % 10 == 0:
        print(f"Episode: {episode}, Reward: {total_reward:.2f}, Epsilon: {epsilon:.2f}")

env.close()
  • 각 에피소드에서 환경을 초기화하고 초기 상태를 얻습니다.
  • while 루프를 사용하여 에피소드가 종료될 때까지 반복합니다.
  • epsilon_greedy_policy를 사용하여 행동을 선택합니다.
  • 선택된 행동을 환경에 적용하고 다음 상태, 보상, 종료 여부를 얻습니다.
  • 경험을 Experience Replay Buffer에 저장합니다.
  • Experience Replay Buffer의 크기가 batch_size보다 크면 미니 배치를 샘플링하고, Q-Network을 학습합니다.
  • Target Network를 주기적으로 업데이트합니다.
  • epsilon 값을 감소시켜 탐험의 비중을 줄여나갑니다.
  • 학습 과정을 모니터링하기 위해 에피소드 진행 상황을 출력합니다.
d. 학습된 DQN 에이전트 평가
# 학습된 에이전트 평가
env = gym.make('CartPole-v1', render_mode="human")
state, info = env.reset()
done = False
truncated = False
total_reward = 0

while not done and not truncated:
    q_values = model.predict(np.array([state]), verbose=0)
    action = np.argmax(q_values[0])
    next_state, reward, terminated, truncated, info = env.step(action)
    state = next_state
    total_reward += reward
    done = terminated

    env.render()

print(f"Total reward: {total_reward}")
env.close()
  • 학습된 DQN 모델을 사용하여 에이전트의 성능을 평가합니다.
  • render_mode="human" 옵션을 사용하여 에이전트의 행동을 시각적으로 확인할 수 있습니다.
  • 최적의 행동을 선택하고 환경과 상호작용하며, 총 보상을 계산합니다.
  • 평가 결과를 출력합니다.

5. 실습 결과 분석 및 개선 방향

1) Q-Learning 및 DQN 실습 결과 비교

  • Q-Learning은 비교적 간단한 알고리즘이지만, 상태 공간이 커지면 학습이 어려워지는 단점이 있습니다. CartPole-v1과 같이 작은 상태 공간에서는 비교적 빠르게 학습할 수 있습니다.
  • DQN은 딥러닝 모델을 사용하므로, 복잡한 환경에서도 학습이 가능합니다. Experience Replay와 Target Network를 통해 학습 안정성을 높일 수 있습니다. 하지만, Q-Learning보다 더 많은 하이퍼파라미터 튜닝이 필요합니다.

2) 성능 개선 방법

  • 하이퍼파라미터 튜닝: 학습률, 할인율, 탐험률, 배치 크기 등 다양한 하이퍼파라미터를 조정하여 성능을 개선할 수 있습니다.
  • 신경망 구조 변경: Q-Network의 구조(레이어 수, 은닉 유닛 수, 활성화 함수 등)를 변경하여 성능을 개선할 수 있습니다.
  • Exploration-exploitation trade-off 조절: $\epsilon$-greedy 정책에서 $\epsilon$ 값의 감소 속도를 조절하여 탐험과 활용의 균형을 맞출 수 있습니다.
  • Reward shaping: 보상 함수를 조정하여 학습을 더 효율적으로 만들 수 있습니다.

3) 추가적인 고려 사항

  • 환경 선택: 다양한 OpenAI Gym 환경을 사용하여 다양한 강화 학습 알고리즘을 실험해 볼 수 있습니다.
  • 알고리즘 비교: Q-Learning, DQN 외에도 다른 강화 학습 알고리즘(예: Policy Gradient)을 구현하고 비교해 볼 수 있습니다.
  • 실제 문제 적용: 실제 문제에 강화 학습을 적용하기 위해서는 문제에 맞는 환경을 구축하고, 적절한 알고리즘을 선택해야 합니다.

6. 결론

본 포스트에서는 OpenAI Gym 환경을 활용하여 Q-Learning과 DQN 알고리즘을 실습하는 과정을 자세히 살펴보았습니다. 강화 학습의 기본적인 개념과 각 알고리즘의 원리를 이해하고, CartPole-v1 환경에서 직접 구현해 보면서 실제 문제에 적용하는 경험을 쌓았습니다.

강화 학습은 끊임없이 발전하는 분야이며, OpenAI Gym은 이러한 발전을 뒷받침하는 중요한 도구입니다. 앞으로도 다양한 환경과 알고리즘을 활용하여 강화 학습에 대한 이해를 넓히고, 실제 문제 해결에 기여할 수 있기를 바랍니다.

비슷한 글 추천

Comments (0)

No comments yet. Be the first to comment!