300x250

Getting Started with OpenAI and Tensorflow (1) 글에 이어서, 시험 삼아 간단한 실습을 진행해보고, Tensorflow에 대해 알아보자.

실습 내용은 아래 깃허브를 참조하자.

https://github.com/JJukE/ReinforcementLearning

 

GitHub - JJukE/ReinforcementLearning: Reinforcement Learning Course

Reinforcement Learning Course. Contribute to JJukE/ReinforcementLearning development by creating an account on GitHub.

github.com

 

 

목차

     

     

     

     

     

    4. openAI Gym - Basic Cart Pole

     

    나는 docker환경도 (굳이..) VS Code로 써보고 싶어져서, Visual Studio Code 환경에서 진행해보려고 했는데..

    VS Code와 Docker 연동, VS Code와 Jupyter Notebook 연동은 쉽게 잘 되는데, 셋을 동시에 해보려고 하니까 관련 자료도 없고 오류가 계속 떠서 결국에는 실습 진행은 웹 상의 Jupyter Notebook으로 진행하려 한다. (쓸데없는 데 시간을 너무 많이 쏟는 것 같아 결국 포기..)

     

    어쨌든, Basic Cart Pole 실습을 시작해보자.

     

     

     

    1) Import Modules

     

    먼저, 필요한 모듈(라이브러리)들을 import한다.

     

    import gym
    from IPython import display
    import matplotlib.pyplot as plt
    %matplotlib inline

     

    여기서 Ipython의 display는 주피터에서 환경을 렌더링하여 이미지로 보여주기 위해 필요한 모듈이다.

     

     

     

    2) Create a Simulation Instance

     

    그다음, 시뮬레이션을 위한 instance(object)를 만들어 준다.

     

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

     

    'CartPole-v0'라는 환경은 이미 docker 이미지파일에 정의되어있고, 이를 gym.make()메소드로 instance를 생성해준다.

     

     

     

    3) Initialize the Environment

     

    그리고, 환경을 초기화해준다. (

     

    env.reset()

     

    셀을 실행시키면 배열이 표시되는데, 큰 의미는 없다.

     

     

     

    4) Loop for Time Steps

     

    마지막으로, time step에 대한 루프를 실행시킨다.

     

    for _ in range(1000):
        plt.imshow(env.render(mode='rgb_array'))
        display.clear_output(wait=True)
        display.display(plt.gcf())
        env.step(env.action_space.sample())

     

    for loop에서 첫 3줄은 jupyter notebook 환경에 pyplot 모듈을 사용하여 렌더링 하는 과정이다. (해당 과정이 매우 오래걸린다. 실제로 step 진행하는 부분만 돌린다면 금방 끝난다.)

    핵심적인 강화학습 코드는 마지막줄인데, 실제 step을 진행하는 부분으로 볼 수 있다.

    각 envrionment마다 취할 수 있는 action들의 집합(action space)이 존재하는데, 그중에서 랜덤하게 하나를 샘플링하여 action을 취하는 것이다.

     

     

     

    5) Result

     

    결과는 다음과 같다.

     

    이는 에피소드의 terminate 조건 등이 없이, 간단히 1000번의 action을 sequential하게 선택하는 과정을 보여준다.

     

     

     

     

    5. OpenAI Gym - Training a Robot to Walk

     

    다음으로, robot이 넘어지지 않고 걸을 수 있도록 학습시키는 과정을 살펴보자.

     

     

     

    1) Import Modules & Create a Simulation Instance

     

    해당 과정은 위와 동일하다.

     

    import gym
    from IPython import display
    import matplotlib.pyplot as plt
    %matplotlib inline

     

    env = gym.make('BipedalWalker-v2')

     

    'BipedalWalker-v2' 역시 Docker 이미지파일 내에 이미 구현된 내용을 가져오는 것이다.

     

     

     

    2) Initialize the Environment for Each Episode

     

    이번에는 Environment 초기화를 각 에피소드마다 진행해준다. 에피소드는 terminal condition이 존재한다.

     

    for episode in range(100):
        observation = env.reset()
        
        # Render the environment on each step
        for i in range(10000):
            plt.imshow(env.render(mode='rgb_array'))
            display.clear_output(wait=True)
            display.display(plt.gcf())
            
            # we choose action by sampling random action from environment's action space.
            # Every environment has some action space which contains the all possible
            # valid actions and observations.
            
            action = env.action_space.sample()
            
            # Then for each step, we will record the observation, reward, done, info
            observation, reward, done, info = env.step(action)
        
            # When done is true, we print the time steps taken for the episode and break the current episode.
            if done:
                print("{} timesteps taken for the episode.".format(i+1), episode)
                break

     

    observation = env.reset()을 통해 environment를 리셋해주고, 에피소드 하나가 시작된다.

    환경에서의 action space에서 aciton을 랜덤 샘플링하는 과정까지는 위와 같다.

     

    이후 해당 스텝에서 할당되는 action에 의한 네 가지 변수는 각각 다음과 같다.

    • observation은 환경의 observation을 나타내는 object, 예를 들면 땅 기준에서 로봇의 state 등이 할당된다.
    • reward는 이전 action에 의해 얻은 reward가 할당된다.
    • done은 플래그로, true이면 agent인 로봇이 final state에 도달하였다는 것을 의미한다. 즉, 로봇이 성공적으로 학습했거나 완전히 fail했다는 것을 의미한다.
    • info는 디버깅을 위한 정보를 담는다.

     

    'done' 플래그가 true일 경우 해당 에피소드에 소요된 time step을 출력하고, 그 에피소드를 끝낸다.

     

    결과는 다음과 같다.

     

     

     

     

     

    6. Tensorflow

     

    다음으로, 텐서플로에 대해 알아보자. 강의 후반부에 Deep Learning과 Reinforcement Learning을 함께 사용하는 Deep Reinforcement Learning에 대해 다룰 것이다. 강화학습만의 이론도 중요하지만, 결국 딥러닝과 결합한 내용을 배우고 적용시키기 위해 이 강의를 듣는 것이므로, 사전에 Tensorflow에 대해 알아둘 필요가 있다.

     

     

     

     

    1) Tensorflow란?

     

    텐서플로우는 머신러닝, 특히 딥러닝에서의 numerical 계산에 특화된 오픈소스 소프트웨어 라이브러리이다. Google에서 만들었고, 현재 추세로는 Google의 Tensorflow는 실제 현업에서의 적용에, Facebook의 Pytorch는 연구개발에 많이 사용되고 있다.

    텐서플로우는 다른 플랫폼에서 공유되고 실행될 수 있는 data flow graph를 사용한다. 여기서의 graph는 데이터를 시각화하는 graph가 아니라, computer science에서의 graph 자료구조를 말한다.

    Tensor는 다차원 배열을 말하고, 이에 따라 Tensorflow는 글자 그대로 해석하자면 다차원 배열인 텐서의 수학적 계산 과정의 흐름이다.

     

    실습에서 사용하는 Tensorflow는 1.X 버전으로, 현재에 비하면 그 문법 등이 많이 달라졌다. 강의를 통해 일단 이론적인 내용에 대해 파악하고, 실습을 해보며 어떤식으로 코드를 작성하는지 익힌 후에 최근 기술에 대한 논문을 읽고 프로젝트를 진행해보는 것이 가장 이상적일 것이다.

     

     

     

     

    2) Variables, Constants, Placeholders

     

    Tensorflow 1.X 버전 기준에서는 Variable, Constant, Placeholder가 주요 개념이다. 각각에 대해 살펴보자.

     

     

     

    (1) Variable

     

    다른 언어에서와 비슷한 개념으로, 값을 저장하는 공간이다.

    기본적으로 앞서 언급했던 Tensor(multi-dimensional array) 형태를 가지며, computational graph의 동작에서 input으로 들어가게 된다.

    Tensorflow 1.X 버전에서 다음과 같이 선언할 수 있다.

     

    tf.Variable()

     

    예를 들어,

    weights = tf.Variable(tf.random_normal([3, 2], stddev=0.1), name="weights")

     

    와 같이 사용하면, 표준편차가 0.1인 normal 분포를 갖는 random 값들을 3 by 2 tensor로 만들어 graph의 node의 이름을 weights로 설정하여 weights라는 변수에 할당한다.

    여기서 주의할 점은 괄호 안의 name="weights"는 graph에 들어갈 node의 이름을 설정해주는 것이지, 변수의 이름과는 관련이 없다는 점이다.

     

     

     

    (2) Constant

     

    Constant도 다른 언어에서와 마찬가지로, 변할 수 없는 상수 값을 말하며, 다음 문법으로 할당할 수 있다.

     

    tf.constant()

     

    사용 예시는 다음과 같다.

     

    x = tf.constant(13)

     

     

     

    (3) Placeholder

     

    Placeholder는 Tensorflow 1.x버전에서 사용하는 특별한 개념인데, value 없이 data type만 정의하여 공간(메모리)을 미리 잡아두는 개념이다.

    값은 runtime 도중에 할당되게 된다. 이를 'feed'라 한다.

    옵션으로 데이터의 차원을 설정해줄 수 있다. (shape이 None이면 어떤 사이즈의 데이터든 feed 해줄 수 있다.)

     

    Placeholder는 다음과 같이 사용된다.

    x = tf.placeholder("float", shape=None)

     

    위와 같이 할당하면, placeholder의 data type은 float으로 미리 정해지며, shape은 runtime 시 정해지게 된다.

     

    간단하게 개념을 정리하자면, tf.Variable은 데이터를 저장하기 위해 사용하고, tf.placeholder는 외부 데이터를 runtime 시 feed해주기 위해 사용한다.

     

     

     

     

    3) Computational Graph

     

    Tensorflow에서 모든 것은 Graph로 표시된다. 앞서 언급했듯이 여기서 graph는 node, edge를 갖는 자료구조적인 graph를 말한다.

    여기서 node는 addition, multiplication 등의 수학적 operation을 나타내고, edge는 tensor를 나타낸다.

     

    Tensorflow를 사용하여 코드를 짠다는 것은 결국 graph를 생성하는 과정이고, Session을 엶으로써 실제 실행을 시키는 것(graph에 input을 넣는 것)이다.

     

    Computational Graph를 사용함으로써 resource를 효율적으로 사용할 수 있고, 분산 컴퓨팅(distributed computing)이 가능해진다.

     

    예를 들어, A의 결과에 따른 값을 input으로 받는 node B를 생각해보자.

     

    A = tf.multiply(8, 5)
    B = tf.multiply(A, 1)

     

    여기서 Graph의 형태는 명확해지고, edge로 연결되지 않은 node들은 multi core로 실행이 가능하다. 즉, 구조가 생성되고 distribution이 가능하다.

     

     

     

     

    4) Sessions

     

    위에서 말한 Computation Graph는 정의만 될 뿐, 실행을 시키기 위해서는 Session을 열어주어야 한다.

    Tensorflow Session은 다음과 같이 연다.

    sess = tf.Session()

     

    tf.Session() 메소드를 통해 session object를 만들 수 있고, 이는 변수의 현재 값을 저장하기 위한 메모리를 할당해준다.

    Session object를 만든 이후에, run()메소드로 그래프를 실행할 수 있다.

     

    sess.run()

     

    코드에서 tensorflow를 import 할 때마다, 자동적으로 default computational graph가 만들어지고,

    만들어두었던 모든 노드들이 그래프에 attach된다.

    아래 예시를 살펴보자.

     

    import tensorflow as tf # default computational graph 생성
    a = tf.multiply(2, 3) # 'a' node의 역할 : 2와 3이라는 tensor(edge)를 곱함
    print(a)

     

    이에 대한 결과로는 tensorflow object, 즉 a node의 주소값이 나올 것이다. 왜냐하면 아직 session을 열지 않아 실행이 되지 않았기 때문이다.

    따라서 실행을 위해서는 아래와 같은 절차를 진행해야 한다.

     

    # Import tensorflow
    import tensorflow as tf
    
    # Initialize variables
    a = tf.multiply(2, 3)
    
    # Create tensorflow session for executing the session
    with tf.Session() as sess:
    	# run the session
        print(sess.run(a))

     

    session을 실행한 결과는 6을 나타낸다.

     

     

     

     

    4) Tensorboard

     

    Tensorboard는 tensorflow의 시각화 툴이다. computational graph를 시각화하여 디버깅, 네트워크 구조 파악을 용이하게 해준다.

    또한 Tensorboard를 통해 행렬 계산 등의 결과를 plot하여 살펴볼 수도 있다.

     

    Tensorboard에서 tensor들의 계산 결과를 살펴보자.

     

    import tensorflow as tf
    a = tf.constant(5)
    b = tf.constant(4)
    c = tf.multiply(a, b)
    d = tf.constant(2)
    e = tf.constant(3)
    f = tf.multiply(d, e)
    g = tf.add(c, f)
    
    with tf.Session() as sess:
        writer = tf.summary.FileWriter("output", sess.graph)
        print(sess.run(g))
        writer.close()

     

    a ~ g까지 정의하면서 graph를 생성하고, with 구문 내에서 Session을 생성 및 실행하면서 계산을 진행한다.

    tf.summary.FileWriter()메소드로 Tensorboard를 위해 생성된 파일들을 어느 폴더에 저장할 것인지 지정해준다.

     

    여기서 sess.run(g)만으로 모든 계산이 실행되는데, 최종 node 하나만 실행시키면 이에 필요한 모든 node와 edge가 실행되기 때문이다.

     

    Tensorboard를 살펴보자.

    Jupyter Notebook의 home에 가서 'New → Tensorboard → Current Directory'를 클릭해보면, 다음과 같은 결과를 얻을 수 있다.

     

    Tensorboard

     

     

     

    (1) Adding Scope

     

    여기에 Scope라는 기능을 추가해보자. 연관된 노드들을 tf.name_scope()로 묶어준 다음, tensorboard를 사용하여 표시하면 그래프 해석이 더 용이해진다.

     

    위에서 진행했던 코드를 변형시켜 다음과 같이 진행해보자.

     

    import tensorflow as tf
    
    with tf.name_scope("Computation"):
        with tf.name_scope("Part1"):
            a = tf.constant(5)
            b = tf.constant(4)
            c = tf.multiply(a, b)
        with tf.name_scope("Part2"):
            d = tf.constant(2)
            e = tf.constant(3)
            f = tf.multiply(d, e)
    
    with tf.name_scope("Result"):
        g = tf.add(c, f)
    
    with tf.Session() as sess:
        writer = tf.summary.FileWriter("output", sess.graph)
        print(sess.run(g))
        writer.close()

     

    코드를 보면, 명시적으로 scope를 나누면서 각 계산 part들의 계산이 독립적으로 이루어진다는 것을 알 수 있다.

     

    이에 따라 tensorboard 결과도 다음과 같이 바뀌게 된다.

     

     

    name scope에 따라 나누어진 것을 볼 수 있다.

    tensorboard의 범례는 다음과 같다.

     

    legend of tensorboard

     

    위 결과의 Result와 Computation을 더블클릭하여 자세히 표현하면 다음과 같은 결과가 나온다.

     

     

     

    728x90
    • 네이버 블러그 공유하기
    • 네이버 밴드에 공유하기
    • 페이스북 공유하기
    • 카카오스토리 공유하기