본문 바로가기
프로그래밍/딥러닝 (완)

탐험 vs 활용 딜레마와 ε-greedy 전략 (50)

by 서가_ 2025. 5. 19.
반응형

탐험 vs 활용 딜레마와 ε-greedy 전략

강화학습에서 가장 근본적이면서도 중요한 문제 중 하나는 탐험(Exploration)과 활용(Exploitation) 사이의 균형을 맞추는 것입니다. 이번 포스팅에서는 이 딜레마가 무엇인지, 그리고 이를 해결하는 대표적인 방법인 ε-greedy 전략에 대해 자세히 알아보겠습니다.

 

탐험 vs 활용 딜레마란?

기본 개념

  • 탐험(Exploration): 아직 덜 알려진 행동이나 상태를 시도하여 새로운 정보를 얻는 과정
  • 활용(Exploitation): 현재까지 학습한 지식을 바탕으로 최선이라고 생각되는 행동을 선택하는 과정

딜레마의 핵심

에이전트는 매 순간 다음 중 하나를 선택해야 합니다:

  1. 지금까지 알고 있는 최선의 행동을 수행 → 즉각적인 보상 최대화
  2. 아직 시도해보지 않은 새로운 행동을 시도 → 더 나은 장기적 해법 발견 가능성

현실에서의 탐험 vs 활용

일상적인 예시

레스토랑 선택 문제

  • 활용: 항상 좋아하는 단골 레스토랑 방문 → 확실한 만족도
  • 탐험: 새로운 레스토랑 시도 → 더 맛있는 곳을 발견할 수도 있지만 실망할 수도 있음

투자 포트폴리오

  • 활용: 이미 수익을 내고 있는 안전한 투자처에 집중
  • 탐험: 새로운 투자 기회 탐색으로 더 높은 수익률 추구

비즈니스에서의 응용

  • A/B 테스트: 기존 방법 vs 새로운 방법
  • 추천 시스템: 사용자가 좋아하는 콘텐츠 vs 새로운 콘텐츠 추천
  • 광고 최적화: 성과가 입증된 광고 vs 새로운 광고 시도

ε-greedy 전략

ε-greedy는 이 딜레마를 해결하는 가장 간단하면서도 효과적인 방법 중 하나입니다.

기본 원리

ε-greedy 전략은 다음과 같이 작동합니다:

  • 확률 ε로 무작위 행동 선택 (탐험)
  • 확률 (1-ε)로 현재 최적 행동 선택 (활용)

수학적 정의

ε-greedy 정책은 다음과 같이 정의됩니다:

$$\pi(a\mid s) = \begin{cases}
\frac{\varepsilon}{|A|}, & \text{임의 행동 선택 with probability } \varepsilon \
1-\varepsilon + \frac{\varepsilon}{|A|}, & \text{최적 행동 선택 with probability } 1-\varepsilon
\end{cases}$$

여기서 |A|는 가능한 행동의 개수입니다.

예시 코드

import numpy as np

def epsilon_greedy_action(q_values, epsilon):
    """
    ε-greedy 정책에 따른 행동 선택

    Args:
        q_values: 각 행동의 Q-값 (배열)
        epsilon: 탐험 확률

    Returns:
        선택된 행동의 인덱스
    """
    if np.random.random() < epsilon:
        # 무작위 행동 선택 (탐험)
        return np.random.randint(len(q_values))
    else:
        # 최고 Q-값을 가진 행동 선택 (활용)
        return np.argmax(q_values)

# 사용 예시
q_values = [0.1, 0.5, 0.3, 0.8]  # 4개 행동의 Q-값
epsilon = 0.1  # 10% 확률로 탐험

chosen_action = epsilon_greedy_action(q_values, epsilon)
print(f"선택된 행동: {chosen_action}")

ε-greedy의 장단점

장점

  1. 구현 간편성: 매우 간단하고 직관적으로 구현 가능
  2. 이론적 보장: 충분한 시간이 주어지면 모든 행동을 무한히 시도하게 됨
  3. 조절 가능성: ε 값으로 탐험/활용 비율을 쉽게 조절
  4. 범용성: 거의 모든 강화학습 알고리즘에 적용 가능

단점

  1. 비효율적 탐험: 이미 나쁘다고 알려진 행동도 계속 시도
  2. 하이퍼파라미터 의존성: ε 값 설정이 성능에 큰 영향
  3. 초기 문제:
    • ε가 작으면 → 초기에 충분한 탐험 부족
    • ε가 크면 → 나중에 과도한 탐험으로 성능 저하

