Word2vec이다!! 어마어마한 수식이 기다리고 있으니 기대해도 좋다. 이번 포스팅에서는 Word2vec을 간략하게 설명한 후 Word2vec의 한 model인 continuous bag of words(CBOW)를 수학적으로 설명할 예정이다.


우선 word2vec이 무엇이냐? text classification을 하기 위해 만들어진 것이다. word2vec을 통해서 우리는 비슷한 부류에 있는 단어들을 모을 수 있다. 예를 들어, Apple, Samsung은 서로 가까이 있을 것이고, BMW, Audi도 서로 가까이 있을 것이다. word2vec의 유명한 예로 "man과 woman의 비슷함은 queen과 king의 비슷함과 비슷할 것이다" 이런 것도 있다. 다음의 예시 문장을 보자.


the king loves the queen

the queen loves the king

the dwarf hates the king

the queen hates the dwarf

the dwarf poisons the king

the dwarf poisons the queen


기술적인 것을 모두 잊어버리고 한번 생각해보자. 

the king ______ the dwarf


빈 칸에 알맞은 것은 무엇인가? 음 loves는 아닌 것 같고. 문맥상 보면 hates가 들어가야 맞다. 지금 이거는 the king dwarf를 보고 우리가 유추한 것이다. 그러면 반대로 이렇게도 할 수 있다.


____ ____ dwarf ____ ____


dwarf라는 단어를 바탕으로 주변 단어를 추측하는 것. 


word2vec은 이렇게 크게 두 가지 형태의 model을 가지고 있다. 첫번째 예제처럼 여러 단어로부터 한 단어를 추측하는 것을 CBOW : continous bag of words model이라고 하고, 두번째 예제처럼 한 단어로부터 여러 단어를 추측하는 형태의 model을 skip gram model이라고 한다. 


이번 포스팅에서는 continuous bag of words model에 대해서 공부해보려고 한다. 이 CBOW 모델을 제대로 알기 위해서는 이 model을 어떻게 train을 하는지 알아야 되고, 그리고 어떻게 사용을 하는지 알아야 된다. 우선 여기서는 어떻게 train하는지를 알아보고 그 다음에 어떻게 사용하는지를 알아보자.


우선 train을 어떻게 하는지 알아보자. train을 하기 위해서는 이전 포스팅에서 공부했었던 ANN과 gradient decent가 사용된다. 다른 것이 있다면, ANN 포스팅에서 나왔던 activation function이 hidden layer에는 적용되지 않고, output layer에만 적용된 다는 것. 그리고 ANN 포스팅에서는 activation function으로 sigmoid function을 사용했으나 여기서는 softmax function을 사용할 것이라는 점이 다르다.


activation function 이 hidden layer에는 적용되지 않기 때문에 아래와 같은 형태의 ANN을 갖게 될 것이다.

x와 w와의 matrix 곱이 바로 (activation function 거치지 않고) w'에 적용되어 w'와의 곱이 u로 나오게 된다. 그리고 이 u에 우리는 softmax function을 적용시킬 것이다. 자꾸 softmax softmax하는데 그게 어떤 식인지 알아보자.

P(wO|wI)가 softmax function의 결과물이다. 즉, conditional probability를 구하는 함수가 되는데, 어떤 단어(e.g. dwarf)가 input으로 들어왔을 때, output으로 e.g. hates가 될 확률을 구하는 것이다. 뭔가 식만 보면 어떻게 하라는 것인지 잘 모르겠으므로, 실제 예를 봐보자. V는 unique한 단어의 개수라는 점과 N은 단어를 표현하고 싶은 dimension이라고 보면 된다. 위의 사용했던 문장을 다시 봐보자.


the king loves the queen

the queen loves the king

the dwarf hates the king

the queen hates the dwarf

the dwarf poisons the king

the dwarf poisons the queen


unique words : the king loves queen dwarf hates poissons


여기서 unique words를 전문용어로 bag of words라고 한다. 그러면 이 bag of words의 길이는 7이다. 그래서 V = 7로 놓고, 난 각 단어를 3차원으로 표현하고 싶으므로 N = 3으로 놓을 것이다. 그리고 input word는 dwarf, output word는 hates라고 해보자.


