1. 요즘은 A3C 같은 것을 많이 사용한다고 하지만, DQN도 나름 구현하기도 쉽고, 베이스 코드 설명이 쉬워서 DQN으로 gym 에 있는 내용들로 강화학습 하는 내용을 간단하게 공유합니다.

  2. gym과 python 환경

    1. 저는 gym을 사용했지만 현재 해당 패키지는 Gymnasium 으로 이전했고, 해당 이전한 Gymnasium을 사용 하는것이 권장됩니다. 아마 원리만 알면 몇 가지 변경점이 있어도 쉽게 옮길 수 있을 것이라고 기대합니다.
    2. gym (혹은 Gymnasium)은 강화학습을 위한 환경을 제공하는 라이브러리입니다. 해당 패키지를 사용해서 쉽게 강화학습의 환경을 세팅 할 수 있습니다. 제공하는 환경의 종류는 해당 링크참고하세요.
    3. python 버전은 3.9 에서 테스트 된 코드이고, anaconda 를 사용해서 필요한 패키지를 모두 설치했습니다.
  3. DQN 이 무엇인가

    1. DQN에 대해서 설명하려면 Q Network 에 대해서 간략하게 설명드려야 할 것 같습니다.
      1. Q-Network
        1. Q Network는 결국 어떤 상태에 현재 오브젝트가 놓여있다면, 해당 오브젝트가 가장 높은 누적 보상을 얻을 수 있는 방향을 선택한다 라는 개념입니다.
        2. 해당 방식을 취하기 위해서는 테이블이 필요합니다. 어떤 상태 A에 놓여 있을 때, 취할 수 있는 상태의 가짓수가 N개가 있고, 어떤 상태 B에 있을 때는 상태가 M 개 있고 이런 식이 될 거니까요.
        3. 실제로 그 행동을 해서 얻어지는 보상으로 해당 테이블에 값을 업데이트 하는 방식이라고 이해하시면 됩니다.
        4. 실제로는 조금 더 자세한 내용이 있긴 하지만, DQN을 이해하는 것에는 이 정도 지식만 있으면 충분합니다.
      2. DQN
        1. 그런데 현재 오브젝트의 상태가 무한(혹은 무한이 아니더라도 너무 많은 경우) 는 어떻게 처리하면 좋을까요?
        2. 또는 현재 어떤 행동을 하는게, 즉각적인 보상으로 돌아오지 않는 경우는 어떻게 할 수 있을까요? 어떤 행동에 대해서 우리가 보상 테이블을 만들 수 있을까요?
        3. 예를 들어 슈퍼마리오를 생각해보면, 슈퍼마리오에서는 마리오의 위치가 거의 연속이기 때문에 마리오의 상태가 엄청나게 많아집니다. (마리오가 갈 수 있는 모든 공간이 상태가 되기 때문입니다.)
        4. 그렇게 상태가 너무 많을 때는 Q-Network에 필요한 테이블을 정의하는 것이 거의 불가능에 가깝게 됩니다.
        5. 그래서 우리는 추론을 잘 하는 Deep Learning Network를 Q-Network와 붙여서 작동 시키기로 합니다. 테이블을 만드는 대신, 인공 신경망을 사용하기로 한 것이죠.
        6. 결국 DQN은 Q-Network에 인공 신경망만 붙인 것입니다. 그래서 테이블을 만들 필요도 없고 모델만 짜서 던져놓으면 됩니다. 적절한 loss값과 보상 설계만 남아있죠
  4. DQN으로 Cart-Pole 학습하기

    universe2.yaml

    올려놓은 yaml 파일은 제가 학습 시킬 때 사용했던 anaconda 의 enviroment 입니다

    해당 파일대로 anaconda 환경을 구축하고 싶으시다면

    conda env create -f universe2.yaml # 이 명령어로 yaml파일 내용의 환경 구성
    conda activate universe2 # 이 명령어로 universe2 환경 사용
    
    1. 우선 Cart-Pole 이 무엇인지 알아봅시다.

    Untitled

    이렇게 생긴 게임이고, 왼쪽으로 이동할거냐, 오른쪽으로 이동할거냐 하는 입력을 받을 수 있는 게임입니다.

    cartpole 을 직접 플레이 해보고 싶다면 해당 링크로 웹에서 플레이 가능합니다.

    우선은 CartPole 의 게임의 상태 공간과, 가능한 행동, 보상이 어떻게 이루어지는지를 확인해 보겠습니다.

    링크 참조

    Untitled

    사진에서 보는 것 처럼

    가능한 Action 은 (0, 1) 로 두가지 이고

    관측 공간의 행렬의 크기는 4입니다. 4 가지의 변수가 들어온다는 것인데요,

    (카트의 위치, 카트의 속도, 막대의 각도, 막대의 각속도) 네 가지의 형태로 들어온다는 것을 알았습니다.

    Untitled

    그리고 보상은 단순히 버틴 시간이 길 수록 더 큰 보상을 주고 있습니다.

    마지막으로 게임이 종료되는 것은,

    1. 막대가 12도보다 더 많이 기울어졌을 때
    2. 카트의 위치가 -2.4 미만이거나 2.4 초과됐을 때
    3. 500 스텝이 지났을 때

    강화학습을 할 때 필요한 정보는

    1. 현재 어떤 상태에 있는가
    2. 내가 선택할 수 있는 행동은 어떤 것들이 있는가
    3. 어떤 행동을 선택 했을 때 어떤 보상이 돌아오는가

    위 세가지를 알아야 합니다. 자 위에 있는 내용을 보고 위 1,2,3 에 대한 답을 내릴 수 있겠죠?

    그렇다면 우리는 강화학습을 할 준비가 된 것입니다.

    이제부터 코드를 섞어서 완성해가면서 설명 해 드리겠습니다.

    import gym
    import torch
    import torch.nn as nn
    import torch.optim as optim
    import random
    import math
    import matplotlib
    import matplotlib.pyplot as plt
    
    from collections import namedtuple, deque
    

