개발 이야기/PyTorch (파이토치)

[Ray RLlib로 강화학습 쉽게 사용하기] 7편: 사용자 정의 환경, 관측/행동 전처리, 콜백 활용하기

nodiscard 2024. 12. 25. 17:00

이전까지는 주로 Gym에 내장된 표준 환경(CartPole, MountainCar, Atari 등)을 활용했습니다. 그러나 실제 문제 해결 과정에서는 고유한 시뮬레이터나 데이터 소스에서 얻은 관측을 RL 환경으로 구성하고, 에이전트가 특정 형식의 행동을 내도록 설계해야 할 수 있습니다. 또한 RL 실험 중간에 특정 이벤트에 반응하거나, 관측값을 가공하는 등의 커스터마이징이 필요할 수도 있습니다.

이번 글에서는 다음 내용을 다룹니다.

  1. 사용자 정의 Gym 환경을 RLlib에 등록하고 적용하기
  2. Observation/Action Wrapper를 통한 관측, 행동 전처리
  3. 콜백(Callbacks)을 활용한 로그 확장, 성능 조건부 로직 삽입

사용자 정의 환경 연동

RLlib은 기본적으로 Gym 인터페이스에 맞는 환경이면 어떤 것이든 학습 대상로 사용할 수 있습니다. 사용자 정의 환경을 사용하려면 다음 단계를 따르면 됩니다.

  1. 사용자 환경 구현: gym.Env를 상속받아 __init__(), reset(), step() 메서드를 구현. 관측(observation), 행동(action), 보상(reward), done 반환 형식을 Gym 규칙에 맞춰야 합니다.
    import gym
    from gym import spaces
    import numpy as np
    
    class MyCustomEnv(gym.Env):
        def __init__(self, config=None):
            super(MyCustomEnv, self).__init__()
            self.action_space = spaces.Discrete(2)    # 예: 행동 2개
            self.observation_space = spaces.Box(low=0, high=1, shape=(4,))
            self.state = np.zeros(4)
        
        def reset(self):
            self.state = np.zeros(4)
            return self.state
        
        def step(self, action):
            # action에 따라 상태 변화, 보상 계산
            reward = 1.0 if action == 0 else 0.0
            done = False
            # 상태 업데이트 로직
            self.state = np.random.rand(4)
            if np.mean(self.state) > 0.9:
                done = True
            return self.state, reward, done, {}
    
  2. 예:
  3. 환경 등록:
    Gym 등록 방식을 이용하거나, RLlib에서 config.environment() 호출 시 env 인자에 이 환경 클래스를 직접 전달할 수도 있습니다.
    from ray.rllib.algorithms.ppo import PPOConfig
    
    config = (
        PPOConfig()
        .environment(env=MyCustomEnv)  # 클래스 자체 전달
        .framework("torch")
    )
    trainer = config.build()
    
    이렇게 하면 RLlib이 MyCustomEnv를 인스턴스화하여 사용합니다. env_config를 통해 환경 생성 시 필요한 추가 파라미터를 넘길 수도 있습니다:
  4. config = PPOConfig().environment(env=MyCustomEnv, env_config={"param1":123})
  5. 예:

이 방식으로 실제 산업 시뮬레이터, 로보틱스 시뮬레이션, 재무 데이터 처리 환경 등을 RLlib에 쉽게 통합할 수 있습니다.

관측/행동 전처리: Wrapper 활용

경우에 따라 관측값을 정규화하거나, 특정 행동을 행동공간에 매핑하는 전처리가 필요합니다. Gym에는 ObservationWrapper, ActionWrapper와 같은 래퍼(Wrapper) 클래스를 제공하며, RLlib에서도 이를 투명하게 사용할 수 있습니다.

예를 들어, 관측값을 정규화하기 위한 Wrapper:

import gym

class ObsNormalizeWrapper(gym.ObservationWrapper):
    def __init__(self, env):
        super().__init__(env)
    
    def observation(self, obs):
        return obs / 1.0  # 예: 단순 스케일링

