짐나지움으로 강화 학습하기: 실용 가이드

강화 학습 (RL)은 지도 및 비지도 학습과 더불어 세 가지 주요 기계 학습 패러다임 중 하나입니다. RL에서 에이전트는 누적 보상을 최대화하기 위해 환경과 상호 작용하는 방법을 학습합니다. 이는 시행착오를 통해 다양한 환경 조건에서 최적의 행동을 학습합니다. 인간 피드백이 포함된 강화 학습 (RLHF)은 에이전트가 각 단계에서 인간 입력에 기반해 행동을 수정할 수 있도록 합니다.

RL은 자율 주행 자동차, 자동화 된 거래, 비디오 게임의 컴퓨터 플레이어, 로봇 훈련 등과 같은 문제를 해결합니다. 딥 신경망을 사용하여 RL 알고리즘을 적용할 때, 이를 심층 강화 학습이라고 합니다.

이 튜토리얼에서는 Gymnasium이라는 오픈 소스 파이썬 라이브러리를 사용하여 강화 학습 알고리즘을 개발하고 비교하는 방법을 안내하겠습니다. Gym 환경을 설정하고, 다양한 RL 환경을 탐색하며, 파이썬을 사용하여 간단한 에이전트를 구축하여 RL 알고리즘을 구현하는 방법을 보여드리겠습니다.

Gymnasium이란 무엇인가요?

Gymnasium은 RL 알고리즘 개발을 지원하기 위해 설계된 오픈 소스 Python 라이브러리입니다. RL의 연구 및 개발을 촉진하기 위해 Gymnasium은 다음을 제공합니다:

  • 단순한 게임부터 실제 시나리오를 모방한 문제까지 다양한 환경.
  • 환경과 인터페이스하기 위한 간소화된 API 및 래퍼.
  • 사용자 정의 환경을 만들고 API 프레임워크를 활용할 수 있는 기능.

개발자는 RL 알고리즘을 구축하고 다음과 같은 작업을 위해 API 호출을 사용할 수 있습니다:

  • 에이전트가 선택한 행동을 환경에 전달하기.
  • 환경의 상태와 각 행동에 따른 보상을 알고 있습니다.
  • 모델 훈련하기.
  • 모델 성능 테스트하기.

OpenAI의 Gym과 Farama의 Gymnasium

OpenAI는 Gym 개발에 상당한 자원을 투자하지 않았습니다. 이는 회사의 비즈니스 우선순위가 아니었기 때문입니다. Farama 재단은 RL 라이브러리를 장기적으로 표준화하고 유지하기 위해 설립되었습니다. Gymnasium은 OpenAI의 Gym의 포크입니다. Gymnasium 0.26.2는 Gym 0.26.2의 대체 버전입니다. Farama는 포크를 통해 모든 API 호출에 대해 기능 기반(클래스 기반 외) 메서드를 추가하고, 벡터 환경을 지원하며, 래퍼를 개선하는 것을 목표로 하고 있습니다. 전체적인 목표는 프레임워크를 더 깔끔하고 효율적으로 만드는 것입니다.

Gymnasium 설정하기

Gymnasium은 다양한 종속 프로그램의 특정 버전(최신 릴리스가 아님)이 필요합니다. NumPyPyTorch와 같은 프로그램입니다. 따라서 Gymnasium을 설치하고 사용하며 RL 프로그램을 실행하기 위해 새 Conda 또는 venv 환경이나 새 노트북을 만드는 것을 권장합니다.

DataLab 워크북을 사용하여 튜토리얼을 따라 할 수 있습니다.

Gymnasium 설치하기

서버나 로컬 머신에 Gymnasium을 설치하려면 다음 명령을 실행하십시오:

$ pip install gymnasium

Google의 Colab이나 DataCamp의 DataLab과 같은 노트북을 사용하여 설치하려면 다음을 사용하세요:

!pip install gymnasium

위 명령어는 Gymnasium과 올바른 버전의 종속성을 설치합니다.

Gymnasium 환경 탐색

2024년 11월 기준, Gymnasium은 60개 이상의 내장 환경을 포함하고 있습니다. 사용 가능한 내장 환경을 탐색하려면 gym.envs.registry.all() 함수를 사용하세요. 아래 예시와 같이:

import gymnasium as gym for i in gym.envs.registry.keys(): print(i)

당신은 또한 Gymnasium 홈페이지를 방문할 수 있습니다. 왼쪽 열에는 모든 환경에 대한 링크가 있습니다. 각 환경의 웹페이지에는 행동, 상태 등과 같은 세부 정보가 포함되어 있습니다.

