강화학습

강화학습: Deep Deterministic Policy Gradient (DDPG) 완전 정복

move84 2025. 4. 6. 09:49
반응형

강화학습은 에이전트가 환경과 상호작용하며 보상을 최대화하도록 학습하는 머신러닝의 한 분야입니다. Deep Deterministic Policy Gradient (DDPG)는 이 강화학습 분야에서 연속적인 행동 공간을 다루기 위해 개발된 알고리즘입니다. DDPG는 딥러닝의 강력함과 정책 기반 방법의 효율성을 결합하여 복잡한 환경에서도 학습할 수 있는 에이전트를 만들 수 있습니다.


🤖 DDPG란 무엇인가요? (What is DDPG?)

DDPG는 Actor-Critic (액터-크리틱) 알고리즘의 일종으로, Actor (액터)와 Critic (크리틱) 두 개의 신경망을 사용합니다. Actor는 환경에서 어떤 행동을 취할지 결정하는 정책을 학습하고, Critic은 주어진 상태에서 액션의 가치를 평가합니다. DDPG는 특히 연속적인 행동 공간, 즉 가능한 행동의 수가 무한대인 환경에서 효과적입니다. 예를 들어, 로봇 팔의 각도 조절이나 자율주행 자동차의 조향각 조절 등이 이에 해당합니다.


🧠 DDPG의 핵심 구성 요소 (Key Components of DDPG)

DDPG는 다음과 같은 주요 구성 요소로 구성됩니다:

  1. Actor Network (액터 네트워크): 이 신경망은 현재 상태를 입력으로 받아, 어떤 행동을 취할지 결정합니다. Actor는 deterministic policy (결정적 정책)를 따르며, 특정 상태에서 항상 동일한 행동을 출력합니다.

  2. Critic Network (크리틱 네트워크): Critic은 Actor가 취한 행동의 가치를 평가합니다. 이는 주어진 상태와 행동에 대한 Q-value (Q 값)를 예측합니다. Q-value는 에이전트가 특정 상태에서 특정 행동을 취했을 때 얻을 수 있는 예상 누적 보상을 나타냅니다.

  3. Target Networks (타겟 네트워크): DDPG는 Actor와 Critic의 학습 안정성을 높이기 위해 각 네트워크에 대한 Target Network (타겟 네트워크)를 사용합니다. Target Network는 정기적으로 실제 네트워크의 가중치를 복사하여 학습 과정에서 업데이트됩니다. 이렇게 함으로써 학습의 변동성을 줄이고 수렴을 돕습니다.

  4. Experience Replay (경험 재생): Experience Replay는 에이전트가 경험한 (state, action, reward, next_state) 튜플을 저장하고, 이를 무작위로 샘플링하여 네트워크를 학습시키는 기술입니다. 이는 데이터의 상관 관계를 줄이고 학습 효율을 높입니다.


💻 Python 코드 예제 (Python Code Example)

다음은 간단한 DDPG 알고리즘의 Python 코드 예제입니다. 이 코드는 이해를 돕기 위한 기본적인 구조를 보여주며, 실제 구현에서는 환경과의 상호작용, 하이퍼파라미터 튜닝 등이 추가로 필요합니다.

import torch
import torch.nn as nn
import torch.optim as optim
import numpy as np

# 1. Actor Network 정의 (Actor Network Definition)
class Actor(nn.Module):
    def __init__(self, state_dim, action_dim, hidden_dim=256):
        super(Actor, self).__init__()
        self.fc1 = nn.Linear(state_dim, hidden_dim)
        self.fc2 = nn.Linear(hidden_dim, hidden_dim)
        self.fc3 = nn.Linear(hidden_dim, action_dim)
        self.tanh = nn.Tanh()

    def forward(self, state):
        x = torch.relu(self.fc1(state))
        x = torch.relu(self.fc2(x))
        action = self.tanh(self.fc3(x))
        return action

# 2. Critic Network 정의 (Critic Network Definition)
class Critic(nn.Module):
    def __init__(self, state_dim, action_dim, hidden_dim=256):
        super(Critic, self).__init__()
        self.fc1 = nn.Linear(state_dim + action_dim, hidden_dim)
        self.fc2 = nn.Linear(hidden_dim, hidden_dim)
        self.fc3 = nn.Linear(hidden_dim, 1)

    def forward(self, state, action):
        x = torch.cat([state, action], 1)
        x = torch.relu(self.fc1(x))
        x = torch.relu(self.fc2(x))
        q_value = self.fc3(x)
        return q_value

