1. 심층 신경망(Deep Neural Network)

 이번 포스팅에서야 제대로 Deep한 개념이 나오게 된다. Deep하다는 것은 입력층과 출력층 사이에 은닉층(Hidden Layers)이 많이 껴있어 입력층과 출력층 사이가 Deep하다는 의미이다. 그렇다면 왜 딥러닝일까? 직관적으로 이해하기 위하여 아래 그림을 보면, 여러 비선형 변환기법의 조합을 통해 높은 수준의 추상화가 가능하다는 것을 알 수 있다. 일반적으로 깊은 층을 가질 수록 더욱 복잡한 표현이 가능하다고 알려져있다. 


출처: 장교수의 딥러닝


 심층 신경망은 Perceptron을 여러개 쌓은것 처럼 보인다 하여 다층 퍼셉트론(Multi-layer Perceptron)이라고도 한다. 그러면 단층 퍼셉트론에서 진행한 순서대로 심층 신경망을 설계해보자.


Step 1. 모델 설계


 아래 그림은 심층신경망의 예이다. 입력층 $x$가 있고, $L-1$개의 은닉층(Hidden Layers) $h$가 있고, 마지막에 출력층 $\hat{y}$이 있다. 일반적으로 Layer의 개수를 셀 때는 입력층을 제외하고 센다. 엄밀히 말하면 출력층 $\hat{y}$은 $h_{L}$이라 할 수 있다. 윗 첨자($^{[n]}$)는 각 Layer에서의 원소 인덱싱이 될 것이고, 입력층에서는 feature가 된다. $n_{i}$는 $i$번째 Layer의 원소 개수를 뜻한다. 심층신경망 모델을 프로그래밍 할 때, 파라미터 행렬들($W, B$)의 크기가 많이 헷갈리므로 잘 기억해두길 바란다.



 출력층 $h_{L}$을 제외한 모든 층에서는 Relu함수를 활성화 함수로 사용하겠다. 또한, 이해하기 쉽게 각 층을 Linear Function과 Activation Function 두개로 나누어 생각하겠다. 오류 역전파(Step 3)에서 설명할테지만 $\frac { \partial J }{ \partial W } =\frac { \partial J }{ \partial z } \frac { \partial z }{ \partial W }$으로 $dW$를 구하기 위함이다. 하여, 은닉층에서의 Forward propagation의 일반식은 $h_{i+1}=relu(W_{i+1}h_{i}+B_{i+1})$이 된다.



 이번 실습도 Cat vs Dog 데이터셋에서 수행할 것이므로 출력층에서 Label의 개수 $n_{L}$은 1개이다. 따라서 출력층의 활성화 함수는 이진분류에 적합한 $sigmoid$ 함수를 사용하겠다. 출력층의 일반식은 $\hat{y}=h_{L}=sigmoid(W_{L}h_{L-1}+B_{L})$이 되겠다.


Step 2. 손실함수 정의


 전체 학습데이터에 대한 손실함수($J$)는 하나의 데이터에 대한 손실함수 ($L$)의 평균으로 정의할 수 있다. 전체 시스템은 데이터의 수 만큼(문제의 수) 총 $m$번의 학습이 진행될 것이다. 


$$J=\frac{1}{m}\sum _{ i=0 }^{ m-1 }{ \mathcal{L}(y^{i}, \hat{y}^{i}) } $$

$$\mathcal{L}= −ylog(\hat{y})−(1−y)log(1−\hat{y}))  $$


Step 3. 오류 역전파(Backpropagation)로 미분식 풀기 


 아마 오류 역전파(Back propagation)이라는 것을 많이 들어봤을 것이다. Step1에서 입력->출력 방향으로 전파되는 것을 Forward propagation라고 했었다. 반대로 미분식을 풀기 위해서는 출력->입력 방향으로 수식이 전개 되는데 이것을 Back propagation 라고 한다. 단일퍼셉트론과 마찬가지로 손실함수 $J$를 최소화 하는 미분식부터 구하게 된다. 사실 단일퍼셉트론을 이해했다면 심층 신경망 유도는 쉬울것이다. 

 먼저 하나의 데이터에 대한 손실함수 $\mathcal{L}$를 최소화 하는 $L-1$층의 파라미터의 편미분값을 구해보자. 아래 그림에서 Back propagation방향은 빨간색으로 그렸다.  단일퍼셉트론에서 했던 최적화 과정과 동일하게 $\frac{\partial \mathcal{L}}{\partial z_{L-1}} $을 구할 수 있으며 연쇄법칙으로 $\frac{\partial \mathcal{L}}{\partial B_{L}} $과 $\frac{\partial \mathcal{L}}{\partial W_{L}} $을 구할 수 있다. Back propagation을 위해 다음 Layer에 넘길 $\frac{\partial \mathcal{L}}{\partial h_{L-1}} $ 또한 요구된다. 



 아래는 은닉층에서의 Back propagation에 대한 설명이다. 출력층->$i_{th}$Layer까지 전파(propagation)가 이루어졌다면 $\frac{\partial \mathcal{L}}{\partial h_{i+1}} $의 값을 넘겨받았을 것이다. $Relu(x)$함수의 미분은 $1(x>0)$ 또는 $0(x\leq 0)$이 된다. 나머지 파라미터 ($W, B$)는 위와 동일하게 진행된다. 개념은 그리 어렵지 않을 것이다. 여기서 눈치가 좋은 사람이라면 $Relu(x)$의 미분이 0을 반환하는 것에 주목할 것이다. 이것이 저번 포스팅에서 설명한 "Dying Relu Problem"이다.



Step 4. 행렬식으로 풀기


 이제 모든 $m$개의 데이터를 한번에 트레이닝 하기 위하여 벡터화(Vectorization) 하면 아래와 같이 모든 Layer가 행렬을 이루게 된다. 역시 우리가 할 실습에 따라서 그림은 $n_{L}=1$로 그렸다. 아래 그림에서 대괄호아래첨자($[]_{i}$)는 데이터 순번 인덱싱이다. 



위의 모델을 Back propagation 하게되면 아래와 같이 되는데 자세한 설명은 동영상 강의를 참고하길 바란다. 




동영상 강의: 준비중...

1. 활성화 함수

 활성화 함수(Activation Function)는 신경학적으로 볼때 뉴런발사(Firing of a Neuron)의 과정에 해당한다고 볼 수 있다. 최종출력 신호를 다음 뉴런으로 보내줄지 말지 결정하는 역할을 하게 된다.


Firing of a neuron 출처: Andrii Vodolazhskyi via Shutterstock


 뉴런이 다음 뉴런으로 신호를 보낼 때 입력신호가 일정 기준 이상이면 보내고 기준에 달하지 못하면 보내지 않을 수도 있다. 그 신호를 결정 해주는 것이 활성화 함수(Activation Function)라 이해하면 된다. 많은 종류의 활성화 함수가 있고, Activation function의 결정이 결과에 크게 영향을 준다. 하나하나 알아보도록 하자.