환경은 Classic Control, Box2D 등의 카테고리로 구성되어 있습니다. 아래에는 각 그룹에서 일반적인 환경을 나열합니다:

  • Classic Control: 이러한 환경은 RL 개발에 사용되는 표준 환경으로, 많은 교과서 예제의 기초를 형성합니다. 새로운 RL 알고리즘을 테스트하고 벤치마크하는 데 있어 적절한 복잡성과 단순성을 제공합니다. Gymnasium의 Classic Control 환경에는 다음이 포함됩니다:
    • Acrobot
    • Cart Pole
    • Mountain Car Discrete
    • Mountain Car Continuous
    • Pendulum
  • Box2D: Box2D는 게임을 위한 2D 물리 엔진입니다. 이 엔진을 기반으로 한 환경에는 다음과 같은 간단한 게임들이 포함됩니다:
    • Lunar Lander
    • Car Racing
  • ToyText: 이들은 RL 알고리즘을 디버그하는 데 자주 사용되는 작고 간단한 환경들입니다. 이러한 환경의 많은 부분은 작은 그리드 월드 모델과 간단한 카드 게임을 기반으로 합니다. 예시로는 다음이 있습니다: 
    • Blackjack
    • Taxi
    • Frozen Lake
  • MuJoCo: 접촉을 하는 다중 관절 역학 (MuJoCo)은 로봇공학, 생체역학, 기계 학습 등을 위한 환경을 시뮬레이션하는 오픈 소스 물리 엔진입니다. Gymnasium의 MuJoCo 환경으로는 다음이 있습니다:
    • Ant
    • Hopper
    • Humanoid
    • Swimmer
    • And more

내장된 환경 외에도, Gymnasium은 동일한 API를 사용하여 많은 외부 환경과 함께 사용할 수 있습니다.

이 튜토리얼에서는 대표적인 Classic Control 환경 중 하나를 사용할 것입니다. 특정 환경을 불러오려면 .make() 명령을 사용하고 환경의 이름을 인수로 전달하십시오. 예를 들어 CartPole (버전 1)을 기반으로 한 새 환경을 만들려면 아래 명령을 사용하십시오:

import gymnasium as gym env = gym.make("CartPole-v1")

짐내슘에서 강화학습 개념 이해

간략히 말해, 강화학습에이전트(로봇과 같은)가 환경과 상호작용하는 것으로 구성됩니다. 정책은 에이전트의 행동을 결정합니다. 에이전트의 행동에 따라 환경은 각 타임스텝마다 보상(또는 패널티)을 제공합니다. 에이전트는 총 보상을 극대화하는 최적의 정책을 찾기 위해 강화학습을 사용합니다.

강화학습 환경의 구성요소

다음은 RL 환경의 주요 구성 요소입니다:

  • 환경: 외부 시스템, 세계 또는 맥락. 에이전트는 환경과 일련의 타임스텝에서 상호 작용합니다. 각 타임스텝에서 에이전트의 행동에 기반하여 환경은 다음을 수행합니다:
    • 보상(또는 벌점) 부여
    • 다음 상태 결정
  • 상태: 환경의 현재 구성을 수학적으로 표현한 것입니다.
    • 예를 들어, 진자의 환경 상태는 각 시간 단계에서 진자의 위치와 각속도를 포함할 수 있습니다.
    • 종단 상태: 새로운/다른 상태로 이어지지 않는 상태입니다.
  • 에이전트: 환경을 관찰하고 이 관찰을 기반으로 다양한 행동을 취하는 알고리즘입니다. 에이전트의 목표는 보상을 최대화하는 것입니다.
    • 예를 들어, 에이전트는 진자를 얼마나 세게, 어떤 방향으로 밀지를 결정합니다.
  • 관찰: 에이전트가 환경에 대한 견해를 수학적으로 표현한 것으로, 예를 들어 센서를 사용하여 획득한다.
  • 행동: 에이전트가 다음 단계로 진행하기 전에 내리는 결정. 이 행동은 환경의 다음 상태에 영향을 주고 에이전트에게 보상을 제공한다.
  • 보상: 환경으로부터 에이전트에게 오는 피드백. 행동과 환경의 상태에 따라 긍정적이거나 부정적일 수 있다.
  • 반환: 미래 타임 스텝에 대한 예상 누적 반환. 미래 타임 스텝의 보상은 할인 요소를 사용하여 할인될 수 있습니다.
  • 정책: 에이전트의 다양한 상태에서 취할 행동에 대한 전략. 일반적으로 상태를 행동으로 매핑하는 확률 행렬P로 표현됩니다.
    • 주어진 한정된 상태의 집합 m개와 가능한 행동 n개가 있을 때, 행렬의 요소 Pmn은 상태 an에서 행동 sm을 취할 확률을 나타냅니다.
  • 에피소드: 에이전트가 종단 상태에 도달할 때까지 (랜덤화된) 초기 상태에서의 시간 단계 시퀀스.

