Q-Network

컴퓨터공부/인공지능 2018.09.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

Q-Learning in Non-Deterministic World

컴퓨터공부/인공지능 2018.08.19 13:11 Posted by 아는 개발자


그림 1.


Non Deterministic은 한가지 행동이 여러가지 결과를 만들 수 있는 환경을 의미한다. 그림1에서 빨간선은 Agent가 이동하기로 의도한 방향이고 파란선은 에이전트가 실제로 이동한 방향이다. Deterministic한 상황에서는 에이전트가 의도한 대로 항상 오른쪽으로만 이동한다. 그런데 그림 1과 같은 상황에서는 에이전트가 그림처럼 오른쪽으로도 이동할 수도 있고 위로도 이동할 수도 있다. 이처럼 한가지의 행동(Action)이 여러가지 결과를 내는 환경을 Non-Deterministic이라 부른다.


앞선 포스트에서 설명한 Q-Learning은 예전에 알고리즘 시간에 배웠던 Dynamic Programming(이하 DP)과 여러모로 유사한데 DP는 에이전트가 취한 행동이 항상 고정된 결과를 가져올 때는(Deterministic) 최적의 해를 빠르게 낼 수 있는 알고리즘이지만 여러 가지 결과를 낼 수 있는 상황(Non-Deterministic)에서는 적용할 수 없는 문제점이 있다. 마찬가지로 Q-Learning도 환경이 고정될 때는 100%에 가까운 확률로 예측을 하지만 여러가지 결과를 내는 환경에서는 학습률이 1~2% 이하로 급격하게 저하된다. 


다행이도 DP와 달리 Q-Learning 수식을 조금만 수정하면 Non-Deterministic 환경에서도 어느 정도 괜찮은 성능을 볼 수 있다. 알고리즘 설명에 앞서 우리의 현실 세계를 바라보자. 회사에 이제 막 입사한 신입 사원은 자신의 직속 상사뿐만 아니라 고과권자, 임원 그리고 다른 회사에서 일하는 학교 선배 등등 무수히 많은 멘토들로부터 조언을 듣게 된다. 이중 몇몇은 지금 당장 실행에 옮길 수 있는 조언도 있고 지금은 아니어도 미래에 해야할 조언도 있으며 감동적인 얘기지만 요즘 시대의 정서와는 맞지 않는 (꼰대 소리) 이야기도 있다. 그래서 현명한 신입 사원이라면 멘토의 조언을 곧이곧이 받아들이지 않고 필요한 것들만 적절히 취사 선택 한다.


수정된 Q-Learning에서도 동일한 방식이 적용된다. 에이전트는 행동의 보상을 그대로 업데이트 하지 말고 여러가지 결과물의 보상값을 볼 수 있도록 기존에 학습한 정보를 고집할 필요가 있다. 수학자들은 고집하는 정도를 수학 수식의 형태로 간단하지만 예술적으로 표현 해뒀다. 이미 인공지능을 공부해본 사람들은 아마 예측 했을 수도 있겠다. Linear Regression을 공부 할 때 귀에 박히도록 배운 학습률(learning rate)을 적용하면 된다. 학습률이 높을 수록 방금 취한 action의 보상 값을 많이 반영하고 낮을 수록 보상값을 무시한다. 


1. 모든 환경 데이터 값, Q(s, a)을 초기화 한다.

2. 현재 상태를 확인한다.

3. 그리고 다음의 작업을 반복한다.

- 동작을 선택할 때 랜덤 값을 포함한다.

= argmax(Q(s, a) + ramdom_value)

- 보상 값을 받는다.

