본문 바로가기

Data Analysis

기계학습 - Spark(7) - Word2Vec 코드분석 완결

지금까지 스파크 소스코드 분석을 통해 이해한 word2vec작동 원리에 대한 정리글을 올린다.


word2vec은 아주 많은 양의 문장을 사용한 학습을 통해 단어들마다 고유의 벡터값을 산정하는데, 그 값에 따르면 유사한 성격의 단어들이 어느 한 지점에 몰리는 것을 볼 수 있다. 그러나 학습은 단어간의 연관성을 문장에서 서로 가까운 위치에 놓여 있는지에 따라 정해지기 때문에 한계도 있다.


word2vec은 크게 두 단계로 나뉜다. 첫번째는 문장들의 단어들을 추려 빈도수에 따라 이진 트리를 구성하는 것이고, 두번째는 본격적으로 학습을 행하는 것이다. 


1. 이진트리 구성


위의 그림은 이진트리를 구성할 때 사용하는 빈도수가 어떻게 적용되는지를 보여준다. 이 이진 트리는 소위 인공지능을 이용한 여러 이론에서 애용되는 Hidden Layer에 대한 것이기도 하다. 이론서들은 신경망등을 대단히 복잡하게 설명을 하는데, 소스 코드상에서는 간단한 내용이다. 이 이진트리의 바탕이 되는 생각을 이해하면 관련된 내용은 쉽게 이해되는 것 같고 심지어는 응용 및 스스로 새로운 모델도 구성이 가능하게 된다고 본다.


이진트리를 구성하는 방법은, 모든 문장들을 단어로 나누고 단어의 빈도수를 센다. 그리고 그 빈도수를 가지고 단어들을 정렬, 이진 트리를 구성한다. 하위노드일수록 그리고 왼쪽노드일수록 빈도수는 작아지고 거꾸로일 수록 빈도수는 커진다. 최상위 노드가 가장 빈도수가 크다.


뒤에서도 설명이 되지만 학습을 위해 어떤 단어를 이진 트리에서 선택할 때, 그 부모노드부터 최상위노드까지 경로상에 있는 모든 단어(노드)들도 같이 선택 사용한다. 이진트리 구성상 빈도수가 작은 노드가 선택되면 많은 노드들이 덩달아 선택되고, 빈도수가 큰 노드가 선택되면 상대적으로 적은 노드들이 선택된다. 이 것은 다른 각도에서 보면 빈도수가 큰 노드는 선택이 될 가능성이 높고 심지어 최상위 노드는 무조건 선택이 된다. 거꾸로 빈도수가 작아질수록 선택이 될 가능성은 줄어든다. 확률은 1, 1/2, 1/4, 1/8 ... 로 줄게 된다. 수학을 잘하는 사람은 눈치를 챘을 것이다. 2의 -n승 의 모습을, 그리고 이것은 어찌어찌 하다 보면 결국 수학자들이 아주 좋아하는 e 값으로 귀결된다는 것을... 


또한 많이 선택된다는 것은 학습할 때, 자주 처리된다는 것으로 상위노드로 갈수록 잦은 영향을 받는다. 잦은 영향을 받는 노드는 노드에 끼친 하나 하나의 영향은 점점 희석이 되지만 많은 항목의 영향을 내포하게 된다. 반면에 하위노드로 갈수록 드믄 영향을 받게 되고 따라서 개별 영향의 흔적은 상대적으로 깊게 새겨지게 된다. 이 부분을 잘 이해하면 인공지능 신경망 모델링의 요체를 이해할 수 있다고 본다.


2. 학습


(1) 모든 단어를 원점 근처에 흩뿌린 다차원 공간을 만든다.  => SYN0

(2) 모든 단어를 원점에 위치시킨 다차원 공간을 만든다.  => SYN1 

(3) 순서대로 학습에 사용될 많은 문장들중 하나를 선택한다.

(4) 순서대로 선택된 문장에서 한 단어를 선택한다.  => 선택단어=word

(5) 선택된 단어의 앞뒤로 일정한 범위 안에 위치한 단어들을 추리고, 추린 것들중에서 하나를 순서대로 선택한다.  => 선택단어=L1

(6) 원점에 위치하는 임시벡터를 하나 새로 만든다. 원점벡터=neu1e

(7) 이진트리에서 'word'에 짝지어진 노드를 선택하고 자기자신을 포함 최상위 노드에 이르는 경로에 위치한 모든 노드들을 추리고 순서대로 하나를 선택한다. => 선택노드 단어=L2

7-1) SYN0:L1 벡터와 SYN1:L2 벡터간의 스칼라 곱을 구한다.

7-2) 앞서 항의 스칼라곱을 가지고 saxpy함수의 알파값을 구한다.

7-3) 알파값을 가지고 SYN1:L2 벡터쪽으로 neu1e벡터를 이동한다. 

7-4) 알파값을 가지고 SYN0:L1 벡터쪽으로  SYN1:L2 벡터를 이동한다.

(8) neu1e벡터쪽으로 SYN0:L1 벡터를 이동한다.


