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 빛나유
,