- 선형함수 (Linear Function)

 선형함수는 말 그대로 직선적인 함수($y=x$)이다. 결론부터 말하면 Linear Function를 활성화 함수로 하게되면 "Deep"한 네트워크의 이점이 전혀 없다는 것이다. 아래의 2-Layer 모델을 예로 들어보자.



 2개의 Layer를 쌓아봤지만 $X$에 곱해지는 항들은 $W$로 치환가능하고, 입력과 무관한 상수들은 전체를 $B$로 치환 가능하기 때문에 $WX+B$라는 Single layer perceptron과 동일한 결과를 낸다. 다시말해 Deep 하게 쌓는 의미가 없어진다.


linear Function


- 계단함수 (Step Function)

 입력이 양수일때는 1(보낸다)을 음수일때는 0(보내지 않는다)의 신호를 보내주는 이진적인(Binary) 함수이다. 직관적으로는 상당히 좋다. 0이상이면 출력하고 0이하면 뉴런을 죽이고 하지만 우리가 모델 Optimization과정에서 미분을 해야하므로 미분이 되지않는 이녀석은 쓸 수가 없다.


Step Function


- Sigmoid Function 

 지난 포스트04 단일퍼셉트론에서 사용했던 활성화 함수이다. 입력을 ($0, 1$) 사이의 값으로 normalize해준다.  과거에 상당히 인기가 있었던 활성화 함수이다. sigmoid의 수식과 그 미분은 아래와 같다.


$$sigmoid(x)=\frac { 1 }{ 1+{ e }^{ -x } } $$