단어들이 벡터로 표현되는 다차원 공간은 SYN0, SYN1 두개로, 이름은 소스코드상 변수명을 대문자화한 것이다. 모든 결과가 저장되는 공간은 SYN0이고 SYN1은 계산을 위한 공간이다. 초기값도 SYN0는 흩뿌려진 상태에서 시작하고, SYN1은 모두 원점에 놓는다. (7)항을 보면 SYN1은 단어간 영향만을 보존하고 SYN0은 neu1e의 벡터값이 적용되는데 이  neu1e 벡터는 여러 단어들에 의해 영향받은 값이다. 따라서 SYN0은 순수하지(?) 못하죠. 즉 SYN0는 오염된 값, SYN1은 순수한 값 이렇다. 


(7)항을 보면 이진트리에서  'word'에 짝지어진 노드 포함 관련 단어들을 추린다. 앞서 설명했듯이 하위 노드는 빈도수가 낮은 특정 단어들에게 강한 영향을 받았을 것이고, 상위노드로 갈수록 이것 저것등 많은 것들에게 영향을 받았을 것이다. 


7-3)항에서 추려진 노드(단어)들을 하위노드부터 상위노드의 순으로 neu1e 벡터에 영향을 끼친다. 가장 편향되고 강한 영향을 먼저 끼치고, 점점 약해지고 중립적이 되는 영향을 끼쳐 뭔가 보정을 하는 느낌이다. neu1e 벡터는 최초 원점에서 출발하여 여러 단어의 방향으로 이동하다 즉, 영향을 축적해서 (8)항에서 SYN0공간상의 L1단어에 반영된다.


(7),(8)항을 좀더 풀어 쓰면, 우리집에 친구(L1)를 데려왔다. 우리집에는 나(word), 아빠, 누나, 엄마가 있다(이들이 모두 L2이다).  최초 L2는 '나'다. 나와 친구와 가까운 정도를 가지고(7-1,7-2), 내가 보는 친구의 인상, 아빠가 보는 친구의 인상, 누나가 보는 친구의 인상, 엄마가 보는 친구의 인상들을 SYN1에 각인시키고 그런 인상들을 모으고 모아서(neu1e) 친구가 바라보는 우리 가족속의 '나'의 인상을 정한다. ^^


계속해서, 이렇게 하나의 벡터를 다른 벡터쪽으로 이동시킬 때, saxpy함수를 적용한다. 함수명은 아래 수식에 대한 영어의 약어이다. 


위의 것을 계산하는 BLAS함수인데, Single-precision A X Plus Y, 를 따서 함수명이 saxpy이다. 이 함수의 매개변수는 알파값, 벡터1, 벡터2 인데, 계산결과를 벡터2에 넣는다. 그 결과 벡터2가 벡터1에 다가가게 된다. 자세한 내용은 이전회의 내용을 참고바란다. 이 때 알파값이 중요한데, 얼마큼 접근할지를 결정하기 때문이다. 이 값은 7-1)항의 스칼라곱을 가지고 계산된다. 7-1)항의 스칼라곱은 원점을 기준으로 대칭되는 양수/음수값의 범위안의 것만을 취급하는데, 예를 들면 -5 ~ +5까지 예에서 -5값은 가장 정반대일 경우이고 0이면 직각 +5이면 가장 방향이 일치될 때이다. 이 스칼라곱의 값을 0부터의 값으로 치환한다. -5 ~ +5 ===> 0 ~ 10의 범위로 그리고 아래의 함수를 적용한 것이 알파값이 된다. 

변환 과정에 대한 설명하는 그림은 아래와 같다. 



그림과 수식을 보면, x값이 0이상이기 때문에 알파값은 0.5 <= 알파값 < 1 의 범위 안에 위치한다. 


이렇게 다차원 공간에서 각 단어들이 위치와 빈도수등에 따라 학습을 통해 조금씩 이동하다 보면 유사한 성격이 단어들이 일정한 곳에 모이게 된다.



결론


스칼라에서 구현된 word2vec은 이론보다는 실전적인 코딩으로 보여졌다. 이론가가 아닌 이론의 요체를 아는 응용능력이 뛰어난 엔지니어의 작품으로 느껴졌다. 잘 작동되는 신경망의 바탕으로  "빈도수"를 기준으로 구성된 이진트리라는 모델을 고안했다. 이 것을 이해하면서 강한 편향된 영향과 약하지만 광범위한 영향이 잘 짜여지는게 하는 것이 신경망 모델링의 요체라는 생각이 들었다. 


그러나 몇가지 한계가 있다고 생각한다. 먼저 다중벡터를 사용하는 것이 가능한 단어들을 흩뿌리기 위한 용도로 보였다. 학습에서 벡터의 차원이 어떤 의미를 갖지 않았다. 이는 개선의 여지가 있다고 본다. 하나는 낮은 차원에서도 잘 흩뿌릴 수 있게 해서 속도를 높이거나, 어차피 높은 차원 보다 각각의 차원을 나누어 세밀하게 다룰 수 있거나.


또 다른 한계는 학습의 요소는 단어간 위치 하나이다. 그러나 내가 모르는 변형 모델이 이미 있을 수도 있다. 


어쨌든, 코딩 기술 수준이 높진 않지만 수학 수준보단 높기에 직접 word2vec을 구현한 소스코드를 분석하면서 신경망의 개념이 들어간 인공지능에 대해 이해하게 되었고 무엇보다도 직접 구현, 응용 심지어는 새로운 모델을 구상할 수 있게 되었다. 물론 이 생각은 틀릴 수 있다.