위와 같이 softmax function을 사용하면 된다. 위의 결과를 해석해보면 위와 같은 w와 w'이 주어졌을 때, p('hates'|'dwarf')의 확률이 0.1428이라는 것이다. 자 여기서 질문!! 저기 w와 w'은 어떻게 구한 것일까? 답은 그냥 랜덤이다. 그냥 말그대로 랜덤 함수를 통해 0과 1사이의 값을 찍어낸 것이다. 그런데 그렇게 하면 당연히 확률이 좋을 리가 없다. 그래서 gradient decent가 나오는 것이다. ANN에서는 error를 minimize하는데 목표를 두었으나, 여기서는 softmax function의 결과값을 maximize하는 것을 목표로 둔다. 아래와 같이 구할 수 있다.

ipad에 써서 손글씨가 엉망이다.(원래 그렇기도 하다) 아무튼 p(wO|wI)를 maximize한다는 말은 그것의 log를 취한 값을 maximize하는 것과도 같기 때문에 위와 같은 식이 나온다. 이제 우리는 E를 알았으니 이것을 w와 w'로 미분을 해주도록 하자. w'로 미분을 먼저 해보자. 지금부터 조금 복잡해질 수 있다. 그래서 기본식으로 아래를 먼저 이해하고 가자.


위의 그림과 ANN을 이해했다면 무리없이 이해할 수 있는 식이다. E를 w'로 미분할 때는 chain rule을 이용하여 아래와 같이 미분한다.

앞에 dE/duj는 아래와 같고

(위의 식에서 tN은 tN이 실제 output일 경우에만 1이다. 이 부분 조금 어려울 수 있으나 잘 생각해보면 알 수 있다.)

뒤에 duj/dwij는 식 (2)를 전개하여 미분하면 hi라는 것을 쉽게 알 수 있다.

자 그러면 마지막으로 update!! 

(저기 ejhi앞에 있는 것은 learning rate이다.)

다음에는 dE/dwij를 구할 차례다. 이전 것보다 조금 더 복잡하니 집중해서 보자.

앞에 dE/dhi는 아래와 같이 구할 수 있다.

(식이 조금 복잡하므로 EHi ~ EHn으로 치환한것이다.)


뒤에 dhi/dwji는 식(1)을 전개하여 미분해보면 xj라는 것을 쉽게 알 수 있다. 자 이제 update 남았다. 


xj 가 어디갔냐고 물어보는 사람이 있을 것이다. 없어진거 아니다.

위의 식에서 x1 xV까지를 잘 생각해보면, V개 중에 하나만 1이다. 따라서 V row 중 하나만 1이고, 1은 곱하나마나이므로, 한 row가 EH1부터 EHn가 되고 나머지는 모두 0이 되는 것이다. 그렇다 결국 wji를 미분한 결과는 old wji의 한 row만 변경시키게 되는 것이다.


ANN에서 말했듯이 이 과정을 엄청엄청 많이 반복해서 w와 w'를 계속 optimize하는 것이다. 지금까지 w와 w'를 update하는 과정을 살펴봤는데, 한 가지 덧붙일 것이 있다. 지금까지는 input word 하나로 output word 하나를 예측해왔는데, input word가 여러 개일 수도 있다. 그럴 때는 아래와 같이 계산하면 된다. 원리는 같으나 합해서 평균내주는 부분이 조금 추가되었다. 


input word = "queen", "loves"

target word = "king"


w'을 우선 update 해줘야 되는데, 그러려면 h를 알아야 된다. h는 hidden layer의 output인데, 우리는 input word가 두 개 있으니까 그 hidden layer output도 두 개 나올 것이다. 

결과물로 나온 loves와 queens 두 개를 더해서 2로 나눠주면 h가 나오게 된다. 그 h를 이용해서 w'를 update해준다. w'new = w'old - learning_rate * error * h 하면 된다. 우리는 단어가 7개 있으니까 이 식을 각 7개의 단어에 대해서 반복해주면 되는데, 이 식에서의 error는 현재 작업하고 있는 word와 target word가 같을 경우에는 1 - p, 그렇지 않을 경우에는 0 - p가 되겠다. 


그 다음에는 w를 update 해줘야 되는데, 위에서 설명했을 때, input word가 하나 일 때는 한 row만 빼주게 되는 결과가 나타난다고 했다. 이번에는 input word가 두 개니까 두번 수행해주면 된다. 한 가지 유의할 점은 식이 w_new = w_old - (1/C) * learning_rate * EH 라는 점이다. 1/C를 곱해주고 빼는 것을 잊지 말자. (단 C는 context 개수, 여기서는 2가 된다) 자 이렇게 w까지 update 해줬다.