우선 필요한 패키지를 전부 import 해 줍니다.

env = gym.make('CartPole-v1', render_mode="human")
env.action_space.seed(42)

device = torch.device("cuda" if torch.cuda.is_available() else "cpu")

다음으로는 환경을 세팅 해 줘야합니다.

render_mode="human" 이면 우리가 볼 수 있는 게임 화면이 나온다고 생각하시면 됩니다.

저 argument 를 빠뜨리면 게임 화면은 안 나와요 (화면이 출력은 되지 않지만 게임 자체는 구동이 되고 있는 상태가 됩니다.)

다음 상태공간에 seed를 주입해주고, torch가 gpu를 사용할 수 있는지, 없는지를 체크해서 gpu를 쓸 수 있다면 gpu를 cpu를 써야한다면 cpu를 device 에 저장합니다.

torch에서는 gpu를 명시할 때 cuda 라고 명시 합니다. gpu 번호까지 명시하고 싶다면 cuda:0과 같이 쓰면 됩니다.

다음으로는 namedtuple 을 사용해서 우리가 사용할 데이터셋의 형식을 지정하겠습니다.

DataSegment = namedtuple('DataSegment', ('state', 'action', 'next_state', 'reward'))

각 항에는 상태 / 행동 / 다음 상태 / 보상

네 가지의 항목이 들어갑니다.

Q-Network, Deep-Q-Network 둘 다 우선 지금 현재 에이전트가 처해있는 상태에서 어떤 행동을 했고, 그게 다음 상태로 어떻게 변경이 됐는지가 필요하기 때문에 같이 저장합니다.

namedtupled 은 특별히 다른 기능이 있는 것은 아니고, 일반적인 tuple 처럼 사용 할 수 있지만, 가독성과 유지보수를 하기 쉽다는 장점이 있어서 자주 사용됩니다.