관찰 공간과 행동 공간

관찰은 에이전트가 환경에 대해 수집하는 정보입니다. 예를 들어, 로봇과 같은 에이전트는 센서를 사용하여 환경 정보를 수집할 수 있습니다. 이상적으로, 에이전트는 환경의 모든 측면을 설명하는 완전한 상태를 관찰해야 합니다. 실제로는 에이전트가 자신의 관찰을 상태의 대리자로 사용합니다. 따라서 관측값이 에이전트의 행동을 결정합니다.

A 공간은 수학적 집합에 비유됩니다. 항목의 공간 XX의 모든 가능한 인스턴스를 포함합니다. X의 공간은 또한 X 유형의 모든 항목의 구조(구문 및 형식)를 정의합니다. 각 체육관 환경은 두 개의 공간을 가지고 있습니다: 행동 공간 action_space와 관찰 공간 observation_space입니다. 행동 공간과 관찰 공간은 모두 부모 gymnasium.spaces.Space 슈퍼클래스에서 파생됩니다. 

관측 공간

관측 공간은 모든 가능한 관측을 포함하는 공간입니다. 또한 관측이 저장되는 형식을 정의합니다. 관측 공간은 일반적으로 Box 데이터 유형의 객체로 표현됩니다. 이는 관측의 매개변수를 설명하는 ndarray입니다. 상자는 각 차원의 경계를 지정합니다. 환경의 관측 공간을 확인하려면 observation_space 메서드를 사용할 수 있습니다:

print("observation space: ", env.observation_space)

CartPole-v1 환경의 경우, 아래 예시와 같이 출력됩니다:

observation space: Box([-4.8 -inf -0.41887903 -inf], [4.8 inf 0.41887903 inf], (4,), float32)

이 예에서는 CartPole-v1 관측 공간이 4차원입니다. 관측 배열의 4 요소는 다음과 같습니다:

  • 카트 위치 -4.8에서 +4.8 사이에서 변동합니다.
  • 카트 속도 – 범위는 부터 +
  • 폴 각도 – -0.4189와 +0.4189 사이에서 변동
  • 극 각속도 – 범위는 에서 +

개별 관찰 배열의 예를 보려면 .reset() 명령어를 사용하세요.

observation, info = env.reset() print("observation: ", observation)

CartPole-v1의 경우, 출력은 아래 예시와 같습니다:

[ 0.03481963 -0.0277232 0.01703267 -0.04870504]

이 배열의 네 요소는 앞에서 설명한 네 가지 관측된 양(카트 위치, 카트 속도, 막대 각도, 막대 각속도)에 해당합니다.

Action space

액션 공간에는 에이전트가 취할 수 있는 모든 가능한 액션이 포함됩니다. 액션 공간은 또한 액션이 표현되는 형식을 정의합니다. 환경의 액션 공간을 볼 수 있습니다. action_space 메서드를 사용하여:

print("action space: ", env.action_space)

CartPole-v1 환경의 경우, 출력은 아래 예시와 같습니다:

action space: Discrete(2)

CartPole-v1 환경의 경우, 액션 공간은 이산형입니다. 에이전트가 취할 수 있는 총 2개의 액션이 있습니다:

  • 0: 카트를 왼쪽으로 밀기
  • 1: 카트를 오른쪽으로 밀기

첫 번째 RL 에이전트 만들기 with Gymnasium

이전 섹션에서는 강화 학습과 체육관의 기본 개념을 탐색했습니다. 이 섹션에서는 체육관을 사용하여 강화 학습 에이전트를 구축하는 방법을 보여줍니다.

환경 생성 및 재설정

첫 번째 단계는 환경의 인스턴스를 만드는 것입니다. 새로운 환경을 만들려면 .make() 메서드를 사용하십시오.

env = gym.make('CartPole-v1')

에이전트의 상호 작용은 환경의 상태를 변경합니다. .reset() 메서드는 환경을 초기 상태로 재설정합니다. 기본적으로 환경은 무작위 상태로 초기화됩니다. 프로그램을 실행할 때마다 환경을 동일한 상태로 초기화하려면 .reset() 메서드에 SEED 매개변수를 사용할 수 있습니다. 아래 코드에서는 이를 어떻게 수행하는지 보여줍니다:

