딥러닝 파이토치 강좌, 딥 큐-러닝

1. 들어가며

딥 큐 러닝(Deep Q-Learning)은 강화학습(Reinforcement Learning) 분야에서 매우 중요한 알고리즘 중 하나입니다.
심층 신경망을 사용하여 에이전트가 최적의 행동(action)을 선택하도록 학습시킵니다. 본 강좌에서는 파이토치(PyTorch) 라이브러리를 활용하여
딥 큐 러닝 알고리즘을 구현하고 이해하는 데 필요한 기본 개념들을 자세히 살펴보겠습니다.

2. 강화 학습 기초

강화 학습은 에이전트가 환경과 상호작용하여 보상(reward)을 최대화하는 행동을 학습하는 방법입니다.
에이전트는 상태(state)를 관찰하고, 가능한 행동을 선택하며, 그로 인해 환경에서 변화를 경험합니다.
이러한 과정은 다음과 같은 구성요소로 이루어져 있습니다.

  • 상태 (State, s): 에이전트가 현재 존재하는 환경의 상황.
  • 행동 (Action, a): 에이전트가 선택할 수 있는 행동.
  • 보상 (Reward, r): 행동을 취한 후, 에이전트가 받는 평가.
  • 정책 (Policy, π): 상태에서 행동을 선택하는 전략.

3. Q-Learning 알고리즘

Q-Learning은 강화학습의 한 형태로, 에이전트가 어떤 상태에서 특정 행동을 취했을 때 예상되는 보상을
학습하는 알고리즘입니다. Q-Learning의 핵심은 Q-값을 업데이트하는 것입니다. Q-값은 상태-행동 쌍의
장기적인 보상을 나타냅니다. Q-값은 다음과 같은 벨만 방정식으로 업데이트됩니다.

Q(s, a) ← Q(s, a) + α[r + γ max Q(s’, a’) – Q(s, a)]

여기서 α는 학습률, γ는 할인계수, s는 현재 상태, s’는 다음 상태입니다.
Q-Learning은 주로 테이블 형식으로 Q-값을 저장하지만, 상태 공간이 크거나 연속적일 때는
딥러닝을 통해 Q-값을 근사해야 합니다.

4. 딥 큐 러닝 (DQN)

딥 큐 러닝(Deep Q-Learning)은 심층 신경망을 사용하여 Q-값을 근사하는 방식입니다.
DQN은 다음과 같은 주요 구성 요소를 갖습니다.

  • 경험 재플레이 (Experience Replay): 에이전트의 경험을 저장하고 무작위로 샘플링하여 학습.
  • 타겟 네트워크 (Target Network): 안정성을 높이기 위해 일정 주기로 업데이트되는 네트워크.

DQN은 이 두 가지 기술을 활용하여 학습의 안정성과 성능을 개선합니다.

5. 환경 설정

이제 파이썬과 파이토치를 사용하여 DQN을 구현하기 위해 필요한 패키지를 설치해보겠습니다.
아래와 같이 pip를 이용하여 필요한 라이브러리를 설치하겠습니다.

        
            pip install torch torchvision numpy matplotlib gym
        
    

6. DQN 구현하기

아래는 DQN 클래스의 기본적인 골격과 환경 설정 코드입니다. 간단한 예로 OpenAI의 Gym에서 제공하는 CartPole 환경을 사용하겠습니다.

6.1 DQN 클래스 정의

        
            import torch
            import torch.nn as nn
            import torch.optim as optim
            import numpy as np
            import random
            
            class DQN(nn.Module):
                def __init__(self, state_size, action_size):
                    super(DQN, self).__init__()
                    self.fc1 = nn.Linear(state_size, 128)
                    self.fc2 = nn.Linear(128, 128)
                    self.fc3 = nn.Linear(128, action_size)

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

6.2 환경 설정 및 하이퍼파라미터

        
            import gym
            
            # 환경과 하이퍼파라미터 설정
            env = gym.make('CartPole-v1')
            state_size = env.observation_space.shape[0]
            action_size = env.action_space.n
            learning_rate = 0.001
            gamma = 0.99
            epsilon = 1.0
            epsilon_decay = 0.995
            epsilon_min = 0.01
            num_episodes = 1000
            replay_memory = []
            replay_memory_size = 2000
        
    

6.3 학습 루프

        
            def train_dqn():
                model = DQN(state_size, action_size)
                optimizer = optim.Adam(model.parameters(), lr=learning_rate)
                criterion = nn.MSELoss()
                
                for episode in range(num_episodes):
                    state = env.reset()
                    state = np.reshape(state, [1, state_size])
                    done = False
                    total_reward = 0
                    
                    while not done:
                        if np.random.rand() <= epsilon:
                            action = np.random.randint(action_size)
                        else:
                            q_values = model(torch.FloatTensor(state))
                            action = torch.argmax(q_values).item()

                        next_state, reward, done, _ = env.step(action)
                        total_reward += reward
                        next_state = np.reshape(next_state, [1, state_size])
                        
                        if done:
                            reward = -1

                        replay_memory.append((state, action, reward, next_state, done))
                        if len(replay_memory) > replay_memory_size:
                            replay_memory.pop(0)

                        if len(replay_memory) > 32:
                            minibatch = random.sample(replay_memory, 32)
                            for m_state, m_action, m_reward, m_next_state, m_done in minibatch:
                                target = m_reward
                                if not m_done:
                                    target += gamma * torch.max(model(torch.FloatTensor(m_next_state))).item()
                                target_f = model(torch.FloatTensor(m_state))
                                target_f[m_action] = target
                                optimizer.zero_grad()
                                loss = criterion(model(torch.FloatTensor(m_state)), target_f)
                                loss.backward()
                                optimizer.step()

                        state = next_state

                    global epsilon
                    if epsilon > epsilon_min:
                        epsilon *= epsilon_decay
                    
                    print(f"Episode: {episode}/{num_episodes}, Total Reward: {total_reward}")
        
            train_dqn()
        
    

7. 결과 및 마무리

DQN 알고리즘은 복잡한 상태 공간을 가진 문제에서 효과적으로 동작할 수 있습니다.
이 코드 예제에서 우리는 CartPole 환경을 사용하여 DQN을 학습시켰습니다.
학습이 진행됨에 따라 에이전트는 점점 더 나은 성능을 보이게 될 것입니다.

향후 개선 방안으로는 더 복잡한 환경에서의 실험, 다양한 하이퍼파라미터 조정,
테크닉을 조합한 다양한 전략적 접근 방식 등이 있습니다.
이 강좌에서 다룬 내용이 여러분의 딥러닝 및 강화학습 이해에 도움이 되기를 바랍니다!

8. 참고 문헌

  • 리프, E. (2013). Playing Atari with Deep Reinforcement Learning.
  • 미니, D., & 하프, M. (2015). Continuous Control with Deep Reinforcement Learning.