- 새로운 상태 값(s')을 확인한다.

- 환경 데이터 값을 업데이트 한다

  Q(s, a) = (1 - learning_rate) * Q(s, a) + learning_rate * (gamma * reward + Max Q(s', a'),)

# 0 < learning_rate < 1


* 이 알고리즘을 사용하면 예전처럼 100%까지는 아니어도 50-60% 정도의 정확도는 보인다. 여전히 아직은 아쉬운 결과 값이다.


* 어찌보면 단순한 수식의 변형이 학습률을 이정도로 끌어올리니 신기하다. 인간의 두뇌도 생각보다 단순하게 이뤄져 있을 것 같다는 생각이 든다.

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

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

Q-Learning

컴퓨터공부/인공지능 2018.08.19 09:50 Posted by 아는 개발자

강화학습은 주변의 상태를 지속적으로 탐사해가며 미래에 주어지는 '보상' 값을 활용해 최적의 알고리즘을 찾는 학습법이다. 초기 학습데이터가 필요한 딥러닝과는 달리 초기의 학습데이터가 필요 없으며(물론 학습 데이터를 활용해서 성능을 높이기도 한다) 대신 어떤 조건에서 보상을 줄 것인지에 대한 정책과 탐사할 환경이 필요한 알고리즘이다. 국내에선 이세돌과 커제를 무참히 무찌른 알파고의 학습 알고리즘으로 알려져있다.


Q-Learning은 대표적인 강화 학습 알고리즘으로 '특정 상태에서 어떤 결정을 내리는 것이 미래 보상을 가장 높여줄 것'인지에 대한 정책 데이터를 지속적으로 업데이트 하는 알고리즘이다. 강화학습을 배울 때 가장 먼저 접하는 알고리즘이며 수학 수식들이 난무해 이해하고 싶지 않고 할 수도 없을 것 같은 위키피디아 페이지와 달리 예상외로 쉽고 차근차근 학습해나가면 누구나 배울 수 있는 알고리즘이다. 유튜브에 쉽게 풀어 쓴 강의도 많으니 심도 있게 공부하고 싶은 분들은 여기서 공부하면 좋을 것 같다.


이번 포스트에서는 Q-Learning을 아주 쉽게 풀어 쓰지는 않고 대략적인 동작 방법과 의사 코드를 정리해 수강한 강의 내용들을 정리하는데 초점을 맞추고자 한다.


그림 1.


Q-Learning의 현재 상태를 표현하면 위의 그림 처럼 테이블의 형태로 표현 할 수 있다. 현재 에이전트(학습하는 주체를 에이전트라고 부른다)가 있는 곳은 S로 표시된 곳이고 가야할 곳은 D이며 이곳에 도달 했을 때 보상을 받게 된다. H는 진입하면 죽는 곳이다.


그림 2.


처음 환경에 진입했을 때는 아무런 정보가 없기 때문에 이곳 저곳 다 다녀본다. 에이전트가 선택할 수 있는 방향은 동서남북중 하나인데 어떠한 정보가 없기 때문에 에이전트는 어느 곳을 선택해도 돌아오는 보상 값은 동일하다고 보고 랜덤하게 선택한 방향으로 이동하게 된다. 이렇게 다니면서 다니면서 홀에도 빠져 보고 이전에 지나친 경로들을 다시 다녀보기도 한다. 한마디로 삽질의 연속이다.


그림 3.


이렇게 우왕좌왕하면서 우연히 D 값에 도달 하기도 하는데 이때 에이전트는 처음으로 보상(reward)값을 받는다. 그리고 앞으로 움직이는 행동들은 앞서 초기화한 보상값을 활용해서 업데이트가 이뤄진다. 즉 이 상태에서는 특정 방향이 목적지에 도달할 확률이 높다고 가중치를 주는 작업이다. 지금까지를 의사코드로 정리하면 다음과 같다.

1. 모든 환경 데이터 값, Q(s, a)을 초기화 한다.

2. 현재 상태를 확인한다.

3. 그리고 다음의 작업을 반복한다.

- 동작을 선택하고 실행한다.

- 행동에 따른 보상 값을 받는다. reward

- 새로운 상태 값(s')을 확인한다.

- 아래의 수식으로 환경 데이터 값을 업데이트 한다

  Q(s, a) = reward + Max Q(s', a')


Q(s, a)의 의미는 상태 현재 상태가 's'이고 'a' 행동을 취했을 때 얻게 될 보상 값이다. 위 그림에서는 총 25개의 상태가 있고 각 상태별로 가능한 행동이 4개가 있으니 총 100개의 환경 데이터 값이 필요하다.


그림 4. 


위의 알고리즘은 최적의 값은 찾기는 하지만 보상값을 업데이트한 이후에는 똑같은 경로로 이동하게 되는 단점있다. 현재 상태의 보상 값을 바로 다음 상태의 보상 값으로 입력시키기 때문에 파란선으로 지나온 상태에서 최적의 보상을 주는 값이 이미 정해져 버리고 또 각 상태별 행동은 가장 높은 보상 값을 주는 것으로 선택하기 때문에 매번 동일한 경로로 이동하게 된다. 그래서 그림 4의 빨간선을 이용하면 더 빠르게 갈 수 있지만 이 경로는 보지 못하고 이전에 학습한 경로대로만 다니게 되는 단점이 있다.


이런 오류를 막기위해서 알고리즘에 두가지 노이즈를 추가한다. 미래의 보상은 시간이 지날 수록 낮춰지는 것과 행동을 선택할 때 보상값과 랜덤값을 더하는 방식이다. 두 방법 모두 에이전트에게 돌출 행동을 유도하는 일종의 트릭이다.


1. 모든 환경 데이터 값, Q(s, a)을 초기화 한다.

2. 현재 상태를 확인한다.

3. 그리고 다음의 작업을 반복한다.

- 동작을 선택할 때 랜덤 값을 포함한다.

a= argmax(Q(s, a) + ramdom_value)

- 보상 값을 받는다.

- 새로운 상태 값(s')을 확인한다.

- 환경 데이터 값을 업데이트 한다

  Q(s, a) = gamma * reward + Max Q(s', a'), # 0 < gamma < 1


노이즈를 준 부분을 굵은 글씨로 표시해뒀다. 행동을 선택 할 때 최적의 보상값 + random 값으로 선택하도록 했는데 이는 동서남북을 선택 할 때 각각의 보상값과 ramdom값을 더한 값중에서 가장 높은 값을 선택하도록 하는 것이다. 초기 알고리즘은 그림 4에서 빨간선과 파란선이 갈라지는 지점(2행 3열)에서 가장 높은 보상값을 주는 파란선을 무조건 선택하게 되는데 수정한 알고리즘은 빨간선을 선택 했을 때의 랜덤값이 더 높으면 빨간선을 선택하게 된다.


그리고 미래에 주어지는 보상은 지속적으로 감소하게 만들었다. 처음으로 받게되는 보상은 D에 도달하는 지점이었으니 빨간선과 파란선이 갈라지는 지점에서는 보상값이 꽤 많이 감가상각돼 빨간선을 택하는 것과 파란색을 택할 때의 보상값 차이가 얼마 나지 않을 것이다. 이 두가지 방법으로 에이전트는 기존 학습 데이터 값을 크게 벗어나지 않는 선에서 돌출된 행동을 유도 할 수 있다.


참고문헌


- 홍콩과기대 교수님 유튜브 강의: https://www.youtube.com/channel/UCML9R2ol-l0Ab9OXoNnr7Lw

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

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

파이썬으로 인공지능을 개발할 때 자주 사용하는 패키지 세가지를 정리해봤다.


1. Pandas


csv형태로 된 데이터 파일을 일어올 수 있는 라이브러리를 제공. 엑셀 파일을 함수 호출 한번으로 파이썬에서 사용할 수 있는 객체로 변환할 수 있다. 데이터 셋이 엑셀의 형태로 되어있는 경우가 많아 데이터 분석을 할 때 자주 사용하는 패키지중에 하나다.


import pandas pd
df_data = pd.read_excel('data.xlsx', encoding='utf-8') # 엑셀 데이터 읽어오기


리턴된 객체인 df_data에는 행을 추가하거나 삭제할 수 있는 기본적인 기능뿐만 아니라 새로운 속성을 추가하고 다른 데이터와 합칠 수 있는 기능도 제공한다. 꽤 많은 기능이 있으니 직접 사용하면서 익혀보는게 좋다


2. Numpy




파이썬에서 차트 형태로 있는 데이터를 행렬로 바꾸고 필요한 데이터만 쪽쪽 뽑아내야 할 때 numpy를 사용하면 쉽게 해결 할 수 있다. 리턴 객체 안에서 간단한 행렬 연산 뿐만 아니라 선형대수에서 자주 사용하는 행렬 연산을 제공해서 인공지능 뿐만 아니라 수치해석, 행렬연산, 기술통계에서도 자주 사용되는 패키지다. 거의 matlab에 맞먹는 사용성을 지니고 있다고 하기도.


import numpy as np
data = np.array(df_data) # df_data를 행렬 형태로 변환
select_data = data[:,5:6] # 5열만 데이터를 뽑음
transpose_data = data.transpose() # Transpose 형태로 변환


상대적으로 라이브러리가 제공이 잘되어있는 Java에서도 행렬을 이용한 작업은 언제나 까다롭기 마련인데 파이썬에는 numpy라는 유용한 패키지가 있어 비전공자들에게도 사랑 받는 것 같다.


3. Matplot



엑셀 차트만큼 강력한 파이썬 데이터 시각화 툴. 처음에는 사용하기 낯설지만 함수 몇개만 좀 외워두고 나면 갖고 있는 데이터를 몇줄 안되는 코드로 그래프로 나타낼 수 있다. 주로 Machine Learning 단계에서 자주 사용하는 툴이다. 


import matplotlib.pyplot as plt
plt.figure(figsize=(10, 10))
plt.scatter(x_test, y_test, color="black") # Test 데이터는 검은 점으로 표현한다
plt.scatter(x_train, y_train, color="red") # Train 데이터는 붉은 점으로 표현한다
plt.plot(x_test, model.predict(x_test),
            color="blue", linewidth=3) # 예측 결과는 파란 선으로 표현한다.
plt.show()


다섯줄의 코드로 Linear Regression의 결과를 시각화 할 수 있다.



뉴럴네트워크(Neural Network)

컴퓨터공부/인공지능 2017.08.18 20:45 Posted by 아는 개발자

숫자 인식 코드를 분석 할 때 이미지 사이즈의 크기는 28x28이라서 총 784개의 feature를 두어서 구할 수 있었습니다. 그런데 실제로 사용하는 이미지는 이것보다 훨씬 크기가 큽니다. 바탕화면 해상도는 1920x1020이고 여기에 색깔을 넣기 위해 3차원까지 넣어서 총 요소(Element)들의 개수는 5,875,200(1920*1020*3)개가 됩니다. 요소들의 개수만큼 feature로 놓고 학습을 시킨다면 매우 시간이 오래 걸리겠죠?


그래서 인공지능 과학자들은 다른 방법을 고안했습니다. 과학자들은 연구에서 어려움이 있을 때마다 주로 자연에서 해답을 얻곤 하는데요 인공지능 뇌과학자들은 인간의 뇌의 뉴런구조를 본따서 이 문제를 해결하기로 했습니다. 인간의 뇌가 생각하는 방식을 컴퓨터에 이식 할 수 있다면 이 문제도 쉽게 해결 할 수 있다고 본겁니다. 완전히 발상을 전환했지요?



아마 고등학교때 생물 수업을 들어보신 분은 뉴런 구조에 대해서 간단히 알고 계실 겁니다. 왼쪽 줄기로 된 부분들에서 외부의 전기 자극을 받고 이것의 종합 값이 새로운 전기 자극을 발생시킬 정도가 되는지 확인해서 자극을 전달하는 방식입니다. 이것을 좀더 수학적으로 표현하면 아래와 같습니다.




x1, x2, x3는 외부에서 온 자극의 세기를 말합니다. 그리고 g(x1, x2, x3)는 이 자극들을 어떠한 수식에 의해서 변환된 총합을 의미합니다. 최종적으로 H(x) 함수를 통해 외부의 세기로 전달할 자극의 세기를 결정합니다. 이것으로 어떤 세기로 전달할지가 결정 되는 것이지요. 여기서 g(x1, x2, x3) 이 식은 주로 직선 개별에 가중치 값을 둬서 w1*x1 + w2*x2 + w3*x3로 표현하곤 하는데요 반복적인 학습 작업을 통해서 적절한 w1, w2, w3의 값을 구하게 됩니다.


뉴런 하나 가지고 학습하고 미래를 예측하기엔 턱없이 부족합니다. 하지만 뉴런의 개수가 많다면 더 효율적으로 예측 할 수 있습니다. 실제로 뉴럴네트워크에서는 아래의 그림처럼 여러 개의 뉴런층을 나눠서 학습시킵니다.


neural network에 대한 이미지 검색결과


많은 양의 데이터와 뉴럴네트워크를 사용한 학습모델은 생각보다 '아주 잘' 작동합니다. Feature 개수가 늘어나서 도저히 학습시키기 어려워 보였던 것들도 뉴럴 네트워크를 이용해 금방 해결 할 수 있고 예측도 '생각보다 잘' 합니다. 정말 인간의 뇌를 복사한 것 같기도 합니다. 뉴럴네트워크 덕분에 이미지/음성 인식처럼 불가능해보였던 영역이 많이 발전했습니다. 특히 이미지인식은 알래스카 맬러뮤트랑 시베리언 허스키를 구분 할 수 있는 수준까지 왔다고 하네요

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

Q-Learning  (0) 2018.08.19
파이썬으로 AI 개발할 때 유용한 패키지 모음  (0) 2018.08.07
뉴럴네트워크(Neural Network)  (0) 2017.08.18
오버피팅(Overfitting)  (0) 2017.08.10
숫자인식 코드 분석해보기  (2) 2017.08.03
Softmax와 Cross entropy  (0) 2017.08.03

오버피팅(Overfitting)

컴퓨터공부/인공지능 2017.08.10 21:18 Posted by 아는 개발자

학습 능률을 높인다는 것은 비용함수(Cost function)의 값을 줄이는 것입니다. 하지만 학습에 사용하는 Feature(쎄타라고 생각하시면 됩니다)의 개수가 일정하면 Gradient Decent와 같은 최적화 작업을 통해 통해 최적의 해에 도달 했다고 해도 절대적인 비용은 어쩔 수가 없습니다.


최대한 학습 데이터를 따르는 직선을 만들었지만 그래도 비용은 어쩔수가 없네요.


그런데 우리가 직선이 아니라 볼록한 함수를 이용해서 학습한다면 어떨까요? 쎄타2를 추가하고 이때의 x는 제곱으로 본다고 합시다. 여러차례 최적화 작업을 거치면서 아래로 볼록한 함수가 나온다면 데이터의 흐름을 잘 따를 수 있을 것 같습니다. 실제로 그림으로 그려보봐도 그렇네요.


데이터 흐름을 더 잘 따라가는 것 같습니다.


실제로 계산해보면 비용함수의 값도 감소합니다. 이로써 Feature의 개수를 늘리면 학습효과가 더 증가 한다는 것을 알 수 있겠네요. 내친김에 극솟값 x축에 있는 학습 데이터도 캐치 할 수 있도록 차원을 더 올려봅시다. 이번엔 아예 다섯제곱까지 늘려보자구요.


이제는 학습에 사용된 모든 데이터들을 캐치 할 수 있게 됐습니다. 아마 비용함수의 값은 0이 나올것 같네요. 학습 성능은 가장 좋은 것으로 판단해도 될 것 같습니다만 X축에서 오른쪽으로 갈수록 값이 곤두박질 치고 있다는게 맘이 걸리긴 합니다.


만약 위 데이터의 원래 흐름이 아래로 블록한 그래프였다면 어땠을가요? 실제로 아래 그림의 노란색 데이터들이 들어온겁니다. 이런 경우 학습을 잘했다고 보기 어렵습니다. 차라리 2차원 블록한 그래프가 비용함수 값은 좀 있더라도 노란색 데이터가 들어 올 것이라고는 더 잘 예측 했을 것 같네요.


이처럼 비용함수의 값을 낮추기 위해 여러개의 Feature를 과하게 넣다보면 오히려 실제 데이터와 괴리되는 현상이 생깁니다. 분명 학습 데이터는 잘 맞추는데 실제로 보면 예측은 전혀 못하고 있는 것이지요. 이런 경우를 오버피팅(Overfitting)이라고 합니다. 학습 모델을 만들 때 위와 같은 경우를 방지하기 위해 비용함수의 수식에 Feature의 크기에 따른 변화값을 두기도 한답니다. 선형회귀에선 수식으로는 이렇게 표현해요!


파란색 원으로 그려둔 부분이 Overfitting을 방지하기 위한 값입니다. 일반적으로 쎄타의 값이 커질수록 Overfitting 발생 정도가 증가합니다. 그래서 이 값의 제곱 값을 더하면 전체 비용함수가 늘어나는 것으로 보고 학습 효과를 떨어뜨리게 되는 것이죠.


람다 값은 이때의 상수입니다. 오버핏 방지 연산에 얼만큼 비중을 둘 것인지를 결정합니다. 이 값이 커질수록 오버피팅이 하지 않게 되겠지만 낮아진다면 학습 데이터도 잘 맞추지 못하게 됩니다. 이 값이 적당할 때 가장 그럴듯한 예측을 하는 학습 모델을 만들 수 있게 됩니다.

숫자인식 코드 분석해보기

컴퓨터공부/인공지능 2017.08.03 20:49 Posted by 아는 개발자

지난 포스팅에서 인공지능 이론중 가장 간단한 Linear Regression과 Logistic Regression에 대해서 설명했습니다. 이번 포스팅에선 tensorflow 튜토리얼에 있는 숫자 인식 코드를 차근차근 분석해가며 어떻게 우리가 배운 이론이 접목되었는지 공부해보는 시간을 가지려고 합니다.


먼저 숫자 인식 코드는 여기를 공식 튜토리얼 페이지는 여기를 클릭하면 볼 수 있습니다. 


튜토리얼 페이지를 클릭하시면 MNIST라는 단어를 보실 수 있을겁니다. 이건 컴퓨터 비전에 사용되는 데이터 셋을 말하는 용어니 너무 주의깊게 보시지 않아도 괜찮아요. 그냥 이런 이미지를 가지고 있다는 것만 기억하시면 됩니다!



위의 이미지들은 우리가 숫자를 직접 손으로 쓸 때의 이미지들입니다. 우리가 만든 숫자 인식 인공지능은 고딕으로된 숫자 이미지 뿐만 아니라 여러가지 폰트로 된 숫자도 인식해야 하니까 이렇게 만들어두면 학습에 도움이 되겠죠? 우리는 이런 이미지들을 잘 학습시켜서 우리가 어떤 이미지를 넣더라도 정확한 숫자를 출력하게 하고 싶습니다.


이미지를 학습 시키는 것에 앞서 이미지를 학습에 사용될 데이터로 전환하는 작업을 해야합니다. 아마 비전공자라 하더라도 컴퓨터 이미지들은 픽셀의 형태로 이뤄져 있다는 것을 아실겁니다. 수십에서 수만개의 촘촘한 점들에 숫자 값을 대입해서 이 위치에는 검은 색을 또는 다른 위치에는 빨간 색을 표현하는것이 컴퓨터가 이미지를 보여주는 방식입니다.


왼쪽 '1' 그림을 픽셀 단위로 표현 한 것입니다.

이렇게 표현하니 거대한 행렬이라고 볼 수 있을 것 같습니다. MNIST에 있는 모든 데이터는 28x28 단위를 따르고 있습니다. 784개의 Element들을 하나로 쭉 나열하면 각 이미지가 서로 독립적이게 만들어 줄 뿐만 아니라 보기에도 훨씬 편할 것 같네요(Flattening 한다고 합니다). 이렇게 변환한 행렬은 학습 데이터로 사용하기에 매우 편리합니다.


실제 코드 상에서는 아예 784 배열로 변환한 데이터 값 자체를 한번에 받습니다. 

 
# Train
for _ in range(1000):
   batch_xs, batch_ys = mnist.train.next_batch(100)
   sess.run(train_step, feed_dict={x: batch_xs, y_: batch_ys})


학습에 사용할 input data를 만들어뒀으니 이제 학습 모델을 만들어 봅시다. 숫자 인식은 분류(Classification)작업으로 볼 수 있습니다. 그래서 여기선 Logistic Regression을 사용해야 합니다. 784개의 Element들(숫자 이미지에 있는 모든 픽셀)을 보고 특성을 분석해 10개의 분류(0~9 까지 인식해야 합니다)로 만들어주는 인공지능을 만드는 것이 목표입니다. 먼저 Logistic Regression 에 수식을 다시 살펴봅시다.




여기서 우리는 z에 해당하는 수식을 만들어야 합니다. 전에는 쎄타0, 쎄타1 만 만들어서 간단히 했었죠? 그런데 이번에는 쎄타0, 쎄타1 뿐만 아니라 쎄타784 까지 만들어야 합니다. 학습에 사용하는 input 데이터의 element가 총 784개이기 때문이지요. 계산량이 무척 많아지겠지만 그래도 컴퓨터가 대신 해줄 것이니 너무 염려하지 않도록 합시다.


output data는 크기가 10인 배열로 둘겁니다. 결과값이 3이라면 (0, 0, 0, 1, 0, 0, 0, 0, 0, 0) 요렇게 쉽게 표시 할 수 있습니다. 물론 two's complement로 더 공간 효율적으로 할 수 있긴 하지만 그렇게는 안해요. 이렇게하면 벡터로 표시 할 때 훨씬 보기 편하거든요.


입력값(X)이 1x784 로 들어 온다면 우리는 출력값(Y)을 1x10으로 내야 스펙에 맞습니다. 그러면 입력값을 처리하는 행렬(W)의 크기는 784x10이 되어야 합니다. 수학 수식으로 표현해보면 Y(출력값) = X(입력값) * W(쎄타들의 모음) + B(바이어스, 일반 상수에 해당하는 값) 로 볼  수 있습니다.


실제 코드에서도 이렇게 표현 합니다.

 
# Create the model
x = tf.placeholder(tf.float32, [None, 784])
W = tf.Variable(tf.zeros([784, 10]))
b = tf.Variable(tf.zeros([10]))
# y = xW + b
y = tf.matmul(x, W) + b
  • x는 인풋 데이터 형식입니다. C언어로 생각하면 int, char을 설정해주는 것과 비슷해요.
  • W는 쎄타들의 모음입니다. 실제로는 Weight라고 불러요. Input이 784개이고 10개의 output이 있으니 총 7840개의 Weight가 존재합니다. 지금은 모두 0으로 세팅했는데 여러번 최적화 과정을 통해서 적절한 값을 찾아가게 될겁니다. 
  • b는 Bias 값입니다. 일반상수에 해당하는 값이에요
  • y를 matmul 명령어를 이용해 정의합니다. matmul은 벡터 값의 곱을 의미합니다. 결과적으로 y = xW + b 로 표현이 되겠네요.

학습 모델까지 훌륭하게 만들었습니다. 이제 Cost function을 구하고 최적화 작업만 거치면 됩니다. 이 작업은 softmax와 cross entropy로 한방에 해결 할 수 있습니다. softmax 포스팅에서 소개한 코드를 그대로 사용하겠습니다.

 
cross_entropy = tf.reduce_mean(
    tf.nn.softmax_cross_entropy_with_logits(labels=y_, logits=y))
train_step = tf.train.GradientDescentOptimizer(0.5).minimize(cross_entropy)


tf.reduce_mean은 argument의 평균을 구해주는 작업입니다. 이렇게 cost function 구하는 모델을 만들어 두고 바로 밑에 GradientDescentOptimizer 의 minimize argument안에 cross_entropy 모델까지 넣으면 Gradient Decent 방식으로 최적화 할 수 있는 모델 까지 만들어 집니다.


하지만 이렇게 그냥 둔다고 바로 알아서 학습을 하진 않습니다. 지금까지 우리가 한 것 학습을 위한 모델을 만든 것에 불과하니까요. 함수를 정의한 후에는 호출을 해야하는 것처럼 여기도 우리가 만든 학습 모델을 실행하는 코드가 필요합니다.

 
  # Train
for _ in range(1000):
  batch_xs, batch_ys = mnist.train.next_batch(100)
  sess.run(train_step, feed_dict={x: batch_xs, y_: batch_ys})

# Test trained model
correct_prediction = tf.equal(tf.argmax(y, 1), tf.argmax(y_, 1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
print(sess.run(accuracy, feed_dict={x: mnist.test.images,
                                    y_: mnist.test.labels}))

주석으로 추천하건데 # Train 아래에 있는 부분이 학습하는 부분 인것 같지요? batch_xs, batch_ys는 학습에 쓰일 이미지 벡터 값과 실제 숫자 벡터 값을 가지고 있습니다. 그리고 바로 아래 sess.run 안의 feed_dict 안에 넣어놓지요. 첫번째 인자인 train_step은 우리가 최적화 작업까지 선언한 학습 모델입니다. 이 두 인자만 넣어주면 바로 tensorflow에 있는 함수들을 이용해서 학습이 진행됩니다.


바로 밑에의 코드는 학습한 데이터를 테스트해보는 작업이네요. correct_prediction은 예측한 값(y)과 실제 값(y_)이 동일한지를 보는 것이고 accuracy는 예측 한 값들에서 평균을 내는 작업입니다. 이것도 어떻게보면 검증하는 '모델'로 볼 수 있겠네요. 첫번째 인자로 예측 모델(accuracy)를 두고 두번째 인자에는 테스트할 이미지와(mnist.test.image)과 결과값(mnist.test.labels)을 대입해서 정확도를 측정 할 수 있습니다.


위 학습 모델로 정확도가 92% 정도 나옵니다. 생각보다 우수하죠? 그런데 딥러닝을 적용하면 정확도가 97%까지 상승한다고 합니다!


참고자료

  • https://www.tensorflow.org/get_started/mnist/beginners


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

뉴럴네트워크(Neural Network)  (0) 2017.08.18
오버피팅(Overfitting)  (0) 2017.08.10
숫자인식 코드 분석해보기  (2) 2017.08.03
Softmax와 Cross entropy  (0) 2017.08.03
Logistic Regression (로지스틱 회귀)  (0) 2017.07.31
Linear Regression (선형회귀)  (0) 2017.07.28
  1. 이용원 2019.05.21 09:45  댓글주소  수정/삭제  댓글쓰기

    0000~9999까지 4단위의 숫자를 인식하고자
    합니다.
    이미지 취득은 어떤 파일형식도 가능합니다.
    같은 글씨체 이며 같은 폰트 입니다.
    다만 환경 여건상 이미지 상태가 양호하지
    않은 경우가 있습니다.
    머신런닝을 이용한 프로그램 개발 가능 하세요?
    01047041111 이 룡원

Softmax와 Cross entropy

컴퓨터공부/인공지능 2017.08.03 20:36 Posted by 아는 개발자

학습시키는 데이터의 Feature가 3가지이고 이 데이터들을 총 3개의 분류로 나눈다고 해봅시다. 이때 우리는 하나의 feature에 대하여 총 3가지로 분류해줄 weight값이 필요합니다. 만약 데이터의 Feature들을 x1, x2, x3라고 표현하면 x1이 첫번째 분류, 두번째 분류 그리고 세번째 분류로 나눠 질 수 있도록 값을 조정하는 weight값이 필요하게됩니다. 그림으로 표현하면 더 알아보기 쉽습니다.



x1, x2, x3의 집합을 X, Wi,j값의 집합을 W, bi의 집합을 B로 표현하면 위 식은 S = Wx + B로 표현 할 수 있겠네요. 그리고 이 값이 가장 큰 것으로 분류되게 됩니다.


하지만 학습을 하려면 내가 낸 결과물이 얼마나 비슷한지도 알아야합니다. 내가 고른 값이 옳다 하더라도 50% 확률로 맞췄는지, 70% 확률로 맞췄는지에 따라서 얼만큼 잘 맞추고 있는지 확인 할 수 있으니까요. 이때 출력된 데이터 값(S라고 하겠습니다)을 0~1 사이의 값으로 표현해주는 방법이 softmax입니다. 식으로 표현하면 이렇습니다.


추측하는 분류의 S exponential 값에서 전체 S exponential 합을 나눠주는 방식입니다. 만약 S값이 2, 1, 0으로 나왔다면 softmax를 거친다면 0.7, 0.2, 0.1로 변형됩니다. 그래도 2가 가장 큰 것은 변함이 없죠? 단지 70%의 확률로 맞췄다고 보게 되는거지요. 학습데이터에 얼마나 가까워졌는지 정도를 보여주는 방법입니다. 이렇게 데이터를 보는 방식을 바꾸면 나중에 Weight값을 조정할 때 큰 도움이 됩니다.



이 값을 토대로 비용함수를 구하는 방식이 Cross entropy입니다. 위키 백과에 있는 세부 이론까지 세세히 들어가면 너무 복잡하니 간단히 식과 여기에 무엇을 대입해야 할지만 알아보겠습니다.


위 식을 보면 p(x)와 q(x)가 있는데요 여기서 우리는 p(x)에 실제 분류 값을 쓰고 q(x)는 softmax 결과값(Y)를 대입하게 됩니다. 요렇게요



좀더 정확하게 맞출 수록 H(p,q)의 값이 감소하게 됩니다. 즉 위 값, 비용 총합을 최소화하는 것이 위 작업의 목표지요. 이것도 Gradient Descent 방식으로 최적화가 이뤄집니다. 하지만 이건 생략하고 느낌만 가져가죠. 나머지는 tensorflow해서 해줄거니까요. 그냥 이렇게 작동하는구나 정도만 알고 갑시다.


tensorflow에서는 softmax_cross_entropy_with_logits 함수로 한방에 끝내버립니다.

 
 tf.nn.softmax_cross_entropy_with_logits(labels=y_, logits=y))


참고자료

  • https://www.tensorflow.org/get_started/mnist/beginners


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

뉴럴네트워크(Neural Network)  (0) 2017.08.18
오버피팅(Overfitting)  (0) 2017.08.10
숫자인식 코드 분석해보기  (2) 2017.08.03
Softmax와 Cross entropy  (0) 2017.08.03
Logistic Regression (로지스틱 회귀)  (0) 2017.07.31
Linear Regression (선형회귀)  (0) 2017.07.28

Logistic Regression (로지스틱 회귀)

컴퓨터공부/인공지능 2017.07.31 21:49 Posted by 아는 개발자

앞선 포스팅에서 나이에 따른 연봉 변화로 선형 회귀를 설명했었습니다. 이번에는 예시를 조금 변형해서 연봉이 5000만원이 넘는지 안넘는지를 결정하는 함수를 생각해봅시다. 먼저 연봉이 5000만원을 넘지 않는 경우를 0, 넘는 경우를 1로 생각하고 그래프를 그려볼까요?



y축의 값이 0과 1밖에 없으니 그래프가 상당히 단조로워졌네요. 아마 30-32 사이에서 연봉이 5000만원으로 변화하는 지점이 있는 것 같습니다. 이 정보를 토대로 선형회귀를 해보면 아래 그림처럼 추세선을 만들어 줄 수 있을 것 같습니다.



대략 추세선의 값이 0.5 정도가 넘으면 연봉이 5000만원이 넘는다고 짐작 할 수 있겠네요. 이렇게 하면 뭐 더이상 손댈 것도 없을것 같습니다. 그런데 새로운 학습 데이터가 추가됐다고 해봅시다. 요렇게요.



55세 57세 데이터가 들어오면서 기울기가 낮아져버렸습니다. 아까처럼 y축 값이 0.5 가 넘을때 연봉이 5000만원이 넘을 것이라고 단언하면 30-32세 사이의 데이터를 커버 할 수 없게 됩니다. 골치아프네요. 그렇다고 기준 값을 0.4로 내리자니 다른 데이터로 학습 한 후에는 또 달라질 것이고 머리가 아픕니다. 모든 경우를 커버 해줄수가 없죠.


이런 분류(Classification)의 문제는 선형 회귀로 해결 할 수 없습니다. 차라리 특정 지점을 지나면 분류 되는 것으로 정하면 편할 것 같네요. 인공지능에서도 이렇게 두 가지 경우를 분류합니다. 이때 사용하는 회귀 방법이 Logistic Regression 입니다. 여기서 특정 임계치를 지날 때의 값을 표현하는 함수가 여러가지 있는데요 가장 대표적인 Sigmoid 함수에 대해서 알아봅시다.



그래프를 보니 x축이 증가하는 방향은 1로 수렴하고 감소하는 방향은 0으로 수렴하네요. 쉽게 x>0 인 구간은 1이고 x<0인 구간은 0으로 정의 할 수 있을것 같습니다. 우리는 식을 살짝 변형시켜서 특정 입력값이 0 보다 큰 경우에는 분류가 참인 경우로, 그렇지 않은 경우에는 거짓인 경우로 나눠볼 수 있습니다.



처음보는 수식이 나왔죠? 쎄타 위에 T자가 붙어있습니다. 이건 행렬에서 transpose라는 개념입니다만 지금 설명하면 길어지니 바로 오른쪽 그림처럼 이것이 지난 포스팅에서 배운 선형 방정식과 동일하다는 것만 확인하죠. 이렇게 식을 만들면 결국 z 값에 따라서 분류 기준이 결정되고 z는 곧 우리가 세운 선형 방정식이 됩니다. 우리는 다시 가장 그럴듯한 쎄타 값만 찾아주면 되겠네요.


선형회귀에서 쎄타 값을 찾기 위해 어떻게 했는지 기억 나시나요? 네 맞습니다. 비용 함수를 만들어 내고 여기에 Gradient Descent라는 기법을 적용해 여러번 반복해 가장 우수한 쎄타 값을 찾아 낼 수 있었습니다. 여기도 방식은 똑같습니다. Logistic 회귀에 해당하는 비용 함수를 만들고 이 함수에 Gradient Descent를 여러번 반복해 쎄타값을 찾아낼 수 있습니다. Logistic 회귀의 비용함수는 다음과 같아요



수학자들이 이렇게 하면 가장 좋다는 것을 이미 밝혀 냈으니! 증명하는 것은 생략합시다. 위 수식으로 우리가 설정한 쎄타값이 얼마나 학습 값을 잘 맞추고 있는지 확인 해 볼 수 있어요. 그리고 위 수식에 Gradient Descent를 적용해서 가장 우수한 쎄타값을 구해 낼 수 있답니다. 이것도 증명은 생략하고 수식만 보고 갈까요? 



선형회귀에서 했던 것처럼 Logistic 회귀에서도 위의 수식을 반복 적용해서 훌륭한 쎄타 값을 구해 줄 수 있습니다. 너무 위 식에 신경쓸 필요 없습니다. 어차피 Tensorflow가 모두 계산해 줄 거니까요 하하하. 그냥 느낌만 가져갑시다!


그런데 여기서 의문이 하나 생기네요. 지금껏 우리는 두가지 경우로 분류하는 것만 생각했습니다. 하지만 실제로는 아래 그림처럼 여러가지 경우로 분류하게 되는 경우가 생깁니다. 이런 경우는 어떻게 해야할까요?



방법은 생각보다 간단합니다. 분류 작업을 각각의 군집 마다 세번 실행하면 됩니다. '이것 아니면 나머지는 다 무효로 처리해!' 방법을 쓰는거지요. 아마 그림을 보시면 바로 감이 올겁니다.



첫번째 그림에서 파란색 군집과 나머지를 모두 검은색으로 생각했습니다. 그러면 파란색에 대해서는 확실히 구해 줄 수 있겠지요? 시계방향으로 이어지는 노란색과 초록색도 각각의 색깔에 대해서 만큼은 분류를 확실히 해줄 수 있었습니다. 각각의 분류 기준을 모두 합하니 각 기준에 대해서 분류를 해줄 수 있게 되었네요.


결국 여러 경우에 대해서 분류를 하는 것은 한 군집 집단에 대해서만 Logistic 회귀를 해주면 되는 것으로 귀결됩니다. 정말 유용한 함수죠? 다음 포스팅에선 지금까지 배운 것들을 이용해 손글씨를 판별하는 Tensorflow Tutorial 코드분석을 해보도록 하겠습니다!


* 참고한 자료


Coursera Machine Learning Andrew Ng 강의자료 - https://www.coursera.org/learn/machine-learning/

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

뉴럴네트워크(Neural Network)  (0) 2017.08.18
오버피팅(Overfitting)  (0) 2017.08.10
숫자인식 코드 분석해보기  (2) 2017.08.03
Softmax와 Cross entropy  (0) 2017.08.03
Logistic Regression (로지스틱 회귀)  (0) 2017.07.31
Linear Regression (선형회귀)  (0) 2017.07.28

Linear Regression (선형회귀)

컴퓨터공부/인공지능 2017.07.28 20:50 Posted by 아는 개발자

앞선 포스팅에서 우리는 인공지능이란 '대량의 데이터를 학습해 가장 그럴듯한 미래를 예측한다'고 정의했습니다. 그리고 여기서 우리 개발자가 할 일은 대량의 데이터를 훌륭하게 학습시키는 알고리즘을 만드는 일이라고 말씀드렸습니다. 이제 학습 알고리즘에 대해서 공부해봐야겠죠? 마음은 벌써 알파고에 쓰인 딥러닝을 짜보고 싶지만, 지금 당장은 해볼 순 없으니 가장 기초적인 학습법인 선형회귀(Linear Regression)부터 천천히 공부해봅시다.


우리에게 아래 표처럼 나이에 따른 연봉 데이터가 있다고 가정해봅시다


실제데이터는 아닙니다. 제가 가공한거에요 헤헤


언듯 데이터를 분석해보니 나이가 많을수록 연봉을 더 많이 받는것 같습니다. 한번 차트로 볼까요?


그래프 상으로 표현해보니 실제로도 그러하네요. 위 자료를 통해 나이에 따라서 연봉을 대강 추측 해볼 수 있을 것 같습니다. 나이가 32살이라면 대강 4천 3백만원에서 5천만원 사이인 4천 6백만원 정도 받을거라고 생각 해볼 수 있겠네요. 하지만 이런 식으로 하면 좀 야매인 느낌이죠? 위 데이터를 간단히 선형 방정식으로 표현한다면 좀더 일관성 있고 훌륭하게 예측 할 수 있을 것 같네요.


엑셀에 있는 추세선 기능을 활용해 선형 방정식을 추가해봤습니다. 나이 값에 따라 연봉을 추출 할 수 있으니 더 신뢰성이 가는 데이터입니다. 좀더 전문적인 느낌이죠? 정말 별거 아닌것 같지만 이것은 인공지능의 가장 기본적인 연산작업입니다. 이렇게 짜잘한 일련의 작업들이 쌓여서 더 복합한 것들을 예측하는 작업이지요.


자 그러면 이제 가장 그럴듯한 일차 방정식을 구해봅시다. 아마 위에서 우리는 차트로 그려보고 대강 짐작했을 뿐이지 실제로는 어떻게 구해야 할지 감이 안올겁니다. 따로 이걸 구할 수 있는 방정식이 있는 것도 아니구요. 그래도 괜찮습니다. 좀 번거롭지만 그래도 컴퓨터를 이용하면 훌륭하게 구할 수 있습니다.


기본적인 선형 방정식의 수식은 이렇습니다.



여기서 두 θ(쎄타라고 부르겠습니다) 값이 어떻냐에 따라서 그래프의 모형이 결정됩니다. 우리는 학습 데이터에 가장 근접한 두 쎄타 값을 구하는것이 목표입니다. 가장 손쉽게 해볼 수 있는 방법은 랜덤 값을 막 넣어보고 가장 그럴듯한 모형을 찾는 겁니다만 이렇게 한다면 시간이 엄청 오래 걸리겠지요? 컴퓨터도 이정도 연산을 커버할 만큼 빠르지 못합니다.


마구잡이로 대입해가며 선형 방정식을 만들기 전에 한 번 생각해봅시다 우리가 구한 선형 방정식이 학습 데이터와 얼마나 근접한지를 식으로 어떻게 표현 할 수 있을까요? 가장 간단한 방법은 우리가 만든 선형 방정식이 추출한 값과 실제 데이터 값의 차이를 확인해보는 방법일 겁니다. 여기서 값의 차이의 제곱의 합을 식으로 표현해봅시다.


m: 데이터의 개수, x: 나이값, y: 연봉, h: 선형방정식 입니다


대충 이렇게 만들면 우리가 만든 선형 방정식의 효율을 측정 해 볼 수 있을것 같습니다. 위의 식은 인공지능에 비용함수(cost function)이라 부릅니다. 아마 가장 좋은 선형방정식은 비용함수의 값이 가장 낮은 방정식일 겁니다. 


위의 그래프는 쎄타 값의 변화에 대한 비용함수 그래프입니다. 볼록볼록한 산능선 같은것이 둘쭉날쭉합니다. 지도상의 십자가 포인터는 현재 우리가 있는 지점이고 우리가 가야할 지점, 비용 함수가 가장 낮은 지점은 z 값이 가장 낮은 지점 즉 별표로 표시된 부분입니다. 이때의 쎄타값들을 구해 줄 수 있다면 가장 훌륭한 선형 방정식을 만들어 낼 수 있을것 같습니다.


이건 'Gradient Descent'라는 방법을 이용해서 가능합니다. 먼저 수식을 보여드릴게요!


여기서 α는 Learning Rate라고 합니다


위의 수식은 두개의 쎄타 값이 수렴 할 때 까지 반복하라고 되어 있습니다. 반복하는 작업은 비용함수의 편미분값 곱하기 알파 값을 기존 쎄타 값에서 빼주는 것을 계속 반복하는 방식입니다. 이렇게만 설명하면 감이 잘 오지 않죠? 다시 그래프로 돌아가봅시다


비용함수에서 쎄타0 값을 일반 상수로 놓고 Θ과 비용에 대한 그래프를 그려봅시다. 그러면 아래와 같이 볼록한 이차원 그래프가 만들어질겁니다(위 비용함수 그래프에서 특정 쎄타0를 축으로 자른다고 생각해보세요!)


여기서 노란 십자가는 현재 저희가 있는 지점입니다. 빨간 십자가 지점에 가까워 질수록 비용 값은 작아지겠죠? Gradient Descent 방법은 한번에 최적의 지점에 도달하진 못하지만 반복작업을 통해 최적의 지점에 도달 할 수 있게 해줍니다. 위의 수식을 1회 적용한 그래프는 아래와 같습니다.



비용함수를 쎄타에 대해서 미분한 값은 그 지점의 접선 기울기와 같습니다(고등학교때 다 배웠습니다) Gradient Descent 방법대로 기울기에 α값을 곱한 값을 기존 쎄타값에 빼주면 그래프는 최적점과 조금 더 가까워지게 됩니다. 이 방법을 여러번 반복하면 점점더 그래프가 최적점에 가까워지겠죠?


       


쎄타 0와 쎄타 1 각각에 대해서 위 작업을 반복하면 최적의 선형 방정식을 구해 낼 수 있게됩니다. 단 여기서 주의해야 할 점이 있습니다. Learning Rate라 말씀드린 α값을 어떻게 정하느냐에 따라서 학습 속도 및 성공의 유무가 결정됩니다. 만약 이 값이 너무 크거나 혹은 너무 작으면 어떻게 될까요?



왼쪽 그림은 α값이 너무 큰 경우에 해당합니다. 이때는 기존 쎄타 값이 너무 급격하게 변해 오히려 비용함수의 값이 더 증가하는 방향으로 움직이고 있네요. 이런 경우는 차라리 안하느니만 못합니다.


오른쪽그림은 α값이 너무 작은 경우입니다. 이때는 비용함수의 값이 감소하는 방향으로 이동하는데 이동하는 크기가 너무 느립니다. 한 두번이면 되는 학습 횟수를 몇배 더 해야하니 학습에 소요되는 시간이 오래 걸리게 됩니다. 그래도 비용함수가 증가하는 방향은 아니니 시간이 많다면 충분히 최적점에 도달 할 수 있겠네요


적당한 Learning Rate 값을 세팅하고 두 쎄타값을 구해내는 과정이 Linear Regression입니다. 생각보다 복잡한 수학 지식이 적용되진 않았지요? 고등학교 수학 + 편미분 만 알고 있으면 충분히 따라 갈 수 있을 정도입니다. 앞으로 배울 Logistic Regression도 이와 큰 차이는 없습니다! 다음 포스팅에선 이거랑 비슷한 Logistic Regression에 대해서 배워보도록 합시다

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

뉴럴네트워크(Neural Network)  (0) 2017.08.18
오버피팅(Overfitting)  (0) 2017.08.10
숫자인식 코드 분석해보기  (2) 2017.08.03
Softmax와 Cross entropy  (0) 2017.08.03
Logistic Regression (로지스틱 회귀)  (0) 2017.07.31
Linear Regression (선형회귀)  (0) 2017.07.28