ε-greedy의 개선 방법

1. ε-decay (ε 감쇠)

시간이 지남에 따라 ε 값을 점진적으로 감소시키는 방법:

def decay_epsilon(initial_epsilon, decay_rate, step):
    """
    지수적 ε 감쇠
    """
    return initial_epsilon * (decay_rate ** step)

# 또는 선형 감쇠
def linear_decay_epsilon(initial_epsilon, min_epsilon, decay_steps, step):
    """
    선형 ε 감쇠
    """
    if step >= decay_steps:
        return min_epsilon
    return initial_epsilon - (initial_epsilon - min_epsilon) * (step / decay_steps)

2. ε-먼저 (ε-first)

초기 일정 기간 동안은 완전한 탐험, 이후 완전한 활용

3. 적응적 ε

환경이나 학습 상태에 따라 ε를 동적으로 조정

다른 탐험 전략들

1. Upper Confidence Bound (UCB)

각 행동에 대한 불확실성을 고려하여 행동 선택

2. Thompson Sampling

베이지안 접근법을 사용한 확률적 탐험

3. 정보 이론 기반 탐험

정보 획득량을 최대화하는 방향으로 탐험

실전 적용 팁

1. ε 값 설정 가이드라인

  • 초기 ε: 0.1 ~ 0.3 (환경 복잡도에 따라)
  • 최종 ε: 0.01 ~ 0.05 (완전히 0으로 만들지 않음)
  • 감쇠 비율: 훈련 에피소드 수에 따라 조절

2. 환경별 고려사항

  • 안전이 중요한 환경: 낮은 ε 값 사용
  • 빠른 변화 환경: 높은 ε 값 유지
  • 대용량 행동 공간: 더 정교한 탐험 전략 필요

3. 성능 모니터링

def track_exploration_stats(actions_taken, num_actions):
    """
    탐험 통계 추적
    """
    unique_actions = len(set(actions_taken))
    exploration_ratio = unique_actions / num_actions

    print(f"시도한 행동 수: {unique_actions}/{num_actions}")
    print(f"탐험 비율: {exploration_ratio:.2%}")

    # 행동별 선택 빈도
    action_counts = np.bincount(actions_taken, minlength=num_actions)
    return action_counts, exploration_ratio

실험: CartPole에서의 ε-greedy

간단한 예시를 통해 ε-greedy의 효과를 확인해보겠습니다:

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

def run_epsilon_greedy_experiment(epsilon_values, episodes=100):
    env = gym.make('CartPole-v1')
    results = {}

    for epsilon in epsilon_values:
        returns = []
        for ep in range(episodes):
            obs, _ = env.reset()
            total_reward = 0
            done = False

            while not done:
                # ε-greedy 행동 선택
                if np.random.random() < epsilon:
                    action = env.action_space.sample()  # 무작위
                else:
                    # 간단한 휴리스틱 정책
                    action = 1 if obs[2] > 0 else 0

                obs, reward, terminated, truncated, _ = env.step(action)
                done = terminated or truncated
                total_reward += reward

            returns.append(total_reward)

        results[epsilon] = np.mean(returns)

    return results

# 실험 실행
epsilon_values = [0.0, 0.1, 0.2, 0.3, 0.5]
results = run_epsilon_greedy_experiment(epsilon_values)

# 결과 시각화
plt.figure(figsize=(8, 5))
plt.bar(range(len(epsilon_values)), [results[eps] for eps in epsilon_values])
plt.xticks(range(len(epsilon_values)), epsilon_values)
plt.xlabel('Epsilon Value')
plt.ylabel('Average Return')
plt.title('CartPole Performance with Different Epsilon Values')
plt.show()

결론

탐험 vs 활용 딜레마는 강화학습의 핵심 문제이며, ε-greedy는 이를 해결하는 가장 기초적이면서도 효과적인 방법입니다. 비록 단순하지만, 적절한 ε 값 설정과 감쇠 전략을 통해 많은 실제 문제에서 좋은 성능을 보입니다.

실제 프로젝트에서는 환경의 특성, 안전성 요구사항, 학습 속도 등을 종합적으로 고려하여 탐험 전략을 선택해야 합니다. ε-greedy는 좋은 시작점이 되며, 필요에 따라 더 정교한 탐험 방법으로 발전시킬 수 있습니다.

다음 포스팅에서는 실제 CartPole 환경에서 다양한 정책들을 비교 실험해보는 내용을 다루겠습니다.

반응형