$$\frac { d }{ \partial x } sigmoid(x)=\frac { 1 }{ 1+{ e }^{ -x } } \left( 1-\frac { 1 }{ 1+{ e }^{ -x } }  \right)$$


 아주 아름답게$(A'=A(1-A))$로 미분이 되어 코드로 구현하기가 쉽다. 이런 완벽해보이는 매력적인 함수지만 문제점이 있다. 바로 Gradient Vanishing인데 아래의 tanh함수부터 소개하고 설명하겠다. $x$가 0일때 기울기가 최대가 되는데, 그 미분값이 $\frac{1}{4}$이다. 딥러닝을 하기 위해서는 Layer를 많이 쌓아야 하는데 이렇게 작은 미분 값은 에너지함수 최적화 과정에서 Layer을거쳐갈 때마다 곱하기 연산을 거쳐 deep할 수록 기울기가 사라져 버리는 Gradient Vanishing을 야기 시킬 수 있다. 1~2개의 Layer에서는 사용할 수 있겠지만 Deep한 학습법에서 사용하는 것은 추천하지 않는다. 


Sigmoid Function


- tanh Function

 sigmoid fuction을 보완하고자 나온 함수이다. 입력신호를 ($-1, 1$) 사이의 값으로 normalization 해준다. 거의 모든 방면에서 sigmoid보다 성능이 좋다. 수식은 아래와 같다.


$$tanh(x)=\frac { { e }^{ x }-{ e }^{ -x } }{ { e }^{ x }+{ e }^{ -x } } $$

$$\frac{d}{dx}tanh(x)=1-tanh(x)^{2}$$


 기울기가 최대인 $x$가 0인 지점의 미분값은 1이 된다. 그럼에도 불구하고 Gradient Vanishing문제가 발생하게 된다. sigmoid 함수보다는 덜함


Tanh Function



Gradient Vanishing

 sigmoid와 tanh함수 모두 $x$가 0일때 기울기가 최대가 되는데, 그 미분값이 $sigmoid'(0)=\frac{1}{4}, tanh'(0)=1$이다. 학습을 더 잘 하기 위해서는 Layer를 많이 쌓아야 하는데 이렇게 작은 미분 값은 에너지함수 최적화 과정에서 Layer을 거쳐갈 때마다 곱하기 연산을 거쳐 deep할 수록 기울기가 사라져 버리는 것이 Gradient Vanishing이다. 아래의 deep 모델이 있다고 하자.



 backpropagation에 따라 $\frac{dY}{dw_{1}}$을 구하면,


$$\frac { dY }{ d{ w }_{ 1 } } =\frac { dY }{ dh_{ n } } \frac { dh_{ n } }{ d{ h }_{ n-1 } } ...\frac { dh_{ 2 } }{ dh_{ 1 } } \frac { dh_{ 1 } }{ d{ w }_{ 1 } } $$


 Hidden Layer와 Hidden Layer사이에 미분을 하게 되면 활성화 함수의 미분이 반드시 들어가게 되는데 1이하의 실수가 n번 곱해지면 결국에는 0으로 수렴하게 될 것이다. 비슷한 문제로 미분값이 1 이상이면 Gradient Exploding문제가 발생하는데 이것 또한 1이상의 실수가 $n$번 곱해져 발산해버리는 것이다.


- ReLU Function (Rectified Linear Unit)

 현재 가장 인기있는 활성화 함수인 ReLu는 양수에서 Linear Function과 같으며 음수는 0으로 버려버리는 함수($Relu(x)=max(0, x)$)이다. 우선, 기울기(미분값)가 0 또는 1의 값을 가지기 때문에 Sigmoid Function에서 나타나는 Gradient Vanishing 문제가 발생하지 않는다. 언뜻 보기에는 Linear Function과 같은 문제가 없을까 생각이 들 수 있지만 엄연히 Non-Linear함수 이므로 Layer를 deep하게 쌓을 수 있다. 또한 exp() 함수를 실행하지 않아 sigmoid함수나 tanh함수보다 6배 정도 빠르게 학습이 된다고 한다. 

Relu Function

[블로그 관리] -> [꾸미기] -> [스킨편집] ->[html 편집]에서 태그 안에 다음 script 코드를 복붙한다.


다음은 CSS파일 편집창에 가서 다른 class나 id 선언에 곂쳐지지 않게 아래의 코드를 삽입한다.

.jbMenu {
    text-align: right;
 `  background-color: none;
    width: 100%;
    position: fixed;
    top: 70%;
}
.jbFixed {
    position: fixed;
    top: 70%;
}

 파일 업로드창에서 우리가 원하는 사진을 업로드 하고, 링크주소복사를 한다.



마지막으로 html에서 <body> 태그 안에 사진을 넣어야 한다. <body> 바로 아래에 다른 div에 들어가지 않도록 다음 코드를 붙여넣자.


    <div class="jbMenu">

    <a href="클릭할때 넘어가는 주소"><img src="사진이 저장된 경로" style="width:10%"></a> 


위에서 링크 주소 복사한 것"사진이 저장된 경로"에 붙여주고 나처럼 클릭했을 때, 내 유투브 채널로 이동하려면 "클릭할때 넘어가는 주소" 부분에 링크를 복사해주면 된다.



 아... 그런데 코드의 div에 가려진다. 해결한분들은 알려주시길 바란다.



'잡 기술 > Tistory' 카테고리의 다른 글

[Tistory] 티스토리 움짤 프로필 만들기  (0) 2018.08.09

 포토샾으로 만든 GIF파일을 블로그 프로필로 할 수 없을까? 생각을 해봤다.


 [블로그 설정]에서 프로필에 GIF 파일을 넣어도 티스토리는 움짤 영상으로 인식하지 못한다. Tistory 어플리케이션이 애니메이션 영상을 허용하지 않는다는 뜻이다. 그러면 직접 HTML 언어를 만져야 한다.



 [블로그 관리] -> [꾸미기] -> [스킨편집] ->[html 편집]으로 들어가보자



 그러면 꼴보기 싫은 코드창이 뜰것이다. 거기서 파일 업로드에 가서 GIF 파일을 업로드 시킨다.


 파일을 업로드를 하게되면 아마 Tistory 서버 내부의 본인 계정에 할당된 저장소에 파일이 올라갈 것이다. 링크 주소 복사로 절대경로를 가져오도록 하자.



다시 HTML창으로 돌아와서 블로그 내부에 내 프로필이 어디있는지 찾아야 한다. 내 경우에는 (적용한 블로그 테마스킨에 따라 상이할 수 있음) 블로그 이미지 모듈이라는 주석 아래에 선언되어 있었다. 여러분들이 찾을때는 https://tistory1.daumcdn.net/tistory/2935792/attach/ac8257c8b59f42199ee875db8628904b 이것을 src로 하는 <img> 태그를 찾으면 될듯하다. ctrl+f 해서 찾으셈


 

 image 태그를 찾아서 src를 아까 복사했던 링크로 바꿔주면 빵코네 블로그처럼 움짤 프로필이 가능해진다. 

'잡 기술 > Tistory' 카테고리의 다른 글

[Tistory] 티스토리 스크롤 고정 이미지 넣기  (0) 2018.08.10

 딥러닝 포스트 04까지 이해하는 것을 권장한다.


 이진분류(Binary Classification)를 목적으로 한 단층퍼셉트론(Single Layer Perceptron)을 만들어보자. 데이터셋은 Kaggle의 cat vs dog Conpetition에서 제공하는 데이터셋을 사용했다. 링크

 

Cat images

     Dog images


 모델을 설계하기에 앞서 영상의 구성요소는 가로(width), 세로(height), 색깔(RGB)이 있다. 데이터셋에 있는 영상이 각각 다른 크기를 가지고 있어 가로, 세로를 ($100 \times 100$)으로 통일시켜주었다. 개와 고양이 영상이 각각 $12,500$장씩 있는데 우리는 간단한 모델을 학습하니 개와 고양이 영상을 각각 $300$장으로 샘플링하여 학습데이터로 삼고, 개와 고양이 각각 $100$장씩을 테스트데이터로 하겠다. 데이터는 CSV 파일로 관리하는 것이 좋은데 다음 포스트를 참고하길 바란다. ---> 링크(작성중..)


 이번 실습은 맛보기용이므로 간단하게 모델을 설계하겠다. ($100 \times 100 \times 3$)의 영상을 ($30,000 \times 1$)의 벡터로 펼쳐 입력층으로 만들어준다. 그러면 아래와 같은 단일퍼셉트론 모델을 설계할 수 있다. 수식은 04 포스팅과 동일하게 사용하겠다.



 여기서 대문자로 표기한 것들($W, X, B$)은 행렬식이며 각각의 크기는 아래와 같다. ($m$은 학습 데이터 영상의 개수)


$$ W, dW: (30,000 \times 1) $$

$$ X: (30,000 \times m) $$

$$ Y, \hat{Y}: (1 \times m) $$

$$ B, dB: 1 $$


 이제 본격적인 코딩을 시작하겠다. 필요한 Python Library는 (numpy, pandas, matplotlib.pyplot, PIL) 이다. 적당히 구글링해서 까시고.. 필요한 라이브러리를 importing하자.


import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from PIL import Image



Training dataset( cat0.png ~ cat299.png $+$ dog0.png ~ dog299.png )

Test dataset( cat300.png ~ cat399.png $+$ dog300.png ~ dog399.png )

 위의 데이터 정보가 임의로 섞여있는 csv 파일을 읽어들이고 parsing한다.



train.csv

data=pd.read_csv('train.csv', parse_dates=['file_name', 'label', 'str' ])
data_test=pd.read_csv('test.csv', parse_dates=['file_name', 'label', 'str' ])

 csv파일이 성공적으로 읽혔는지 확인해보자. 
 np.shape(data) 함수는 data의 크기를 반환해주는 함수다. 학습데이터는 ($600, 3$)을 반환하겠고 테스트데이터는 ($200, 3$)을 반환한다. 
 data.head() 함수는 data의 제일 위에 있는 몇개의 원소를 출력창에 보여주는 함수이다.

num_train = np.shape(data)[0]
num_test = np.shape(data_test)[0]
print('training dataset: '+str(num_train))
print('test dataset: '+str(num_test))
data.head()


 설계한 모델로 학습을 진행하기 위해 모든 영상을 ($100 \times 100$) 크기로 만들어줘야 한다. 이번 실습에서 사용할 영상들을 resize() 함수로 크기를 통일시켜주자. 나는 원본영상과 resizing한 영상을 동일한 폴더에 넣었으므로 확장자(.png)로 구분했다.


# resize training dataset
for i in range(0, num_train): 
    im = Image.open(data.file_name[i]+".jpg")
    im = im.resize((100, 100))
    im.save(data.file_name[i]+".png")

# resize test dataset for i in range(0, num_test):      im = Image.open(data_test.file_name[i]+".jpg")     im = im.resize((100, 100))     im.save(data_test.file_name[i]+".png")
print('Resizing done')

  Resizing이 잘 되었는지 확인해보자. PLT 라이브러리의 imshow() 함수를 사용하면 좌표평면에 영상을 출력할 수 있다.

index = 6
im = Image.open(data.file_name[index]+".png")
plt.imshow(im)
num_px = np.shape(im)[0]*np.shape(im)[1]*np.shape(im)[2]



 위에 정리한 행렬 크기에 맞게 $X$와 $Y$를 선언해주고, 모든 영상을 펼쳐 $X$에 넣고 정답 Label을 $Y$에 넣는다.

 ($100 \times 100 \times 3$)영상에 reshape(-1) 함수를 적용시키면 모든 픽셀 정보가 일렬로 펼쳐지는 $30000$개의 배열을 반환한다. 

 X[:, i]=im은 i번째 Column에 배열 im을 할당하는 것을 의미한다.

 RGB 3개의 채널이 각각 8bit로 표현이 되며 $0$~$255(2^{8})$ 사이의 값을 가진다. 입력을 0~1 사이로 정규화 하기 위해 행렬 $X$의 모든 원소를 255로 나누어준다.


# for train
X=np.zeros((num_px, num_train))
Y=np.zeros((1, num_train))

for i in range(0, num_train): 
    im = Image.open(data.file_name[i]+".png")    
    im = np.asarray(im)
    im = im.reshape(-1)
    X[:, i] = im
    Y[:, i] = data.label[i]
X=X/255.

# for test
X_test=np.zeros((num_px, num_test))
Y_test=np.zeros((1, num_test))

for i in range(0, num_test): 
    im = Image.open(data_test.file_name[i]+".png")    
    im = np.asarray(im)
    im = im.reshape(-1)
    X_test[:, i] = im
    Y_test[:, i] = data_test.label[i]
X_test=X_test/255.

print('Done!')

 앞으로 자주 쓰게 될 Sigmoid 함수를 외부함수로 정의해주자.

def sigmoid(a):
    y = 1/(1+np.exp(-a))
    return y

 이제 학습을 시작할텐데 딥러닝 포스트04에서 도출해낸 아래의 수식대로 코드를 짜서 경사하강법대로 파라미터를 업데이트 한다. predict 변수는 학습데이터의 최종학습 결과


W=np.zeros((num_px, 1))
B=0
Y_hat=np.zeros((1, num_train))
predict=np.zeros((1, num_train))

# training start
iter = 2000
for i in range(0, iter):
    # forward
    Y_hat = sigmoid(np.dot(W.T, X)+B)      
        
    # backward
    dW = 1/num_train*np.dot(X, (Y_hat-Y).T)
    dB = 1/num_train*np.sum(Y_hat-Y, axis=1)
    
    # update parameters
    learning_rate = 0.005
    W = W-learning_rate*dW
    B = B-learning_rate*dB

    # print cose
    if i % (iter/5) == 0:
        cost = -np.sum(Y*np.log(Y_hat)+(1-Y)*np.log(1-Y_hat))/num_train
        print('cost: ' + str(cost)+ '\t-> ('+ str(i) +' iter)')
cost = -np.sum(Y*np.log(Y_hat)+(1-Y)*np.log(1-Y_hat))/num_train
print('cost: ' + str(cost)+ '\t-> ('+ str(i) +' iter)')


 학습이 완료되었다. 우선 학습데이터가 얼마나 잘 학습되었는지 학습데이터의 정답($Y$)과 최종적으로 도출된 결과($\hat{Y}$)를 threshold(0.5) 하여 정확도를 구해보자. 

for i in range(0, num_train):
    if Y_hat[0, i] > 0.5:
        predict[0, i] = 1
    else:
        predict[0, j] = 0  
print("train accuracy: {} %".format(100 - np.mean(np.abs(predict - Y)) * 100))


 약 94%로 나름 기대할만한 결과가 나왔다. 다음으로 앞서 따로 구분했던 테스트 데이터를 퍼셉트론 모델에 통과시켜서 정확도를 계산해보자.

predict_test=np.zeros((1, num_test))
Y_hat_test = sigmoid(np.dot(W.T, X_test)+B)
for i in range(0, num_test):
    if Y_hat_test[0, i] > 0.5:
        predict_test[0, i] = 1
    else:
        predict_test[0, i] = 0

print("test accuracy: {} %".format(100 - np.mean(np.abs(predict_test - Y_test)) * 100))


 쓰레기 같은 결과가 나왔다. 단일퍼셉트론의 한계이다. 테스트 결과를 시각적으로 확인하기 위해 아래 코드의 index값을 임의로 정하여 돌려볼 수 있다.

index = 149
A = getim(index)
label = labeling(A)
print('predict: '+str(label) + '\nAnswer: '+str(data_test.str[index]))

 

 딥러닝의 조상격인 Perceptron에 대한 이해를 충분히 했으리라 믿고 다음 실습에서는 Multi-Layer Perceptron을 구현해보도록 하겠다.


 이전 포스팅과 더불어 Window10 환경임을 알려드립니다.


 Anaconda Prompt에서는 tensorflow가 import 되지만 Jupyter에서 No module named 'tensorflow' 에러가 뜨는것을 해결하고자 한다.



 Jupyter에서 tensorflow를 인식하지 못하고 No module named 'tensorflow'를 내뿜는 이 문제는 Jupyter과 tensorflow가 Python을 실행하기 위한 경로가 서로 다르기 때문이다. Python이 실행되고 있는 경로는 sys 라이브러리의 executable 변수를 확인하면 알 수 있다.

 내 컴퓨터를 기준으로 Jupyter에서 Python으로 접근하는 경로는 C:\ProgramData\Anaconda3\python.exe 이다.




 Anaconda Prompt에서 확인한 가상개발환경에서 Python으로 접근하는 경로는 C:\ProgramData\Anaconda3\envs\tensorflow\python.exe 이다.


(base) C:\Users\bbangko>activate tensorflow

(tensorflow) C:\Users\bbangko>python

Python 3.6.6 |Anaconda, Inc.| (default, Jun 28 2018, 11:27:44) [MSC v.1900 64 bit (AMD64)] on win32

Type "help", "copyright", "credits" or "license" for more information.

>>> import sys

>>> print(sys.executable)

C:\ProgramData\Anaconda3\envs\tensorflow\python.exe

>>>



 Jupyter는 tensorflow 모듈에 접근하지 못하는 경로를 가리키고 있는 것을 확인 할 수 있다. 이 문제를 내가 이해한 것으로 그려보면 왼쪽의 그림과 같다. Jupyter가 Tensorflow 안에 있는 Python을 가리킬 수 있도록 해야한다. 그 방법은 Jupyter의 커널을 추가하는 것이다. virtualenv 커널 이라고 한다. 



 Jupyter의 커널을 추가하기 위해 Jupyter의 경로를 jupyter --path 명령어로 확인해보자. 


(tensorflow) C:\Users\bbangko>jupyter --path

config:

    C:\Users\bbangko\.jupyter

    c:\programdata\anaconda3\envs\tensorflow\etc\jupyter

    C:\ProgramData\jupyter

data:

    C:\Users\bbangko\AppData\Roaming\jupyter

    c:\programdata\anaconda3\envs\tensorflow\share\jupyter

    C:\ProgramData\jupyter

runtime:

    C:\Users\bbangko\AppData\Roaming\jupyter\runtime


 Jupyter의 데이터는 C:\Users\bbangko\AppData\Roaming\jupyter 여기에 있는것을 알 수 있다. 커널을 추가할 폴더를 만들도록 하자. (폴더 만들기 mkdir)


(tensorflow) C:\Users\bbangko>mkdir C:\Users\bbangko\AppData\Roaming\jupyter\kernels\tensorflow


 jupyter의 kernels 폴더에 kernels.json파일을 만들어준다. 메모장이나 notepad++ 사용


kernels.json

{

 "argv": [ "/ProgramData/Anaconda3/envs/tensorflow/python", "-m", "ipykernel", "-f", "{connection_file}"],

 "display_name": "tensorflow",

 "language": "python"


 argv 경로는 컴퓨터마다 다를 수 있으니 본인들 컴퓨터에서의 python 경로를 확인하자.


(tensorflow) C:\Users\bbangko>where python

C:\ProgramData\Anaconda3\envs\tensorflow\python.exe

C:\ProgramData\Anaconda3\python.exe


 이렇게 하고 Jupyter을 켜보면 New항목에 tensorflow라는 새로운 커널이 생긴 것이다. New -> Python 3로 하면 기존의 Python경로를 사용하는 파일이 생성됨


 

 tensorflow를 import해서 오류없이 출력되면 성공!




'잡 기술 > Tensorflow' 카테고리의 다른 글

[Tensorflow] Window에서 Tensorflow를 설치해보자  (0) 2018.08.04

 Tensorflow는 구글에서 개발한 데이터 흐름 프로그래밍을 위한 오픈소스 소프트웨어 라이브러리이다. 제공되는 프로그래밍 언어로는 Python과 c++이 있는데 나는 Python을 쓰도록 하겠다.


내 노트북 스펙:

OS: Window10 (x64)

CPU: Intel(R) i5-6200U

GPU: NVIDIA GeForce 940M

RAM: 8GB



설치 순서참고: 괄호() 안에 있는 버젼은 내가 받은 버젼이다.


Step 0. GPU로 돌릴사람만!

 만약 GPU를 사용하여 Tensorflow를 돌려보고 싶다면 CUDA와 cuDnn을 받아야 한다. (CUDA-9.2.148-win10, cuDnn-9.2-win10-x64-v7.1)


CUDA 다운로드 링크: https://developer.nvidia.com/cuda-downloads?target_os=Windows&target_arch=x86_64

cuDnn 다운로드 링크: https://developer.nvidia.com/cudnn


CUDA는 실행파일을 받아서 깔면 되고, 

cuDnn은 압축을 풀어 bin, include, lib 폴더를 아래의 경로에 넣어준다


 “C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v9.2”


Step 1. 아나콘다(Anaconda)를 깔자


 다운로드 링크: https://www.anaconda.com/download/


 위의 다운로드 링크로 가서 .exe파일 (Anaconda3-5.2.0)을 받아 설치를 한다. 아나콘다를 설치하면 알아서 Python (Python 3.6.5)이 깔리므로 따로 안받아도 된다. 


 

Anaconda가 설치 되었으면 시작메뉴에서 Anaconda Prompt를 실행하여 Python을 쳐보자. 


(base) C:\Users\bbangko>python

Python 3.6.5 |Anaconda, Inc.| (default, Mar 29 2018, 13:32:41) [MSC v.1900 64 bit (AMD64)] on win32

Type "help", "copyright", "credits" or "license" for more information.    

>>>           


이렇게 >>> 모양이 뜨면 정상적으로 Python이 설치가 된 것이다.


Step 2. 텐서플로우(tensorflow)를 깔자


 아나콘다 안에서 가상개발환경을 만들어주고, 그 안에 텐서플로우를 깔아야 한다. CPU버젼과 GPU버젼을 따로 설치하고 싶다면 -gpu를 추가해서 구분 지어줍시다.


conda create -n tensorflow python=3.6 

conda create -n tensorflow-gpu python=3.6


 이렇게 하면 가상개발환경 폴더가 만들어진다. 해당 개발환경을 활성화 시키기 위해서는 activate 개발환경이름 명령어를 사용하면 된다.


그러면 각각의 가상개발환경 안에 tensorflow를 깔아주자.


CPU용 Tensorflow

(base) C:\Users\bbangko>activate tensorflow

(tensorflow) C:\Users\bbangko>pip3 install --ignore-installed --upgrade tensorflow



GPU용 Tensorflow

(tensorflow) C:\Users\bbangko>activate tensorflow-gpu

(tensorflow-gpu) C:\Users\bbangko>pip3 install --ignore-installed --upgrade tensorflow-gpu 



Step 3. Tensorflow를 테스트 해보자


 먼저 CPU용 Tensorflow부터 테스트 해봅시다. 아래 코드를 따라 쳤을때 오류 없이 출력이 된다면 성공!


(base) C:\Users\bbangko>activate tensorflow

(tensorflow) C:\Users\bbangko>python

Python 3.6.6 |Anaconda, Inc.| (default, Jun 28 2018, 11:27:44) [MSC v.1900 64 bit (AMD64)] on win32

Type "help", "copyright", "credits" or "license" for more information.

>>> import tensorflow as tf

>>> hello=tf.constant("Hello Wolrd!")

>>> sess=tf.Session()

2018-08-04 19:43:46.857283: I T:\src\github\tensorflow\tensorflow\core\platform\cpu_feature_guard.cc:141] Your CPU supports instructions that this TensorFlow binary was not compiled to use: AVX2

>>> print(sess.run(hello))

b'Hello Wolrd!'

>>>


python에서 cmd명령으로 나가려면 Ctrl+Z 인터럽트를 걸어줍시다


 다음 GPU


(tensorflow) C:\Users\bbangko>activate tensorflow-gpu

(tensorflow-gpu) C:\Users\bbangko>python

Python 3.6.6 |Anaconda, Inc.| (default, Jun 28 2018, 11:27:44) [MSC v.1900 64 bit (AMD64)] on win32

Type "help", "copyright", "credits" or "license" for more information.

>>> import tensorflow as tf

>>> hello=tf.constant("Hello Wolrd!")

>>> sess=tf.Session()

                                                                                     ...

Found device 0 with properties:

name: GeForce 940M major: 5 minor: 0 memoryClockRate(GHz): 1.176

                                                                                     ...

>>> print(sess.run(hello))

b'Hello Wolrd!'

>>>

 

 메세지 중간에 GPU이름이 뜨면서 잘 작동하는 것을 확인하면 성공!


Step 4. 쥬피터(Jupyter)도 써봅시다.


 코딩할때 콘솔창에 한줄 한줄 쓸 수는 없잖슴? 코드를 이쁘게 파일로 관리하기 위해 Jupyter라는걸 써야한다. 다행이도 Anaconda를 설치하면 Jupyter도 같이 깔리니 참으로 다행이다. Jupyter를 실행하는 명령어는 jupyter notebook 이다.


(base) C:\Users\bbangko>activate tensorflow

(tensorflow) C:\Users\bbangko>jupyter notebook

[I 19:59:38.379 NotebookApp] JupyterLab beta preview extension loaded from C:\ProgramData\Anaconda3\lib\site-packages\jupyterlab

[I 19:59:38.380 NotebookApp] JupyterLab application directory is C:\ProgramData\Anaconda3\share\jupyter\lab

[I 19:59:38.847 NotebookApp] Serving notebooks from local directory: C:\Users\bbangko

[I 19:59:38.847 NotebookApp] 0 active kernels

[I 19:59:38.848 NotebookApp] The Jupyter Notebook is running at:

[I 19:59:38.848 NotebookApp] http://localhost:8888/?token=faf573e56c15b7568c52adf8c192727bce39e0c957152cba

[I 19:59:38.848 NotebookApp] Use Control-C to stop this server and shut down all kernels (twice to skip confirmation).

[C 19:59:38.851 NotebookApp]


    Copy/paste this URL into your browser when you connect for the first time,

    to login with a token:

        http://localhost:8888/?token=faf573e56c15b7568c52adf8c192727bce39e0c957152cba&token=faf573e56c15b7568c52adf8c192727bce39e0c957152cba

[I 19:59:39.914 NotebookApp] Accepting one-time-token-authenticated connection from ::1


 아래를 보면 로그인 토큰도 던져주는데 기본브라우저가 아닌 크롬에서 작업하고 싶다면 토큰을 크롬의 주소창에 복붙하면 된다. 그리하면 아름다운 UI의 Jupyter가 뜰것이다. 



 우측상단의 new를 눌러 앞으로 코딩 작업을 할 폴더(Folder) workspace를 만들어줍시다. (경로는 님들 마음대로) 그리고 python코드를 작성할 파일 .ipynb 을 new->Python3를 눌러 생성해보자. 




 in [ ] : 블록 안에 tensorflow를 import해주는 코드를 작성해보자. 그러면 아래와 같은 에러메세지가 뜨게 될것이다. 뜨지 않으면 땡큐하고 그냥 쓰면 된다. 이 에러를 해결하기 위한 포스트는 다음글을 참고하길 바란다.



 이제 신나게 코딩 해봅시다. 화이팅!


1. 퍼셉트론(Perceptron)


 언젠가 후배와 SF영화 이야기를 하다가 컴퓨터로 인간의 뇌를 모방하여 가상뇌를 구현했다는 소리를 들었었다. 어떻게 뉴런 하나하나를 만들어서 뇌를 모방했을까? 반신만의 했었는데 지금 내 눈앞에 있네 ㅋ 하나의 퍼셉트론은 인간의 뇌의 뉴런 하나에 해당한다고 이해하면 된다. 수많은 뉴런들이 우리의 뇌를 구성하고 있듯 딥러닝을 이해하기 위한 가장 기본적인 개념인 퍼셉트론에 대해 아라보자. 




 퍼셉트론 하나로만 이루어진 모델을 단층 퍼셉트론(Single Layer Perceptron)이라고 하며 이는 입력을 두 부류로 나누는 것이다. 단층 퍼셉트론은 선 하나로만 데이터의 경계를 구분지을 수 있다. 어려운 말로 선형분류  

 중학교때 배운 직선 방정식을 떠올려보면 $y=ax+b$라는 익숙한 방정식을 떠올릴 것이다. 그럼 고등학교에서 배운 평면 방적식은 어떤가? $y=ax+by+cz+d$이다. 직선 방정식에 $z$차원이 추가되니 직선이 3차원으로 쌓여 평면을 이룬 것이다. 앞으로 우리는 3차원 이상의 다차원 공간에서 함수를 정의할 것이다. 이렇게 n개의 일차변수들로 이루어진 함수를 초평면(Hyper Plane)이라고 한다. 

 아래는 단일 퍼셉트론의 예시이다. $x_{0}, ..., x_{n-1}$는 입력데이터이고 이것을 행렬로 표현(벡터화, Vectorization)하면 $x$라 할수있다. 우리가 얻어야할 파라미터 $w_{0}, ..., w_{n-1}$는 각각 $x$의 원소에 곱해져야 한다. 파라미터 또한 벡터화 하여 $w$로 표기할 수 있다.

$$x=\{x_{0}, ..., x_{n-1}\}, w=\{w_{0}, ..., w_{n-1}\}$$

 $b$는 편향(Bias)이다. 입력 $x$를 파라미터 ($w, b$)로 변형을 시켜 활성화 함수(Activation Function) $\sigma$를 거치며 $\hat{y}$를 출력한다. Activation Function에 대한 자세한 설명은 다음 포스트에서 하겠다. 

 


 주어진 입력 $x$으로 학습된 파라미터 $w$를 이용하여 $wx+b>0$이라면 Class 1이 할당되고, $wx+b<0$이라면 Class 2에 할당되도록 할 수 있겠다. 이제 선형분류라는 용어가 직관적으로 다가올 것이다. 그러면 최적의 $w$를 찾아보자.


 그러면 종이를 한장씩 꺼내서 간단한 예제를 풀어봅시다. 지난 포스트(#03)를 이해하지 못했다면 따라오지 못할 수 있다. 활성화 함수 $\sigma$가 무식하게 생겨서 겁을 먹을 수 있지만 관대한 눈길로 넘어가주자. Training data는 $m$개의 데이터와 특징 $x$와 정답 $y$로 이루어진 테이블이다. 



Step 1. 손실함수 정의


 전체 학습데이터에 대한 비용($J$)은 하나의 데이터에 대한 손실함수 ($L$)의 평균으로 정의할 수 있다. 전체 시스템은 데이터의 수 만큼(문제의 수) 총 $m$번의 학습이 진행될 것이다. 현재의 $w$을 사용하여 도출해 낸 결과 $\hat{y}$과 실제 정답 $y$와의 오차를 평균 낸 것이다. 손실함수 $L$은 교차 엔트로피 오차를 사용하였다. 위의 문제는 여자($\hat{y}=0$)인지 남자인지($\hat{y}=1$) 두개의 클래스(Label)를 결정짓기 위한 것이므로 Cross entropy가 좋다.


$$J=\frac{1}{m}\sum _{ i=0 }^{ m-1 }{ L(y^{i}, \hat{y}^{i}) } $$

$$L= −ylog(\hat{y})−(1−y)log(1−\hat{y})  $$


Step 2. 미분식 풀기


 경사하강법(Gradient Descendent)을 하기 위해 손실함수($L$)에 대해 파라미터로 미분한 $\frac { dL }{ dw } $와 $\frac { dL }{ db } $를 구해야 한다. (여기서 $i$는 학습 횟수 $i$번째 학습)

$$\overset { i+1 }{ w } =\overset { i }{ w } -\alpha\nabla \frac { dL }{ d\overset { i }w }, \overset { i+1 }{ b } =\overset { i }{ b } -\alpha\nabla \frac { dL }{ d\overset { i }b } $$

 하지만 함수 $L$ 안에서는 $w$가 보이지 않는다. 이때 필요한 것이 고등학교 미분시간에 배운 연쇄법칙(Chain Rule)이다. (여기서 $i$는 데이터의 인덱스 쉽게말해 순번)

$$ \frac { dL }{ dw } =\frac { d{ L } }{ d\hat { y }^{ i }  } \frac { d\hat { y }^{ i }  }{ dw } = \frac { d{ L } }{ d\hat { y }^{ i }  } \frac { d\hat { y }^{ i }  }{ dz^{ i } } \frac { dz^{ i } }{ dw } $$

$$\frac { d{ L } }{ dB  } = ... =\frac { d{ L } }{ d\hat { y^{ i } }  } \frac { d\hat { y }^{ i }  }{ dz^{ i } } \frac { dz^{ i } }{ dB } $$


 위와 같이 미분식을 정리했다면 미분식을 하나하나 전개해보도록 하자. 

$$\frac { dL }{ d\hat { y^{i} }  }=-\frac { y^{ i } }{ \hat { y } ^{ i } } +\frac { 1-y^{ i } }{ 1-\hat { y } ^{ i } } $$

$$\frac { d\hat { y^{i} }  }{ dz^{i} }=\sigma(z^{i})(1-\sigma(z^{i}))=\hat{y}^{i}(1-\hat{y}^{i}) $$

$$ \frac { dz^{i} }{ dw }=x^{i}, \frac { dz^{i} }{ dB }=1 $$


 $\sigma$의 미분은 아래에 있으니 심심하신 분들은 한번 안보고 풀어보시길ㅋ



 이제 모두 합쳐보쟈. 행렬식으로 표현할 수도 있다. 행렬식으로 정리할때의 장점은 다음 실습 포스트에서 설명하겠다. 


$$\frac { dL }{ dw }=\frac { 1 }{ m }\sum {(\hat{y}^{i}-y^{i})x^{i}} = \frac { 1 }{ m }X^{T}(\hat{Y}-Y)$$

$$\frac { dL }{ dB }=\frac { 1 }{ m }\sum {(\hat{y}^{i}-y^{i})x^{i}} = \frac { 1 }{ m }(\hat{Y}-Y)$$


 이렇게 $\frac { dL }{ dw }$와 $\frac { dL }{ dB }$를 구했다면 여러번 반복(Iteration)하면서 Gradient Descendent 공식에 맞도록 $w$와 $b$를 Update해주면 된다. 여러~번 반복하다보면 수렴할텐데 그러면 학습이 완료된 것으로 판단하고 학습이 잘 되었는지 시험(Test)을 치뤄야 한다. 당연히 시험에는 정답($y$)이 없다. 아래의 임의의 행인의 키와 몸무게로 성별을 판별하는 Test를 진행할 수 있다. 물론 최종 출력물인 $\hat{y}$의 값은 sigmoid함수를 통과하면서 $0$~$1$사이의 float값이 나오는데 0.5를 기준으로 $\hat{y} > 0.5$이면 여자($\hat{y}=0$), $\hat{y}<=0.5$이면 남자($\hat{y}=1$)라고 해준다. Threshold 라고 함





동영상 강의: 준비중...

1. 최적화


 우리가 시험공부를 할때 어떻게 하는가? 시험에 나올만한 문제를 풀어본 후 채점도 하고 오답노트도 써가며 학습(Train)을 할 것이다. 공부를 하면서 모의 시험을 봤는데 50점이 나오면 마음편히 잘것인가? 조금 더 공부를 할 것인가? 몇사람 제외하고는 대부분 밤을 새서라도 공부를 더 할 것이다. 머신러닝도 마찬가지로 내가 설계한 모델과 실제 데이터와의 차이가 얼만큼 나는가 채점 해보는 것이 필요하다. 에너지함수(Energy Function)라고도 하며 손실함수(Loss Function)라고도 하며 비용함수(Cost Fucntion)라고도 하는데 모델의 출력정답을 대조해가며 채점하는 과정이다. 채점결과 만족스러운 결과가 나오면 학습을 멈추게 된다.


Slide by 마음의소리 at Naver Webtoon


 간단하게 손실함수(Loss function)를 정의해 보자면 $\mathscr{L}=(y-f(x))^2$ 라고 할 수 있겠다. $y$는 정답이고, $f$는 내가 설계한 모델이며, $x$는 시험문제가 되겠다. 뉘앙스로 볼 때 손실($\mathscr{L}$)이라는 것은 최소가 되어야 좋은 것이라 할 수 있다. 오차가 클 수록 손실이 많아지고, 오차가 적을수록 손실이 적어져 $\mathscr{L}$을 최소화 하는 모델이 강제된다. 2차함수로 손실함수를 정의한 까닭은 손실함수를 최소화 하기 위해서는 오목하거나 볼록한 모양의 함수꼴(Convex Function)이 되어야 한다. 


Slide by Wikipedia


 자주 사용하는 에너지 함수를 소개해본다. 학습 데이터는 총 $n$개이며 $i$는 데이터의 순서이다. 평균제곱 오차는 가장 직관적인 함수로 오차가 작으면 에너지가 낮아지는 것을 한번에 알 수 있다. 


1) 평균 제곱 오차, MSE(Mean Squared Error) 

$$\mathscr{L}=\frac { 1 }{ n } \sum _{ i=0 }^{ n-1 }{ { \left( y^{i}-f(x^{i}) \right)  }^{ 2 } } $$


 교차 엔트로피의 경우는 알아서 최대우도추정(Maximum Likelihood Estimation) 방법을 찾아보면 되겠다. 간단히 설명하면 우도(Likelihood)를 Bernoulli 분포로 표현하여 음수를 취한 형태이다.


2) 교차 엔트로피 오차, CEE(Cross Entropy Error)

$$ \mathscr{L}=-\sum _{ i=0 }^{ n-1 }{ \log { (f(x^{i})) } *y^{i} }  $$


2. 경사하강법(Gradient Descendent)


 최소화 하는 방법으로는 경사하강법(Gradient descendent)이 대표적이다. 말 그대로 경사를 따라 하강하여 수렴(Converge)할 때까지 반복(iteration)을 수행한다. 고등수학에서 배운 미분을 생각해보자. 기울기가 +라는 것은 증가하는 함수라는 의미이고, 기울기가 -라는 것은 감소하는 함수라는 의미이다. 그렇다면 함수를 최소화 하는 극점으로 가기 위해서는 기울기의 반대방향으로 가야한다. 극점에 수렴(Convergence)하여 시험결과에 만족했다면 학습을 마칠것이다.


 수식으로 표현하면 ${ x }_{ i+1 }={ x }_{ i }-\alpha \nabla { x }_{ i }$이다. $x$는 학습할 대상(파라미터)이며 $i$는 반복횟수를 뜻하고 $\alpha$는 학습률(Learning Rate)이라 하여 학습이 반영되는 정도를 뜻한다. 학습률이 너무 크면 수렴하지 않고 무한루프(진동)상태에 빠질 수 있는데 훗날 다시 설명하도록 하겠다.


3. Local Minimum


 수치해석 분야에 있어서 Local Minimum은 골머리 썩는 문제다. 아래 그래프에서 시스템 전체에 대한 해인 Global Minimum에 다다르기를 기도하며 모델을 만들었을 것이다. 하지만 어느위치에 Global Minimum이 있는지 알 수 없으므로 우리는 시작점을 임의로 결정할 수 밖에 없다. 만약 시작점이 A에 잡혔으면 땡큐하고 Global Minimum의 해로 찾아들어갈 것이다. 하지만 시작점이 B로 잡히게 되면 Local Minimum에 수렴하여 아무리 여러번 반복(Iteration)하여 학습을 한다해도 제대로 된 학습이 불가능할 것이다. 이를 해결하기 위해서는 초기값을 잘~ 잡아줘야 하는 수밖에 없다. 


 추가로 2014 NIPS에서 Dauphin이 말하기를 딥러닝과 같은 고차원 모델에서는 Local minimum이 아닌 안장점(Saddle Point)의 구조에서 정착이 발생한다 밝히고 이를 해결하는 알고리즘을 제시했었다. 참고하길 바란다. 



"Identifying and attacking the saddle point problem in high-dimensional non-convex optimization." NIPS2014, Dauphin, Yann N., et al


동영상 강의: https://www.youtube.com/watch?v=1tGxvS5Y4uM

1. 특징(Feature)


 아래 그림을 보자. 뽀족한 귀와 귀여운 조동이와 날개와 다리를 보고 개새 라는 것을 우리는 알 수 있다. 지난 포스트에서 말한 특징(Feature)이라는 것이 바로 이런 것이다. 특징은 그 동안 우리가 경험적으로 학습한 대상들의 부분적인 조각들이며 우리는 특징들을 조합함으로써 대상을 분별한다. 만약 다리와 날개의 특징만 가지고 위의 사진을 보았다면 개새라고 판별할 수 없을 것이다. 즉, 대상의 정확한 판단을 위해서는 적절한 특징을 정의해야 한다. 


개새


 선형회귀(Linear Regression)를 예를 들어 봅시다. 선형회귀를 간단하게 표현하자면 우리나라의 유서깊은 얼중의 하나인 붕당정책과 비슷하다. 선 하나를 가지고 2가지 클래스를 나누는 것이다. 어느 선을 기준으로 이쪽은 아군 저쪽은 적군 인것이다. 

 남고생 10명과 여고생 10명을 구분하기 위한 특징으로 체중과 키를 사용한다면 어느정도 일반화할 수 있을 것이다. 허나 아직 2차성징이 오지 않은 초등학교 저학년들을 대상으로 한다면 아래 그림과 같이 제대로 구분하지 못할것이다. 노란선을 기준으로 아래에 위치한 데이터는 여자(뻘겅색), 위에 위치한 데이터는 남자(퍼렁색)로 구분한다. 기존의 20명으로만 학습된 모델(노랑 선)을 가지고 성별을 모르는 전학생(초록색)의 성별을 판별할 수 있을까? 정답은 여러분의 마음속에



 데이터를 다루는 분야에 자주 언급되는 차원의 저주(Curse of Dimensionality)라는 용어가 있다. 위의 그래프를 예시로 들면 두가지의 특징이 사용되었고 각 특징은 하나의 차원(그래프의 축)을 이루며 직교하는 두 선분의 평면위의 점 하나가 하나의 데이터(학생한명)라고 할 수 있다. 즉, 특징의 개수가 차원의 크기라 할 수 있다. 데이터를 표현하는 차원(Feature)이 많으면 많을수록 대상을 더욱 정밀하게 표현할 수 있고 분류하기가 수월해진다. 하지만 무작정 차원이 크다고 다 좋은것만은 아니다. 차원이 크면 클수록 데이터를 학습하는 것이 복잡해지고 보다 많은 데이터가 필요하다. (차원이 증가될 수록 $2^n$배의 학습데이터가 필요함)

 초딩 20명을 키(x축)와 몸무게(y축)로만 구분하면 선 하나로 구분이 힘들었었다. "여자아이들이 남자아이들보다 머리카락이 길다." 라는 가정 하에 위의 분포에 머리카락 길이(z축)의 Feature만 추가해준다면 더욱 좋은 구분이 가능해질것이다. 3차원에서는 선 방정식 -> 평면방정식 이된다. 3차원 이상의 $n$차원에서는 초평면(Hyperplane)이라 한다.



2. 학습(Learning)은 어떻게 이루어질까요?


1. 지도학습(Supervised Learning)


 지도학습은 학습할 때, 사람이 학습 데이터의 정답(Label)을 알려주고 학습 모델이 학습 데이터가 정답(Label)에 가까워지도록 조정해가며 학습을 진행한다. Supervisor는 사전적으로 감독자 라는 의미로 감독자가 문제의 정답(Label)을 알려주면서 학습을 진행한다는 것이다. 감독자의 역할을 하기 위해 사람이 데이터 하나하나 정답(Label)을 달아줘야 하므로 여간 귀찮은 작업이 아닐 수 없다. 하물며 오버피팅이라는 문제를 피하기 위해 학습 데이터의 양이 어마어마하다. 지도학습은 어떤 데이터가 어떤 Label을 가지는지 분류(Classification)하는 것이 특징이다. 


Slide by Wikipedia


2. 비지도학습(Unsupervised Learning)


 지도학습과는 반대로 감독자가 없는 정답(Label)이 필요 없는 학습법이다. "선생은 필요없어 나 혼자 한다" 이런 느낌 예를들어 지네, 돈벌레, 파리 사진을 비지도학습 시킨다고 해보자. 어떤 사진에 무슨 벌레인지 정답(Label)을 알려주지 않았기 때문에 이 사진이 어떤 벌레인지 컴퓨터가 정의 할 수 없다. 하지만 비슷한 단위로 벌레들을 묶어 군집화(Clustering) 할 수 있다. 다리가 많은 돈벌레와 지네를 한 분류로 묶고, 날개의 유무로 파리를 또 다른 분류로 나누어 놓을 것이다. 




3. 강화학습(Reinforcement Learning)


 주로 게임이나 로봇제어같은 최적의 동작을 찾는데 쓰는 학습 방식이다. 상과 벌이라는 보상(reward)을 주며 상을 최대화하고 벌을 최소화 하도록 하는 학습하는 방식이다. 마치 우리가 어릴적 잘못을 하면 벌을 받고 잘 하면 칭찬받는 것 처럼 많은 시행착오를 경험하고 그에 따른 대처법을 학습하는 것이 강화학습이다. 우리는 지금까지의 행동들에 대해 옳고 그름을 판단 받으며 특정 행동에 대한 옳고 그름을 스스로 결정 할 수 있게 되었다. 이러한 시행착오를 겪으며 경험이 쌓이고, 확실하게 경험했던 것에 대해서는 옳고 그른지 판단 할 수 있으며 실수도 잘 하지 않는다. 하지만 여전히 경험해보지 못한 부분에 대해서는 대처능력이 현저히 떨어지게 된다. 이전 포스트의 알파고 제로가 이에 해당한다.


Slide by DeepMind Technologies Limited



영상강의: https://www.youtube.com/watch?v=TfSLdjDjZCQ&feature=youtu.be

+ Recent posts