env = ObsNormalizeWrapper(MyCustomEnv())

RLlib에서는 래퍼 적용 방법 중 하나로 env_make 콜백을 활용하거나, environment() 설정에서 직접 래핑한 환경 객체를 반환하는 함수를 지정할 수 있습니다.

def env_creator(env_config):
    base_env = MyCustomEnv(env_config)
    wrapped_env = ObsNormalizeWrapper(base_env)
    return wrapped_env

config = PPOConfig().environment(env=env_creator)

이렇게 하면 RLlib이 env_creator를 통해 래핑된 환경을 사용하게 됩니다.

Action Wrapper도 유사한 방식으로 행동을 변환할 수 있으며, 필요한 경우 연속 행동을 특정 범위로 클리핑, 이산 행동을 다른 형태로 매핑하는 작업을 수행할 수 있습니다.

콜백(Callbacks)으로 커스터마이징

callbacks는 RLlib에서 매우 유용한 기능으로, 학습 과정 중 특정 이벤트(에피소드 시작, 에피소드 종료, 스텝 완료, iteration 완료 등) 발생 시 사용자 정의 함수를 실행할 수 있게 합니다. 이를 통해 다음과 같은 작업이 가능합니다.

  • 에피소드마다 특별한 로그 기록
  • 특정 성능 기준 달성 시 파라미터 변경 또는 체크포인트 저장
  • 추가 모니터링 지표 계산 후 result에 포함

콜백 사용 예:

def my_callbacks(params):
    def on_episode_end(info):
        episode = info["episode"]
        ep_reward = episode.total_reward
        print(f"Episode finished with reward: {ep_reward}")
    return {
        "on_episode_end": on_episode_end
    }

config = PPOConfig().environment(env="CartPole-v1").callbacks(my_callbacks)
trainer = config.build()

여기서 on_episode_end 이벤트 발생 시 에피소드 리워드를 콘솔에 출력. 더 확장하면, 특정 리워드 달성 시 trainer.save() 호출하거나, 외부 DB에 결과 전송도 가능.

실제 프로젝트 적용 예시

  • 실제 산업용 RL 프로젝트에서:
    • 커스텀 환경: 로보틱스 시뮬레이터를 Env로 감싸기, 관측 전처리(센서 노이즈 정리), 행동 변환(토크→모터 명령)
    • 콜백: 특정 milestone(평균 리워드 200 이상 달성) 시 Slack 알림 전송, 정책 파라미터 JSON export
    • Wrapper: 관측값 정규화, 클리핑, 차원 축소 등으로 학습 안정성 개선

이런 방식으로 RLlib을 환경 중심의 실제 문제에 맞추어 커스터마이징할 수 있습니다.

마무리

핵심 포인트 정리:

  • 사용자 정의 환경: Gym 인터페이스로 구현 후 env=<class> 또는 env_creator 함수로 RLlib에 등록
  • Wrapper: 관측, 행동 전처리 용이. ObsNormalizeWrapper, ActionWrapper 등을 활용해 관측/행동 변환 가능
  • 콜백(callbacks): 학습 이벤트 기반 커스터마이징, 로그 확장, 조건부 동작 삽입
  • 실제 프로젝트 적용 시 다양한 환경, 전처리, 콜백 조합으로 고유 상황에 맞는 RL 파이프라인 구현 가능

이번 글에서는 RLlib을 단순히 기본 환경에서 사용하는 것을 넘어, 사용자 정의 환경 연동, 관측/행동 전처리 Wrapper, 콜백을 통한 커스터마이징 기법을 배웠습니다. 이를 통해 RLlib을 다양한 현실적인 상황에 적용할 수 있으며, 원하는 로직을 쉽게 삽입하고 변형할 수 있습니다.

다음 글에서는 지금까지 다룬 내용을 종합하고, 실전 프로젝트에서 RLlib을 활용할 때 고려해야 할 포인트, 추가 학습 자료, 앞으로의 방향성 등을 제안하며 시리즈를 마무리할 예정입니다.

반응형