SEED = 1111 env.reset(seed=SEED)

동작 샘플링은 무작위성을 포함합니다. 이 무작위성을 제어하고 완전히 재현 가능한 훈련 경로를 얻기 위해 NumPy와 PyTorch의 난수 생성기를 시드할 수 있습니다:

np.random.seed(SEED) torch.manual_seed(SEED)

랜덤 대 지능적인 행동

마르코프 프로세스의 각 단계에서 에이전트는 무작위로 행동을 선택하고 종단 상태에 도달할 때까지 환경을 탐색할 수 있습니다. 무작위로 행동을 선택함으로써:

  • 종단 상태에 도달하는 데 오랜 시간이 걸릴 수 있습니다.
  • 누적 보상은 가능했던 것보다 훨씬 낮을 수 있습니다.

에이전트를 훈련하여 이전 경험(환경과 상호 작용)을 기반으로 행동 선택을 최적화하는 것은 장기적인 보상을 극대화하기 위해 효율적입니다.

훈련되지 않은 에이전트는 무작위로 초기화된 정책에 기반하여 무작위 행동을 시작합니다. 이 정책은 일반적으로 신경망으로 표현됩니다. 훈련 동안 에이전트는 보상을 극대화하는 최적의 정책을 학습합니다. 강화 학습(RL)에서 훈련 과정은 정책 최적화라고도 불립니다.

다양한 정책 최적화 방법이 있습니다. 벨만 방정식은 RL 정책의 가치를 계산하고 최적의 정책을 결정하는 방법을 설명합니다. 이 튜토리얼에서는 정책 그래디언트라는 간단한 기법을 사용할 것입니다. 근접 정책 최적화(PPO)와 같은 다른 방법도 존재합니다.

간단한 정책 그래디언트 에이전트 구현하기

정책 그래디언트를 사용하는 RL 에이전트를 구축하기 위해 우리는 정책을 구현하기 위한 신경망을 생성하고, 단계별 보상과 행동 확률에서 수익과 손실을 계산하는 함수를 작성하며, 표준 역전파 기술을 사용하여 정책을 반복적으로 업데이트합니다.

정책 네트워크 설정

정책을 구현하기 위해 신경망을 사용합니다. CartPole-v1은 간단한 환경이므로, 우리는 다음과 같은 신경망을 사용합니다:

  • 환경의 관찰 공간 차원과 같은 입력 차원.
  • 64개의 뉴런을 가진 단일 은닉층.
  • 출력 차원은 환경의 행동 공간의 차원과 같습니다.

따라서 정책 네트워크의 기능은 관찰된 상태를 행동으로 매핑하는 것입니다. 입력 관찰이 주어지면 올바른 행동을 예측합니다. 아래 코드는 정책 네트워크를 구현합니다:

class PolicyNetwork(nn.Module): def __init__(self, input_dim, hidden_dim, output_dim, dropout): super().__init__() self.layer1 = nn.Linear(input_dim, hidden_dim) self.layer2 = nn.Linear(hidden_dim, output_dim) self.dropout = nn.Dropout(dropout) def forward(self, x): x = self.layer1(x) x = self.dropout(x) x = F.relu(x) x = self.layer2(x) return x

보상 수집 및 순방향 패스

앞서 언급했듯이, 마르코프 과정의 각 단계에서 환경은 에이전트의 행동과 상태에 따라 보상을 제공합니다. RL의 목표는 총 수익을 극대화하는 것입니다.

  • 각 타임스텝에서의 수익은 시작부터 그 단계까지 얻은 보상의 누적 합계입니다.
  • 각 에피소드의 총 반환값은 해당 에피소드의 모든 단계별 보상을 누적하여 얻습니다. 따라서 총 반환값은 마지막 타임스텝에서의 반환값입니다(에이전트가 종단 상태에 도달할 때).

실제로 보상을 누적하는 과정에서는 다음을 수행하는 것이 일반적입니다:

  • 할인 요소를 사용하여 미래 보상을 조정합니다.
  • 단계별 반환 배열을 정규화하여 부드럽고 안정적인 훈련을 보장합니다.

아래 코드는 이를 어떻게 수행하는지 보여줍니다:

def calculate_stepwise_returns(rewards, discount_factor): returns = [] R = 0 for r in reversed(rewards): R = r + R * discount_factor returns.insert(0, R) returns = torch.tensor(returns) normalized_returns = (returns - returns.mean()) / returns.std() return normalized_returns

