Q-Network

컴퓨터공부/인공지능 2018. 9. 12. 22:10 Posted by 아는 개발자

Q-Network


앞선 포스트에서 다룬 Q-Learning은 초기 학습 데이터 없이 주변을 탐사해가며 보상값을 최대화 하는 방향으로 환경 데이터의 파라미터의 값을 지속적으로 업데이트 하는 알고리즘이다. 그런데 만약 4x4처럼 작고 단순한 환경이 아니라 5000x5000이고 각 환경별로 선택 할 수 있는 경우의 수가 수십가지가 된다면 기존 알고리즘으로는 시간도 오래 걸릴 뿐만 아니라 모든 환경 데이터 값을 관리하는 것도 불가능하다.


이 문제는 Linear/Logical Regression에서도 겪어보았다. 학습에 사용되는 이미지의 크기가 커질수록 Feature의 값이 많아지게돼 기존의 방식 대로는 학습이 불가능했었다. 당시엔 이 문제를 해결하기 위해 Feature단위로 값을 분석하지 않고 인간의 뇌 구조를 본뜬 뉴럴 네트워크에 데이터 값을 몽땅 넣은 다음에 추이를 살펴보는 방법을 택했었는데 다행이도 Q-Learning도 이와 동일한 접근으로 해결 할 수 있다. Network를 사용한 Q-Learning은 Q-Network라고 부른다.


그런데 Linear/Logical Regression과 달리 지금까지 Q-Learning에서는 Cost Function이 없었다. 왜 없었을까? 그런데 조금만 생각해보면 있는 것이 오히려 이상하다. Q-Learning에서는 학습에 사용하는 실제 데이터가 없기 때문에 학습 결과물이 예측한 값과 라벨 값을 비교할 일이 없었다. 그래서 다소 비효율적이지만 모든 값을 돌아다니며 당시에 주어진 보상 값을 업데이트하는 방식을 사용해야 했다. 하지만 뉴럴 네트워크에 적용하려면 죽이되든 밥이되든 Cost Function이 필요하다. 그래서 Q-network에서는 학습데이터 없이 기존과 동일하게 보상 값을 할 수 있는 Cost Function을 새로 만들었다. 


별도로 논문에 첨부된 수식 보다는 코드로 보는것이 더 직관적일 것 같다. tensorflow를 해본 사람은 40, 41번째 줄을 제외하면 술술 넘어갈 것이다.

# Deep Q-Network lecture slide from http://hunkim.github.io/ml/RL/rl07-l1.pdf
# Original source code repository is https://github.com/awjuliani/DeepRL-Agents

import numpy as np
import tensorflow as tf
import random
from collections import deque
import gym 

class DQN:
    def __init__(self, session, input_size, output_size, name="main"):
        self.session = session
        self.input_size = input_size
        self.output_size = output_size
        self.net_name = name
     
        self._build_network()
     
    def _build_network(self, h_size = 10, l_rate = 1e-1):
        with tf.variable_scope(self.net_name):
            # Input data type
            self._X = tf.placeholder(
                tf.float32, [None, self.input_size], name="input_x")
     
            W1 = tf.get_variable("W1", shape=[self.input_size, h_size],
                             initializer=tf.contrib.layers.xavier_initializer())
            layer = tf.nn.tanh(tf.matmul(self._X, W1))
     
            W2 = tf.get_variable("W2", shape=[h_size, self.output_size],
                                initializer=tf.contrib.layers.xavier_initializer())
     
            # Predicted reward value
            self._Qpred = tf.matmul(layer, W2) 
     
        # Label data type
        self._Y = tf.placeholder(
            shape=[None, self.output_size], dtype=tf.float32)

        # Cost function
        self._loss = tf.reduce_mean(tf.square(self._Y - self._Qpred))
        self.train = tf.train.AdadeltaOptimizer(learning_rate=l_rate).minimize(self._loss)

    def predict(self, state):
        x = np.reshape(state, [1, self.input_size])
        return self.session.run(self._Qpred, feed_dict = {self._X: x}) 

    def update(self, x_stack, y_stack):
        return self.session.run([self._loss, self.train], 
                feed_dict={self._X: x_stack, self._Y: y_stack})

위 코드의 40번째 줄에 해당하는 부분이 Q-Network에서 사용하는 Cost Function이다. 여기서 self._Qpred는 현재 위치에서 예측했을 때 각 행동별 reward 값이다. 그리고 그것과 비교하는 self._Y는 아래 update 함수에서 y_stack으로 대입해주는 값인데 여기서 대입 해주는 값은 학습하면서 얻게된 실제 reward 값이다. 이 말은 즉슨 지금 내가 학습한 결과물과 동시에 시도하면서 얻어낸 reward 값을 비교해보면서 맞춰 나가겠다는 뜻이다. 발상의 전환이다. 방금 Learning중에 얻어낸 유의미한 데이터 값을 바로 학습에 적용했다. 특별한 사전 학습 데이터가 없이도 이런 방식으로 Cost Function을 만들어 낼 수 있다니 신기하다.


'컴퓨터공부 > 인공지능' 카테고리의 다른 글

Q-Network  (0) 2018.09.12
Q-Learning in Non-Deterministic World  (0) 2018.08.19
Q-Learning  (0) 2018.08.19
파이썬으로 AI 개발할 때 유용한 패키지 모음  (0) 2018.08.07
뉴럴네트워크(Neural Network)  (0) 2017.08.18
오버피팅(Overfitting)  (0) 2017.08.10