제 3장 : word2vec
업데이트:
카테고리: NLP, 밑바닥부터 시작하는 딥러닝 시리즈
이번 장에선 “추론 기반 기법”에 대해 설명한다. 글의 순서를 바꿔서 내맘대로 글을 재구성했다.
one-hot encoding
추론 기반 기법은 신경망을 이용한다. 이젠 단어를 동시발생행렬로 만들지 않고, one-hot encoding 처리를 하자.
word2vec과 CBOW
CBOW는 word2vec에서 사용되는 신경망이다. CBOW의 목표는 맥락을 읽어서 모르는 단어를 추론하자!이다. 예를 들어서, I {?} dinner 이라는 문장이 있다면 I와 dinner를 통해서 글의 맥락을 읽고 {}에 들어갈 단어를 추론하는 것이다. 여기선 have라는 단어를 추론할 수 있다.
여기에 시간 개념을 도입해보자. have를 현재라고 생각하면, I는 have 바로 전, dinner는 바로 후다. 이것을 t라는 시간변수로 생각하면, 다음과 같이 생각할 수 있다.
- I : $w_{t-1}$
- have : $w_t$
- dinner : $w_{t+1}$
맥락을 통해서 have가 나올 확률을 수학적으로 표현하면 다음과 같이 표현할 수 있다.
\[p(w_t | w_{t-1},w_{t+1})\]이제 우리는 이것을 신경망으로 모델링할 것이다.
CBOW의 구조
그림 1. CBOW의 구조 |
CBOW 모델의 구조는 그림 1과 같다. 생각보다 되게 간단하다. PROJECTION 부분은 MLP로 따지면, hidden layer에 해당한다. 이 hidden layer에 들어오는 값이 여러개이므로, 간단하게 평균을 내서 값들을 가지면 된다. 이 때, 주의할 점 및 개인적으로 신기한 것은 입력으로 들어오는 one-hot encoding vector들과 결합되는 weight는 모든 입력들에 대해 같다는 것이다.
그리고! 이 입력 층에서 hidden layer로 넘어오면서 선형결합되는 weight는 단어들의 의미를 갖는 벡터를 뜻하는 CBOW의 분산 표현임을 알고 가자! 그리고 hidden layer에 있는 node들의 개수는 입력 데이터로 사용되는 dimension보다 작아야한다. 왜냐하면 단어의 액기스 feature들만을 추리기 위해서다.
hidden layer에서 output layer로 갈때도 여전히 weight가 존재한다. 그리고 output으로 나오는 것은 입력 데이터와 차원이 같다. 즉, 맥락을 통해 어떤 단어가 나올지에 대한 값이 추출되는 것이다.
각 값들에 대한 확률 값을 알고싶으면 softmax layer를 output 단에 달자. 그리고 error를 측정하여 back-propagation을 진행하기 위해 cross entropy loss를 사용하자.
\(CEloss = -\sum_k t_k \log y_k\) ※ k는 one-hot encoding 벡터의 순서를 얘기함.
CEloss에 대해 잘 모른다면 링크로 가서 보고오길 바란다!
$t_k=1$이 되는 것은 한개의 one-hot encoding 벡터에서 유일하기 때문에, 하나의 맥락 - 하나의 단어 set의 CEloss는 다음과 같다.
\[each\;CEloss = -\log p(w_t | w_{t-1},w_{t+1})\]모든 데이터 셋에 대한 CEloss는 평균을 내주면 된다.
\[total\;CEloss = -\frac{1}{T} \sum^T_{t=1} \log p(w_t | w_{t-1},w_{t+1})\]skip-gram에 대해
CBOW는 맥락을 통해서 단어를 추론하는 것이 목표였다. skip-gram은 반대로 단어를 통해 주변의 맥락을 파악하는 것이 목표다!
그림 2. skip-gram의 구조 |
I have dinner에서 have를 통해 I,dinner가 나올 확률을 수학적으로 표현하면 다음과 같다.
\[p(w_{t-1},w_{t+1} | w_t)\]각 단어들이 독립적이라는 naive한 가정을 하면, 위 식은 다음과 같이 쓸 수 있다.
\[p(w_{t-1} | w_t)p(w_{t+1} | w_t)\]skip-gram은 출력이 여러 개이므로, 각각의 CEloss를 구해서 평균을 내야한다. 먼저 하나의 단어 - 하나의 맥락 set의 CEloss는 다음과 같다.
\[\begin{align*} each\;CEloss &= -\log p(w_{t-1} | w_t)p(w_{t+1} | w_t) \\ &= -\{ \log p(w_{t-1} | w_t) +\log p(w_{t+1} | w_t) \} \end{align*}\]모든 데이터 셋에 대한 CEloss는 평균을 내주면 된다.
\[total\;CEloss = -\frac{1}{T} \sum^T_{t=1} \{ \log p(w_{t-1} | w_t) +\log p(w_{t+1} | w_t) \}\]CBOW vs skip-gram
지금쯤 둘 중 뭘 써야할까에 대한 의문이 생길 수 있다.
대세는 skip-gram을 사용하는 거라고 한다. 특히 말뭉치가 커질수록 빈도가 적은 단어나, 유추 문제의 성능 면에선 skip-gram 모델이 더 뛰어나다고 한다. skip-gram은 더 적은 정보를 통해 더 많은 것을 추론해야하는 모델이기 때문에 해당 단어에 대한 분산 표현이 더 정밀하게 만들어질 수 있기 때문인 것 같다.
그러나 CBOW가 학습 속도면에서는 더 빠르다고 한다. 스스로 기준을 정해서 모델을 선택하면 될 것 같다. {아마.. 지금은 이 모델들을 쓸 일이 없지 않을까 싶지만..?}
통계 기반 vs 추론 기반
통계 기반 방법은 전체 데이터를 한번에 학습하기 때문에 새로운 데이터가 추가되었을 경우 매번 전체 데이터에 대해서 재학습을 해야한다는 단점이 있다. 추론 기반 방법은 새로운 데이터가 들어왔을 때, 기존에 학습된 모델의 가중치를 초기 가중치로 설정하여 해당 데이터에 대한 재학습을 진행하면 되기 때문에 통계 기반보다 좋은 장점을 갖는다. {근데 여기서 재학습을 할 때 추가된 데이터에 대해서만 학습을 하는 것인지, 원래 데이터에 끼워넣어서 하는 것인진 모르겠다..}
하지만 사실 두 기법들의 결과로 단어의 유사성을 정량평가해보면 우열을 가릴 수 없다고 하며, 두 기법은 서로 관련되어 있기 때문에 어느 한쪽도 소홀히 해선 안되는 것 같다.