순방향 패스는 현재 정책에 따라 에이전트를 실행하여 터미널 상태에 도달할 때까지 단계별 보상과 행동 확률을 수집하는 것입니다. 아래 단계에서는 순방향 패스를 구현하는 방법을 설명합니다:

  • 환경을 초기 상태로 재설정합니다.
  • 행동 확률, 보상 및 누적 수익을 저장할 버퍼를 초기화합니다.
  • .step() 함수를 사용하여 에이전트를 환경에서 반복적으로 실행하여 종료될 때까지 실행합니다:
    • 환경 상태의 관측치를 가져옵니다.
    • 관측에 기반한 정책에 의해 예측된 동작을 가져옵니다.
    • Softmax 함수를 사용하여 예측된 동작을 취할 확률을 추정합니다.
    • 이러한 추정된 확률을 기반으로 범주형 확률 분포를 시뮬레이션합니다.
    • 이 분포를 샘플링하여 에이전트의 동작을 얻습니다.
    • 시뮬레이션된 분포에서 샘플링된 동작의 로그 확률을 추정합니다.
  • 각 단계의 동작과 보상의 로그 확률을 해당 버퍼에 추가합니다.
  • 보상을 기반으로 각 단계의 정규화된 및 할인된 반환 값을 추정합니다.
def forward_pass(env, policy, discount_factor): log_prob_actions = [] rewards = [] done = False episode_return = 0 policy.train() observation, info = env.reset() while not done: observation = torch.FloatTensor(observation).unsqueeze(0) action_pred = policy(observation) action_prob = F.softmax(action_pred, dim = -1) dist = distributions.Categorical(action_prob) action = dist.sample() log_prob_action = dist.log_prob(action) observation, reward, terminated, truncated, info = env.step(action.item()) done = terminated or truncated log_prob_actions.append(log_prob_action) rewards.append(reward) episode_return += reward log_prob_actions = torch.cat(log_prob_actions) stepwise_returns = calculate_stepwise_returns(rewards, discount_factor) return episode_return, stepwise_returns, log_prob_actions

보상에 기반한 정책 업데이트

손실은 우리가 경사 하강을 적용하는 양을 나타냅니다. 강화 학습에서의 목표는 반환을 최대화하는 것입니다. 그래서 우리는 손실의 대리로서 예상 반환 값을 사용합니다. 예상 반환 값은 단계별 예상 반환과 단계별 동작의 로그 확률의 곱으로 계산됩니다. 아래 코드는 손실을 계산합니다:

def calculate_loss(stepwise_returns, log_prob_actions): loss = -(stepwise_returns * log_prob_actions).sum() return loss

정책을 업데이트하려면 손실 함수에 대해 역전파를 실행합니다. 아래의 update_policy() 메서드는 calculate_loss() 메서드를 호출합니다. 그런 다음 이 손실에 대해 역전파를 실행하여 정책 매개변수, 즉 정책 네트워크의 모델 가중치를 업데이트합니다.

def update_policy(stepwise_returns, log_prob_actions, optimizer): stepwise_returns = stepwise_returns.detach() loss = calculate_loss(stepwise_returns, log_prob_actions) optimizer.zero_grad() loss.backward() optimizer.step() return loss.item()

수익의 그래디언트를 기반으로 정책을 업데이트하는 것은 정책 그래디언트 방법이라고 합니다. 

정책 훈련

이제 정책을 훈련하고 평가하기 위해 필요한 모든 구성 요소가 있습니다. 다음 단계에 설명된대로 훈련 루프를 구현합니다.  

시작하기 전에 하이퍼파라미터를 선언하고 정책을 인스턴스화하며 옵티마이저를 생성합니다:

  • 하이퍼파라미터를 Python 상수로 선언합니다:
    • MAX_EPOCHS는 정책을 훈련하기 위해 우리가 실행할 준비가 된 최대 반복 횟수입니다.
    • DISCOUNT_FACTOR는 미래 시간 단계에서의 보상의 상대적 중요성을 결정합니다. 할인 계수가 1이면 모든 보상이 동일하게 중요하다는 의미이고, 0이면 현재 시간 단계의 보상만 중요하다는 의미입니다.
    • N_TRIALS 는 에이전트의 성능을 평가하기 위해 평균 수익을 계산하는 에피소드의 수입니다. N_TRIALS 에피소드의 평균 수익이 임계값을 초과하면 훈련이 성공적이라고 판단합니다.
    • REWARD_THRESHOLD: 정책이 임계값보다 큰 수익을 달성할 수 있다면 성공적인 것으로 간주됩니다.
    • DROPOUT 은 무작위로 0으로 설정할 가중치의 비율을 결정합니다. 드롭아웃 함수는 모델 가중치의 일부를 무작위로 0으로 설정합니다. 이는 특정 뉴런에 대한 의존도를 줄이고 과적합을 방지하여 네트워크를 보다 견고하게 만듭니다.
    • LEARNING_RATE는 각 단계에서 정책 매개변수를 얼마나 수정할 수 있는지를 결정합니다. 각 반복에서 매개변수에 대한 업데이트는 기울기와 학습률의 곱입니다.
  • 정책을 PolicyNetwork 클래스의 인스턴스로 정의합니다(앞서 구현됨).
  • 학습률을 사용하여 Adam 알고리즘으로 옵티마이저를 만듭니다.