# 3. 하이퍼파라미터 설정 (Hyperparameter Settings)
state_dim = 3  # 예시: 상태 차원 (Example: State dimension)
action_dim = 1  # 예시: 행동 차원 (Example: Action dimension)
learning_rate_actor = 1e-4
learning_rate_critic = 1e-3
gamma = 0.99

# 4. 네트워크 인스턴스 생성 (Create network instances)
actor = Actor(state_dim, action_dim)
critic = Critic(state_dim, action_dim)
actor_target = Actor(state_dim, action_dim)
critic_target = Critic(state_dim, action_dim)

# 타겟 네트워크 초기화: 가중치를 복사 (Initialize target networks: Copy weights)
actor_target.load_state_dict(actor.state_dict())
critic_target.load_state_dict(critic.state_dict())

# 5. 옵티마이저 설정 (Optimizer Settings)
optimizer_actor = optim.Adam(actor.parameters(), lr=learning_rate_actor)
optimizer_critic = optim.Adam(critic.parameters(), lr=learning_rate_critic)

# 6. Experience Replay를 위한 Replay Buffer (Replay Buffer for Experience Replay)
class ReplayBuffer:
    def __init__(self, capacity):
        self.capacity = capacity
        self.buffer = []
        self.position = 0

    def push(self, state, action, reward, next_state, done):
        if len(self.buffer) < self.capacity:
            self.buffer.append(None)
        self.buffer[self.position] = (state, action, reward, next_state, done)
        self.position = (self.position + 1) % self.capacity

    def sample(self, batch_size):
        batch = random.sample(self.buffer, batch_size)
        state, action, reward, next_state, done = map(np.stack, zip(*batch))
        return state, action, reward, next_state, done

    def __len__(self):
        return len(self.buffer)

replay_buffer = ReplayBuffer(10000)

# 7. 학습 루프 (Training Loop)
def train(state, action, reward, next_state, done):
    # 텐서로 변환 (Convert to tensors)
    state = torch.FloatTensor(state)
    action = torch.FloatTensor(action)
    reward = torch.FloatTensor(reward).unsqueeze(1)
    next_state = torch.FloatTensor(next_state)
    done = torch.FloatTensor(done).unsqueeze(1)

    # Critic 학습 (Critic Training)
    with torch.no_grad():
        next_action = actor_target(next_state)
        q_target = critic_target(next_state, next_action)
        y = reward + (1 - done) * gamma * q_target

    q_value = critic(state, action)
    critic_loss = nn.MSELoss()(q_value, y)
    optimizer_critic.zero_grad()
    critic_loss.backward()
    optimizer_critic.step()

    # Actor 학습 (Actor Training)
    action_pred = actor(state)
    actor_loss = -critic(state, action_pred).mean()
    optimizer_actor.zero_grad()
    actor_loss.backward()
    optimizer_actor.step()

    # Target Networks 업데이트 (Update Target Networks)
    for target_param, param in zip(actor_target.parameters(), actor.parameters()):
        target_param.data.copy_(0.005 * param.data + (1.0 - 0.005) * target_param.data)

    for target_param, param in zip(critic_target.parameters(), critic.parameters()):
        target_param.data.copy_(0.005 * param.data + (1.0 - 0.005) * target_param.data)

# 8. 에피소드 루프 (Episode Loop)
num_episodes = 1000
for episode in range(num_episodes):
    state = env.reset()
    done = False
    while not done:
        # Actor를 사용하여 행동 선택 (Choose action using Actor)
        state_tensor = torch.FloatTensor(state).unsqueeze(0)
        action = actor(state_tensor).detach().numpy()

        # 환경과 상호작용 (Interact with the environment)
        next_state, reward, done, _ = env.step(action)
        replay_buffer.push(state, action, reward, next_state, done)

        if len(replay_buffer) > batch_size:
            # Replay buffer에서 샘플링하여 학습 (Sample from replay buffer and train)
            state_batch, action_batch, reward_batch, next_state_batch, done_batch = replay_buffer.sample(batch_size)
            train(state_batch, action_batch, reward_batch, next_state_batch, done_batch)

        state = next_state

    print(f"Episode {episode+1}")