input word가 여러 개 있을 경우에는 이와 같이 해주면 된다. 아 힘들다. 자 마지막으로 어떻게 쓰는지에 대해서 써보자. 쓰는 방법은 사실 한 가지가 아니다. 여러 방법으로 적용시켜주면 된다. 예를 들어 나는 이런 식으로 써봤다.

예를 들어 w가 위와 같이 있다고 해보자. 그리고 내가 할 일은 아래의 문장들에 대해서 positive negative를 추측하는 것이다.

train set으로 Naive Bayes Classifier로 training을 할 것이고 그 모델을 가지고 test sentence를 test 할 것이다. train하기 전에 w(7x3) word vector를 가지고 무언가를 할 것이다. 바로 각 문장을 vector화 해줄 것이다.


첫번째 sentence "the king kills the dwarf" 에서는 the, king, dwarf를 위의 w word vector에서 찾을 수 있다. 다 더해서 3으로 나눠주자.(못 찾은 kills는 무시해주면 된다.) 이런 식으로 각각의 train에 대해서 진행하면 아래와 같은 word vector:sentiment를 얻을 수 있다.

위의 세 train sentence를 dimension 1, 2, 3으로 vector화 했고, 그것의 sentiment를 가지고 있다. 이 train set으로 여러가지 classifier를 적용시키는 것이다. 그렇게 model을 training했을 때, test sentence의 vector [0.542085479, 0.458401841, 0.420776285]는 negative? positive? 예측을 하는 것이다. 이런 식으로 쓰일 수 있다는 것이다.


참고로 위의 내용은

http://www-personal.umich.edu/~ronxin/pdf/w2vexp.pdf

http://www.folgertkarsdorp.nl/word2vec-an-introduction/

여기에서 확인할 수 있으니 참고하길 바란다.

Posted by 빛나유