정책을 학습하기 위해 평균 보상(N_TRIALS)이 보상 임계값보다 클 때까지 훈련 단계를 반복 실행합니다:

  • 각 에피소드에 대해 한 번 전방 패스를 실행합니다. 행동의 로그 확률, 단계별 보상 및 해당 에피소드의 총 보상을 수집합니다. 에피소드 보상을 배열에 누적합니다.
  • 로그 확률과 단계별 수익을 사용하여 손실을 계산합니다. 손실에 대해 역전파를 실행합니다. 옵티마이저를 사용하여 정책 매개변수를 업데이트합니다.
  • N_TRIALS을 통해 평균 수익이 보상 임계값을 초과하는지 확인합니다.

아래 코드는 이러한 단계를 구현합니다:

def main(): MAX_EPOCHS = 500 DISCOUNT_FACTOR = 0.99 N_TRIALS = 25 REWARD_THRESHOLD = 475 PRINT_INTERVAL = 10 INPUT_DIM = env.observation_space.shape[0] HIDDEN_DIM = 128 OUTPUT_DIM = env.action_space.n DROPOUT = 0.5 episode_returns = [] policy = PolicyNetwork(INPUT_DIM, HIDDEN_DIM, OUTPUT_DIM, DROPOUT) LEARNING_RATE = 0.01 optimizer = optim.Adam(policy.parameters(), lr = LEARNING_RATE) for episode in range(1, MAX_EPOCHS+1): episode_return, stepwise_returns, log_prob_actions = forward_pass(env, policy, DISCOUNT_FACTOR) _ = update_policy(stepwise_returns, log_prob_actions, optimizer) episode_returns.append(episode_return) mean_episode_return = np.mean(episode_returns[-N_TRIALS:]) if episode % PRINT_INTERVAL == 0: print(f'| Episode: {episode:3} | Mean Rewards: {mean_episode_return:5.1f} |') if mean_episode_return >= REWARD_THRESHOLD: print(f'Reached reward threshold in {episode} episodes') break

마지막으로, main() 함수를 호출하여 정책을 훈련합니다:

main()

UDataLab 워크북을 사용하여 위의 알고리즘을 직접 실행하고 RL을 사용하여 CartPole 환경을 해결하십시오.

체육관의 고급 기술

RL 알고리즘 구현 방법을 시연한 후, 이제 실제에서 일반적으로 사용되는 몇 가지 고급 기술에 대해 논의합니다.

미리 구축된 아키텍처 사용

RL 알고리즘을 처음부터 구현하는 것은 긴 과정이며 특히 복잡한 환경과 최첨단 정책에 대해 어려운 작업입니다.

더 실용적인 대안은 Stable Baselines3와 같은 소프트웨어를 사용하는 것입니다. RL 알고리즘의 시험된 구현을 제공합니다. 미리 훈련된 에이전트, 훈련 스크립트, 평가 도구 및 그래프 플롯 및 비디오 녹화 모듈이 포함되어 있습니다. 

Ray RLib은 RL용 또 다른 인기 있는 도구입니다. RLib은 확장 가능한 솔루션으로 설계되어 있어 멀티 GPU 시스템에서 RL 알고리즘을 구현하기 쉽습니다. 또한 멀티 에이전트 RL을 지원하여 다음과 같은 새로운 가능성을 엽니다:

  • 독립형 멀티 에이전트 학습: 각 에이전트는 다른 에이전트를 환경의 일부로 취급합니다.
  • 협력적 다중 에이전트 훈련: 에이전트 그룹이 동일한 정책과 가치 함수를 공유하고 서로의 경험에서 병렬로 학습합니다.
  • 적대적 훈련: 에이전트(또는 에이전트 그룹)가 경쟁적인 게임 환경에서 서로 경쟁합니다.

RLib와 Stable Baselines3 모두에서 OpenAI Gymnasium의 환경을 가져와 사용할 수 있습니다.

사용자 정의 환경