💡 DDPG 학습 과정 (DDPG Learning Process)

  1. 상태 관찰 (Observe the state): 에이전트는 환경으로부터 현재 상태를 관찰합니다.
  2. 행동 선택 (Select an action): Actor 네트워크는 현재 상태를 입력으로 받아 행동을 결정합니다. 이때, 탐험(exploration)을 위해 노이즈를 추가할 수 있습니다.
  3. 환경과 상호 작용 (Interact with the environment): 선택된 행동을 환경에 적용하고, 다음 상태, 보상, 그리고 에피소드의 종료 여부를 받습니다.
  4. 경험 저장 (Store the experience): (state, action, reward, next_state) 튜플을 Experience Replay 버퍼에 저장합니다.
  5. 미니 배치 샘플링 (Mini-batch sampling): Experience Replay 버퍼에서 무작위로 미니 배치를 샘플링합니다.
  6. Critic 학습 (Train the Critic): Critic 네트워크는 샘플링된 데이터로 학습됩니다. Critic은 현재 상태와 행동에 대한 Q-value를 예측하도록 훈련됩니다. 손실 함수는 예측된 Q-value와 타겟 Q-value (다음 상태의 Q-value를 사용) 간의 차이를 최소화하도록 설계됩니다.
  7. Actor 학습 (Train the Actor): Actor 네트워크는 Critic 네트워크를 사용하여 학습됩니다. Actor는 현재 상태에서 Critic이 높은 Q-value를 예측하도록 행동을 생성하도록 훈련됩니다. 이는 정책 기울기 방식을 사용하여 수행됩니다.
  8. Target Network 업데이트 (Update Target Networks): Target Actor와 Target Critic 네트워크는 실제 네트워크의 가중치를 부드럽게 업데이트하여 학습의 안정성을 높입니다. 일반적으로, 이동 평균(moving average) 방식을 사용합니다.
  9. 반복 (Repeat): 2-8단계를 반복하며, 에이전트가 환경에서 더 나은 성능을 보일 때까지 학습합니다.

🧭 DDPG의 장점 (Advantages of DDPG)

  • 연속적인 행동 공간 처리 (Handling continuous action spaces): DDPG는 연속적인 행동 공간을 효과적으로 처리하도록 설계되었습니다.
  • 온라인 학습 가능 (Online learning): DDPG는 온라인 학습이 가능하며, 환경과 직접 상호 작용하며 학습할 수 있습니다.
  • 안정적인 학습 (Stable learning): Target Network와 Experience Replay를 사용하여 학습의 안정성을 높입니다.

⚠️ DDPG의 단점 (Disadvantages of DDPG)

  • 하이퍼파라미터 민감도 (Sensitivity to hyperparameters): DDPG는 하이퍼파라미터 설정에 민감하며, 적절한 튜닝이 필요합니다.
  • 샘플 비효율성 (Sample inefficiency): DDPG는 다른 강화학습 알고리즘에 비해 샘플 효율성이 낮을 수 있습니다. 즉, 학습에 더 많은 데이터를 필요로 할 수 있습니다.
  • Overestimation bias (과대평가 편향): Q-value의 과대평가 편향이 발생할 수 있습니다. (이 문제를 해결하기 위해 다른 알고리즘, 예를 들어 TD3가 개발되었습니다.)

📚 참고 자료 (References)

  • Lillicrap, T. P., Hunt, J. J., Pritzel, A., Heess, N., Erez, T., Tassa, Y., ... & Wierstra, D. (2015). Continuous control with deep reinforcement learning. arXiv preprint arXiv:1509.02971.

🤔 결론 (Conclusion)

DDPG는 연속적인 행동 공간을 가진 문제를 해결하기 위한 강력한 강화학습 알고리즘입니다. Actor-Critic 구조, Target Networks, Experience Replay 등의 기술을 통해 안정적인 학습과 효율적인 탐험을 가능하게 합니다. DDPG는 로봇 제어, 자율 주행 등 다양한 분야에서 활용될 수 있으며, 강화학습 연구의 중요한 부분을 차지하고 있습니다. DDPG의 이해는 더 복잡한 강화학습 알고리즘을 배우는 데에도 중요한 발판이 될 것입니다.


반응형