댓글을 달아 주세요

  1. 미스터리 2016.04.11 16:54  댓글주소  수정/삭제  댓글쓰기

    덕분에 Word2Vec 이해하는데 도움이 많이 됐습니다.
    좋은 글 감사합니다. ^^

  2. leeyh 2016.04.12 13:23  댓글주소  수정/삭제  댓글쓰기

    안녕하세요!! 이 글덕분에 word2vecd에 대한 내용이 이해되었습니다. 그런데 궁금한게 있어 질문 남깁니다!! Input Layer의 각 뉴런들은 One-hot encoding된 단어값들인데, 첫번째 엑셀에 보면 w*I의 값이 다 (09009588,0.128919,-0.03323)이더라구요. input은 dwarf 하나일 뿐이면 나머지는 다 0이 되어야 하는게 아닌가 하고 질문 남기고 갑니다!!

    • 빛나유 2016.04.13 15:56 신고  댓글주소  수정/삭제

      안녕하세요!! 아 그게.. W*I 에서 I가 one-hot vector맞죠!! 그런데 중간에 hidden layer가 3개 있죠? 즉 하나의 input word인 dwarf에서 3개의 hidden layer로 가는 weight vector 3개가 있죠? dwarf의 1을 그 각각의 3개의 weight vector와 곱한 것이 [0.00959 0.12892 -0.03323]이고요. [0.00959 0.12892 -0.03323]이거를 hidden-output layer에 있는 weight vector들고 dot product해준거죠.

      결국 dwarf 말고 나머지 input word에 대해서는 제가 아무 것도 한게 없게 되는 셈이죠? 무시된거죠 0이라서요ㅋㅋ

      답변이 되셨으면 합니다!!

  3. ㅠㅠ 2016.06.07 12:58  댓글주소  수정/삭제  댓글쓰기

    안녕하세요! word2vec공부하는데 도움 많이 되고 있습니다. 죄송한데 질문하나 해도 될까요?

    위 예제의 경우 한 text에 대해서만 진행하셨는데, 여러개의 텍스트가 있는 경우에 학습이 진행되는게 헷갈려서요

    문장이 여러개 일 경우 즉 [input, target] pairs가 여러개일경우 (10개라 가정)

    input -> hidden 으로 넘어갈때 각각 의 input 데이터마다 input * Weight Matrix를 해줘서

    hidden vector가 10개 나오는건가요?

    마찬가지로 output vector도 10개 나오는건가요??

    더불어서, backpropagation 에서 Weight' Matrix를 업데이트 할때도

    10번 반복해서 업데이트 시키나요?

    ㅠㅠㅠ 답변 부탁드립니다

    • 빛나유 2016.06.08 06:16 신고  댓글주소  수정/삭제

      안녕하세요!! 흠 저도 요즘 word2vec 이용해서 뭘 하고 있는데 마침 동지?를 만났네요. 10개의 문장이 있다고 가정한다는 말은.. 10개의 서로 다른 document가 있다고 가정한다고 이해해도 될까요? 그렇다고 하면요.. 우선.. 음...

      hidden vector 는 굳이 10개가 될 필요는 없을 거 같아요. 예를 들어 제가 지금 하고 있는 것 같은 경우 document 10900개인데 각 단어를 300 dimension으로 표현했거든요. 그러니까 저 같은 경우 document 10900개에 hidden layer 300이겠네요.

      output layer는 10개가 아니라 첫번째 document 에 있는 단어의 개수가 되지 않을까요? 예를 들어
      --------------------------------------
      doc1 : a b c d e a b c d e
      doc2 : a b c d e f a b c d f g z h
      ...
      --------------------------------------
      이런 식으로 있을 때, doc1부터 word2vec training을 하면 doc1에서는 a b c d e 5개에 대한 vector가 나오겠죠?
      --------------------------------------
      a 0.1 0.2 0.3 0.4 0.5
      ...
      e 0.5 0.4 0.1 0.2 0.4
      --------------------------------------
      뭐 이런식으로요. doc2를 training할 때, doc2에서 새로운 단어들 f g z h들은 무시될 거에요. 실제로 python 페키지로 gensim word2vec 사용해보면 생성되는 단어들은 처음 document에서 발견되는 단어들만 training되고 두번째부터 나오는 새로운 단어는 무시되드라고요.

      backpropagation에서 update하는 것은 기본적으로 gradient descent를 사용합니다. gradient descent는 업데이트할 때 반복하는 횟수가 정해져있지 않아요. 보통 converge될 때까지 계속 한다고 하는데 쉽게 말해서 update 전과 후가 변함이 없을 때까지 계속 하는 것이라고 보면 되요.

      http://operatingsystems.tistory.com/entry/Data-Mining-Artificial-Neural-Network
      여기에 gradient descent 설명해두었으니 참고하시기 바랍니다!!

      아 그리고 저도 사실 이쪽 분야 공부 시작한지가 7~8개월 밖에 안되서요.. 틀릴 수도 있고 제가 써둔 부분에 오류가 있을 수도 있습니다!! 그 점 이해해주시고요 답변 도움됐으면 합니다ㅋ

  4. 워투백 2017.02.22 16:04  댓글주소  수정/삭제  댓글쓰기

    안녕하세요. 좋은 글 감사합니다.
    질문이 있는데요. 가중치를 가진 w 행렬(input -> hidden)은 각 word에 대한 feature vector들의 집합 이라 이해를 했고, w'은 이 feature vector들(context)과 target word(vocabulary) 사이의 조건부 확률을 구하는 용도로 사용을 한 것 같습니다. 이렇게 보면 w'도 w와 마찬가지로 각 word에 대한 feature vector들의 집합이고 단순히 행렬의 형태가 w에서 transpose되었다고 생각하는데, 왜 서로 값(w와 w')이 다른지 알 수 있을까요? 같은 행렬을 transpose해서 사용하면 안되나요?

    • 빛나유 2017.02.25 12:24 신고  댓글주소  수정/삭제

      음.. 저도 틀릴수 있다는 점 고려해주셨으면 감사해요ㅋㅋ 결국 위의 ANN이 조건부 확률을 구하는 것처럼 사용된 것은 맞는거 같아요. (진짜 조건부 확률을 구하는 식으로 count/count 로 구한게 아니지만요) 그런데 그때 사용하는 weight, weight'를 단순 transpose해서 구하면 안 될것 같아요.

      weight에서 나오는 단어들은 input 데이터에 나오는 단어들에 대한 weight이고..

      weight'에서 나오는 단어들은 output 데이터에 나오는 단어들에 대한 weight이니까요.

      output으로 확률을 갖기 위해 softmax function을 사용한 것인데, 그 output이 조건부 확률이잖아요?? 그 조건부 확률이 정확한 조건부 확률이 될 수 있도록 w와 w'이 필요한 것인데 w는 input word에 대한 weight이고 w'는 output word에 대한 weight이라는 거죠

      답변이 되었다면 좋겠네요ㅋㅋ

    • 워투백 2017.02.28 17:37  댓글주소  수정/삭제

      좋은 답변 감사합니다!

이번 포스팅은 Back propagation에 대해서 적어보려고 한다. 어마어마한 양의 식이 포스팅될 예정이다. 후 이거 공부하려고 오늘 하루 다 썼다.


우선 back propagation이 뭔지부터 설명해보자. back propagation은 ANN를 training하는 과정이다. 우리가 이전 포스팅에서 ANN의 단 한번의 forwarding으로는 전혀 그럴 듯한 결과를 얻지 못한다고 했었다. 그래서 weight을 update한다고 했었다. 그 weight update하는 과정을 우리는 미분을 써서 dJ/dw가 0이 되는 지점을 찾는다고 했다. 즉 weight을 update하면서 J는 최소값으로 가까워진다는 말이다. 이것을 하는 과정이 back propagation이다. 즉 ANN의 training하는 알고리즘 중 하나가 back propagation algorithm이다.


자 그러면 미분을 시작해보자. 우선 뭘 어떻게 해야하는지 outline을 잡고 시작해보자. 우선 우리는 dJ/dw를 구할 것인데 우리가 예제로 삼고 있는 XOR ANN은 두 개의 weight vector가 있다.

하나 W(1)은 Input layer에서 Hidden layer로 갈 때 사용하는 weight vector이고, 또 다른 하나 W(2)는 Hidden layer에서 Output layer로 갈 때 사용하는 weight vector이다.

이전의 J를 위의 w(1)과 w(2)로 미분을 하면 아래와 같다.

우리는 dJ/dw(1)와 dJ/dw(2)를 구해야 되는데 먼저 dJ/dw(2)를 구하도록 하자. 밑에 식에서 시그마(sum)는 일단 잠깐 빼고 시작하자.


아래의 식은 https://www.youtube.com/watch?v=GlcnxUlrtek 여기에서 나오는 식과 같다. 이 영상과 밑의 식을 같이 보시길 바란다. notation에 있는 숫자도 조금 틀릴 수 있다.

y와 yHat 그리고 z(3) 미분한 값은 각각 아래와 같다.


dz(3)/dw(2)는 왜 저 행렬이 될까? 간단하다. z(3) = aw(2)이기 때문에 w(2)로 미분해주면 a만 남는 것이다. 여기서 우리가 처음에 잠깐 생략했었던 sigma를 다시 넣어준다. 어떻게 넣어줄까? 바로 행렬 곱셈이다. 지금까지는 전부 스칼라 곱이었으나, 마지막에 행렬곱셈으로 바꿔주므로서 아래와 같이 summation을 할 수 있다. 

시그마(3) = -(y-yHat) f'(z(3))는 3x1 행렬이므로 위의 식을 행렬 곱셈으로 바꿔주기 위해서는 3x3 행렬을 시그마(3) 앞에 곱해줘야 되고, 적절한 순서로 summation해주기 위해 transpose matrix로 바꿔준다. 이 부분을 잘 이해해야 된다.


행렬곱셈으로 바꿔주므로서 우리는 앞서 생략했었던 summation도 다시 적용시켰다. 자 이제 dJ/w(1)을 구할 차례다. 이 값도 비슷하게 구할 수 있다. J를 w(1)으로 미분하여 시작하면 된다.

위의 식에서 w(2)^T = dz(3)/da(2) 이 부분.. 이 부분 나도 잘 모르겠다. 대충은 알겠는데, 왜 Transpose를 해줘야 되는지 정확하게는 모르겠다. 그거 빼고는 위의 식은 이전에 dJ/dw(2) 했을 때를 생각하면 이해가 될 것이다.


이제 dJ/dw(2)과 dJ/dw(1)을 구했으니 실제로 weight vector를 업데이트해주면 된다. 이 때 새로운 변수가 들어간다. 바로 learning rate이다.


new w(1) = old w(1) + (learning rate) * dJ/dw(1)

new w(2) = old w(2) + (learning rate) * dJ/dw(2)


이 식으로 w(1)과 w(2)를 update해준다. 이렇게 하면 이제 하나의 epoch가 끝난 것이다. w(1)과 w(2)가 update되었으니 x1과 x2를 update된 w(1)과 w(2)에 집어넣어서 위의 과정을 또 하면 된다. ANN은 이 과정을 무수히 많이 반복하여 error rate을 최대한 작아지게 만든다.(Training) 그 과정을 눈으로 보고 싶다면 아래의 링크를 통해 보면 된다.


http://www.emergentmind.com/neural-network


epoch를 반복반복반복할 수록 XOR 계산에 대한 predicted value가 정확히 0과 1은 아니지만 0.2 0.3 또는 0.97, 0.98로 가까워지는 것을 볼 수 있다. 이걸 만든 사람이 자기 개인 포스팅도 해놓았더라. 


http://mattmazur.com/2015/03/17/a-step-by-step-backpropagation-example/


우와. 정말 engineer다. engineer는 이래야 된다.ㅠㅠ 도무지 실제 예제를 설명해둔 것을 찾을 수가 없어서 자기가 직접 했덴다. 정말 나도 이런 engineer가 되어야 되는데...


아무튼 우리는 back propagation은 이만 끝내고 다음 포스팅으로 넘어가보자. 아마 다음 포스팅은 Word2Vec이 되지 않을까 싶다. 참고로 back propagation에 대한 실제 값을 통한 예제도 언젠간 반드시 포스팅할 거다. 

Posted by 빛나유

댓글을 달아 주세요

  1. ㅋㅋ 2017.02.12 12:26  댓글주소  수정/삭제  댓글쓰기

    뭐? 계산할라고 시그마 뒤에 있던걸 앞으로 옮기고 자기맘대로 전치행렬로 바꾼다고? 뭔 억지수학이지

    • 빛나유 2017.02.13 08:31 신고  댓글주소  수정/삭제

      음... 종이하고 팬 준비해서 한번 써보세요! 그건 그렇게 해도 표현됩니다!

      제가 틀릴수도 있긴한데.. 알려주시면 한수배울께요

    • ??? 2017.02.28 16:38  댓글주소  수정/삭제

      시그마는 sum rule in differentiation 를 보면 알 수 있고, 전치행렬로 바꾸는 것 역시 가능합니다. 억지수학이라니 공부를 좀 하셔야겠네요.

  2. 시그마 2017.03.03 18:26  댓글주소  수정/삭제  댓글쓰기

    안녕하세요. 질문이 있는데...

    이 예제에서 왜 hidden layer의 unit수가 3개인가요? hidden layer의 unit갯수는

    임의로 지정해줄 수 있나요?

    • 빛나유 2017.03.03 23:05 신고  댓글주소  수정/삭제

      네네네 임의로 정하시면 됩니다!! 그런데 개수에 따라서 영향이 있기는 할거 같은데 저는 아직 어떤 영향이 있는지는 잘 모르겠네요;;ㅠ 저도 더 공부를 해야할 거 같네요ㅋㅋ

  3. 2017.06.07 22:11  댓글주소  수정/삭제  댓글쓰기

    dz(3)/dw(2) 행렬 어디서 저런게 튀어 나온건지.... 표현은 가중치 쓰듯 해놨는데... 가중치로 편미분하면 레이어2에 유닛 a1 a2 a3만 남아야지 되는거일텐데 표시까지 가중치마냥 아래첨자가 11 12 13 등으로 해놓고 이해가 안되네요.

    • 빛나유 2017.06.08 14:43 신고  댓글주소  수정/삭제

      http://operatingsystems.tistory.com/entry/Data-Mining-Backpropagation-in-detail-with-example

      backpropagation은 위에 더 자세하게 숫자를 이용해서 포스팅 한번 더해놨습니다. 저걸 보세요~~ 이 포스팅은 그냥 개요정도일 뿐입니다

      그리고 공부는 스스로 하시는겁니다. 제가 쓴것이 별로 맘에 안드시면 혼자 하시면 됩니다!! 위에 제가 보고 공부한 링크들 다 적어놨으니 그걸 보시고 종이와 펜을 준비하신 후 공부해보세용

  4. 2017.07.27 10:15  댓글주소  수정/삭제  댓글쓰기

    비밀댓글입니다

  5. 음음 2017.10.07 20:29  댓글주소  수정/삭제  댓글쓰기

    저기.. 편미분 기호를 다 델타로 쓰셔서.. 헷갈립니다ㅠㅠ

왜 분명히 배운 것들인데 왜 복습을 하는 것 조차 이틀이나 걸리는 것인가. 솔직히 지금도 헛깔린다. 아무튼 Artificial Neural Network(ANN)을 공부해보도록 하자.


ANN에서는 data들을 어찌어찌 처리하여 그 data에 대한 predicted value를 만들어낸다. 예를 들어, 간단하게 XOR 함수를 놓고 생각해보자. x1과 x2가 1이면 그 값은 0이 된다. 우리가 이것을 ANN을 통해 예측해보려고 한다. 그러면 x1과 x2가 각각 1이니까, 이 값들을 어찌어찌 하여 output을 0으로 혹은 1으로 추측해보려고 한다. 어떻게 추측을 할까? weight을 곱해서 알아보는 것이다. 

위의 그림에서 x1, x2는 1이고 w1, w2는 각각 x1과 x2에 대한 weight이다. (x1, x2)와 (w1, w2)의 dot product을 구하면 o1이 나온다. Artificial Neural Network에서 Neural이 위의 그림 저것이다. Neural Network는 저것들이 여러개 모였다는 것이다. 즉, 우리의 XOR 예를 가지고 생각해보자면, XOR를 예측하기 위해 여러개의 Neural Network를 만들었다고 보면 된다. Neural Network는 아래와 같은 형태를 띄게 된다.


위의 그림에서 notation부터 정리를 해보자. 우선 각각 원i에서 원j으로의 weight을 wij로 표시했다. 그리고 원은 1부터 6까지 있다. 그리고 원i에서 나오는 output을 oi로 표시했다. 자 위의 그림에서라면 우리는 x1과 x2의 XOR을 예측하기 위해 아래와 같은 일을 해야된다.

여기서 중요한 용어를 한번 정리해보자. 바로 Input layer, hidden layer, output layer이다. (사실 위의 식은 틀린 것이다. 중요한 과정을 하나 빼먹은 과정인데, 조금만 더 읽어보면 뭐가 빠졌는지 알 수 있다.)

여기서 Hidden layer는 무슨 말이냐면, 말 그대로 감춰진 layer라는 것이다. 무슨 일이 벌어지는지 모른다는 것이다. 여기서 Hidden layer는 하나 밖에 없지만, 실제로는 더욱 깊은(deep) 여러 층의 hidden layer가 있는데, 여기에서의 deep이 deep learning의 deep이라고 한다.


자, 자세한건 일단 제쳐두고 w13부터 w56까지 특정 값을 가지고 있다고 했을 때, 이제 우리는 x1과 x2만 있으면 o6를 구할 수 있다. 그러면 그 값이 0이나 1로 정확히 나올까? o6를 구하기 위해서 우리는 dot product를 input layer에서 hidden layer로 3번하고 hidden layer에서 output layer로 1번, 총 4번을 하는데, 그 dot product의 결과가 0이나 1로 딱 떨어질까? 그럴리는 거의 없다고 보면 된다. 그럼 어떻게 할까? 사실 우리는 지금까지 설명 안한 과정이 한 부분 있다. 그 부분을 포함하면 각 neural은 아래의 그림이 된다.


dot product 결과 z1을 Activation function에 집어넣어야 된다. 이 Activation function은 어떤 함수를 택하느냐에 따라 o1의 값이 바뀔 수 있는데, 가장 일반적으로 sigmoid function을 택한다. (어느 순간부터 가장 일반적으로 ReLu 함수를 많이 사용한다.)


sigmoid function은 그 값이 0과 1 사이(probability 구할 때 유용)라는 특징이 있는 "미분 가능한" 함수이다. ("미분 가능한"을 강조한 이유는 다음 포스팅 backpropagation을 설명할 때 같이 설명하겠다) 자 이제 우리는 o6를 구하는 올바른 식을 알아보자.

이제 o6는 무조건 0과 1사이의 값이 된다. 우리가 x1, x2를 가지고 위의 계산 과정을 거쳤을 때, 마지막 o6의 값이 0.8이 나왔다면 그 값은 1이 될 확률이 클 것이고, 0.2가 나왔다면 그 값은 0일 확률이 크다는 의미가 될 것이다.


우리가 지금까지 한 것은 ANN에서 forwarding이라고 한다. 즉 주어진 X의 값으로 그 ANN의 최종 output을 만들어내는 과정이다. 그렇다면 여기서 한 가지 질문을 해보면, 이거 한번 계산하면 정말 쓸만한 classifier가 되냐? 당연히 아니다. weight이 어떤 값이냐에 따라 결과는 아주아주 많이 바뀔 것이다. 그럼 우리는 가장 좋은 weight을 찾아야 된다. 그것은 어떻게 찾을까? cost function(J)을 통해 구하면 된다. 

여기서 y_hat은 우리가 구한 predicted value이다. 즉 predicted y와 실제 y의 차이를 구해서 제곱을 한 후 그것을 반으로 나눠준다는 것이다. 왜 절반으로 나누냐? 다음 포스팅 back propagation에서 위의 식을 미분할 것인데 그 때 제곱의 2가 밑으로 떨어지면서 1로 상쇄되면 계산하기 편하니까 이다. 이유가 못 마땅하다는 생각을 하는 사람이 많을 것이다. "수학이 뭐.. 편할 거 같은 숫자로 아무렇게나 하면 되는거야?" 이런 생각을 내가 했었고 그것 때문에 1/2를 곱해주는 이유에 대해서 꽤나 찾아봤었는데 결론은... 사실 뭘 곱해도 상관 없다 여기서는... 어짜피 우리한테 중요한 것은 두 개의 차이가 중요한 것이니까. 그 외의 상수는 뭐든 좋다는 것이다.


자 다시 본론으로 돌아가서, 이 cost function의 값이 가장 작도록 하는 weight을 찾아야 되는데, 가령 1부터 1000까지 일일이 weight을 설정하여 나온 값의 최소값을 구하면 아주 아주 아주 시간이 오래 걸릴 것이다. 그래서 우리는 여기서 미분을 한다. weight으로 미분을 해주는 것이다. cost function을 J로 놓으면 우리는 dJ/dw를 구해서 그 값이 0이 되는 방향으로 계속 weight을 update해줄 것이다. 이렇게 최소값을 찾는 과정을 gradient decent라고 한다.


마치 게임할 때 적절한 능력치를 올려줘서 balance를 맞춰주는 것처럼, 혹은 오디오에서 여러가지 음향 효과 버튼을 돌려서 최적의 소리를 세팅하는 것처럼, 각각의 weight(w13부터 w56까지)의 weight "버튼"을 적절히 돌려서 cost function이 최소화되는 그 바로 그 순간을 찾는 것이다.


위의 그림은 아래의 동영상의 일부를 캡쳐한 것이다. 정말 잘 만든 동영상이다.

https://www.youtube.com/watch?v=5u0jaA3qAGk


여기서 한가지만 더 쓰고 포스팅을 마치자. 만일 cost function이 아래와 같이 non-convex이면 어떻게 할까?

우리가 진짜 원하는 것은 global minimum인데 우리가 구한 값이 local minimum일 수도 있다는 이야기이다. 요약하면, 상관없다 이다. local minimum이여도 충분히 쓸만하다고 한다. 조금 어이없지만 그렇다고 한다. (마치 Naive Bayes에서 각 사건을 독립인 것처럼 전부 곱해버리는 데도 불구하고 실제로 꽤나 괜찮은 효율을 내는 것과 비슷하다.)


이것으로 이번 포스팅을 마치려고 한다. 다음 포스팅은 back propagation algorithm이다.

Posted by 빛나유

댓글을 달아 주세요

  1. SDKim 2016.03.31 12:21  댓글주소  수정/삭제  댓글쓰기

    잘 보고 갑니다^^

  2. 2017.07.27 10:16  댓글주소  수정/삭제  댓글쓰기

    비밀댓글입니다

    • 빛나유 2017.07.31 20:29 신고  댓글주소  수정/삭제

      Sigmoid 값입니다. Sigmoid 값은 항상 0과 1사이이기 때문에 확률 예측값으로 사용될 수도 있습니다. 즉!!
      y_hat = o6 = sigmoid(z6)
      입니다.

  3. 2017.07.27 19:52  댓글주소  수정/삭제  댓글쓰기

    비밀댓글입니다

    • 빛나유 2017.07.31 20:27 신고  댓글주소  수정/삭제

      y값은 항상 1이 되는 것은 아닙닌다. 즉 0.5(1-y_hat)^2 라고 항상 쓸 수 있는 것이 아닙니다.

      예를 들어 주어진 데이터에 대해서 참 거짓을 판단하는 경우, 참일 경우 y=1, 거짓일 경우 y=0이 됩니다. y=1인데 y_hat이 0.8이라는 말은 어떤 데이터의 실제 값이 1이고 그 데이터를 예측했을 때 1이라고 판단할 확률이 0.8이라는 뜻입니다. 반대로 y=1인데 y_hat이 0.2라는 뜻은 모델의 예측값이 0에 가깝다는 것이고 이는 틀린 결과를 말하죠.

      또 다른 케이스를 볼까요? y=0인데 y_hat이 0.2라면 모델 예측값이 0에 가깝고 이는 올바른 결과를 말합니다.