Gymnasium으로 패키지된 환경은 새로운 강화 학습 전략을 시험하고 정책을 훈련하는 데 적합한 선택지입니다. 그러나 대부분의 실용적인 응용 프로그램에서는 해결하려는 문제를 정확히 반영하는 환경을 만들고 사용해야 합니다. Gymnasium을 사용하여 사용자 정의 환경을 만들 수 있습니다. Gymnasium 사용자 정의 환경을 사용하는 장점은 RLib 및 Stable Baselines3와 같은 많은 외부 도구가 이미 Gymnasium API 구조와 작동하도록 구성되어 있다는 것입니다.

Gymnasium에서 사용자 정의 환경을 만들려면 다음을 정의해야 합니다:

  • 관측 공간.
  • 종료 조건.
  • 에이전트가 선택할 수 있는 행동 집합.
  • 환경을 초기화하는 방법 (reset() 함수가 호출될 때). 
  • 환경이 에이전트의 행동을 바탕으로 다음 상태를 결정하는 방법 (step() 함수가 호출될 때). 

자세한 내용을 보려면 Gymnasium 사용자 정의 환경 만들기 가이드를 참고하세요

Gymnasium 사용을 위한 모범 사례

다양한 환경을 실험해보세요.

이 튜토리얼의 코드는 CartPole 환경에서 정책 경량 알고리즘을 구현하는 방법을 보여주었습니다. 이는 이산 행동 공간을 가진 간단한 환경입니다. RL을 더 잘 이해하기 위해, 같은 정책 경량 알고리즘(및 PPO와 같은 다른 알고리즘)을 다른 환경에 적용해 보기를 권장합니다. 

예를 들어, Pendulum 환경은 연속적인 행동 공간을 가지고 있습니다. 이는 특정 상태에서 진자에 적용되는 토크의 (크기와 방향)으로 표현되는 단일 입력으로 구성됩니다. 이 토크는 -2+2 사이의 어떤 값도 가질 수 있습니다. 

다양한 환경에서 다양한 알고리즘을 실험하면 서로 다른 종류의 강화 학습 솔루션과 그 도전에 대해 더 잘 이해할 수 있습니다. 

훈련 진행 상황 모니터링

RL 환경은 종종 로봇, 진자, 산악 자동차, 비디오 게임 등으로 구성됩니다. 환경 내에서 에이전트의 행동을 시각화하면 정책의 성능에 대한 더 나은 직관적인 이해를 제공합니다.

Gymnasium에서 env.render() 메서드는 에이전트의 환경과의 상호작용을 시각화합니다. 이는 환경의 현재 상태—게임 화면, 진자 또는 카트 폴의 위치 등을 그래픽적으로 표시합니다. 에이전트의 행동과 환경의 반응에 대한 시각적 피드백은 에이전트의 성능과 훈련 과정에서의 진행 상황을 모니터링하는 데 도움이 됩니다.

렌더 모드는 “human”, “rgb_array”, “ansi”, “rgb_array_list”의 네 가지가 있습니다. 에이전트의 성능을 시각화하려면 “human” 렌더 모드를 사용하세요. 렌더 모드는 환경이 초기화될 때 지정됩니다. 예를 들어:

env = gym.make(‘CartPole-v1’, render_mode=’human’)

렌더링을 수행하려면 에이전트가 수행한 각 작업 후에 .render() 메서드를 포함해야 합니다 ( .step() 메서드를 호출하여). 아래의 의사 코드는 이를 수행하는 방법을 보여줍니다:

while not done: … step, reward, terminated, truncated, info = env.step(action.item()) env.render()

일반 오류 해결

Gymnasium은 복잡한 RL 환경과 인터페이스하는 것을 쉽게 만들어 줍니다. 그러나 지속적으로 업데이트되는 소프트웨어로 많은 의존성이 있습니다. 따라서 몇 가지 일반적인 오류 유형을 주의하는 것이 중요합니다.

버전 불일치

  • 체육관 버전 불일치: Farama의 체육관 소프트웨어 패키지는 OpenAI의 Gym에서 버전 0.26.2를 포크하여 만들어졌습니다. 오래된 Gym 버전과 새로운 Gymnasium 버전 간에는 몇 가지 호환성 문제가 발생했습니다. 공개적으로 사용 가능한 많은 구현은 오래된 Gym 릴리스를 기반으로 하고 있으며 최신 릴리스와 직접적으로 작동하지 않을 수 있습니다. 이러한 경우에는 설치를 이전 버전으로 롤백하거나 코드를 새로운 릴리스에 맞게 조정해야 합니다.
  • 환경 버전 불일치: 많은 체육관 환경들은 서로 다른 버전을 갖고 있습니다. 예를 들어, 두 개의 CartPole 환경이 있습니다 – CartPole-v1CartPole-v0. 환경의 동작은 두 버전 모두 동일하지만, 에피소드 길이, 보상 임계치 등 일부 매개변수가 다를 수 있습니다. 한 버전에서 훈련된 정책이 동일 환경의 다른 버전에서는 성능이 좋지 않을 수 있습니다. 각 환경 버전마다 훈련 매개변수를 업데이트하고 정책을 재훈련해야 합니다.
  • 의존성 버전 불일치: 체육관은 NumPy 및 PyTorch와 같은 종속성에 의존합니다. 2024년 12월 기준, 이러한 종속성의 최신 버전은 numpy 2.1.3torch 2.5.1입니다. 그러나 체육관은 torch 1.13.0numpy 1.23.3와 가장 잘 작동합니다. 이러한 종속성이 미리 설치된 환경에 체육관을 설치하면 문제가 발생할 수 있습니다. 철저히 새로운 Conda 환경에 체육관을 설치하고 작업하는 것을 권장합니다. 

수렴 문제

  • 하이퍼파라미터: 다른 머신러닝 알고리즘과 마찬가지로, RL 정책은 학습률, 할인율 등과 같은 하이퍼파라미터에 민감합니다. 우리는 하이퍼파라미터를 수동으로 조정하거나 격자 탐색 및 랜덤 탐색과 같은 자동화된 기술을 사용하여 실험하는 것을 권장합니다.
  • 탐색 대 활용: 일부 정책 클래스(예: PPO)의 경우, 에이전트는 두 가지 전략을 채택합니다: 환경을 탐색하여 새로운 경로를 발견하고 지금까지 알려진 경로를 기반으로 보상을 극대화하기 위해 탐욕적인 접근 방식을 채택합니다. 너무 많이 탐색하면 정책이 수렴하지 않습니다. 반대로, 충분히 탐색하지 않으면 최적의 경로를 시도하지 않습니다. 따라서 탐색과 활용 사이의 올바른 균형을 찾는 것이 중요합니다. 훈련 과정에서 초기 에피소드에서는 탐색을 우선시하고, 후속 에피소드에서는 활용을 우선시하는 것이 일반적입니다.

훈련 불안정성

  • 큰 학습률: 학습률이 너무 높으면 정책 매개변수가 각 단계에서 큰 업데이트를 받습니다. 이는 최적의 값 세트를 놓칠 수 있습니다. 일반적인 해결책은 학습률을 점진적으로 감소시켜 훈련이 수렴될 때 더 작고 안정적인 업데이트를 보장하는 것입니다.
  • 과도한 탐험: 행동 선택에서 너무 많은 무작위성(엔트로피)은 수렴을 방해하고 연속적인 단계 사이에서 손실 함수의 큰 변동을 유도합니다. 안정적이고 수렴하는 훈련 과정을 갖기 위해서는 탐험과 활용을 균형있게 유지해야 합니다.
  • 잘못된 알고리즘 선택: 정책 그래디언트와 같은 간단한 알고리즘은 큰 행동 및 상태 공간을 가진 복잡한 환경에서 불안정한 훈련으로 이어질 수 있습니다. 이러한 경우, PPO 및 신뢰 영역 정책 최적화(TRPO)와 같은 더 강력한 알고리즘을 사용하는 것이 좋습니다. 이러한 알고리즘은 매 단계에서 큰 정책 업데이트를 피하고 더 안정적일 수 있습니다.
  • 무작위성: RL 알고리즘은 초기 상태와 행동 선택에 내재된 무작위성에 매우 민감합니다. 훈련 실행이 불안정할 때, 때때로 다른 무작위 시드나 정책을 재초기화하여 안정화할 수 있습니다.

결론

이번 튜토리얼에서는 RL의 기본 원리를 살펴보고, 다양한 RL 환경과 인터페이스할 수 있는 깔끔한 API를 가진 소프트웨어 패키지인 Gymnasium에 대해 논의했으며, 간단한 RL 알고리즘을 구현하고 Gymnasium 환경에서 적용하는 Python 프로그램을 작성하는 방법을 보여주었습니다.

이 튜토리얼에서 기본을 이해한 후, 택시 경로 최적화주식 거래 시뮬레이션과 같은 실제 문제를 해결하기 위해 Gymnasium 환경을 활용할 것을 권장합니다.

Source:
https://www.datacamp.com/tutorial/reinforcement-learning-with-gymnasium