비슷한 위치에 등장하는 단어들은 비슷한 의미를 가진다 라는 분포가설을 토대로 단어 자체를 벡터화 하여 분석하는 Word2Vec 방법이 있습니다.
Word2Vec은 단어를 고정 크기의 벡터로 나타내는 기법으로, 분산 표현(distributed representation)의 한 형태입니다.
분산 표현은 단어를 하나의 벡터로 나타내는 대신, 각각의 차원이 특정한 의미를 가지도록 벡터 공간을 구성합니다.
예를 들어, 아래와 같은 두 문장이 있다고 해보겠습니다.
두 문장에서 "good 과 beautiful 은 해당 단어 주변에 분포한 단어가 유사하기 때문에 비슷한 의미를 지닐 것이다" 라고 가정하는 것이 분포 가설입니다.
바로 이 분포 가설에 기반하여 주변 단어 분포를 기준으로 단어의 벡터 표현이 결정되기 때문에 분산 표현(Distributed representation)이라고 부르게 됩니다.
Word2Vec은 대표적으로 CBoW(Continuous Bag-of-Words)와 Skip-gram두 가지 방식으로 구현됩니다.
CBOW는 주변 단어들의 벡터들을 이용해 중심 단어를 예측하는 방법으로, 문맥을 고려한 학습을 가능하게 합니다. 반면에, Skip-Gram은 중심 단어로부터 주변 단어를 예측하는 방법으로, CBOW에 비해 희귀한 단어에 대한 학습이 더욱 용이합니다.
Word2Vec은 텍스트 데이터로부터 단어의 분산 표현을 학습하기 때문에, 이를 이용해 단어 간의 유사도를 계산하거나, 단어들의 선형 연산을 통해 의미적인 계산이 가능해집니다. 이를 통해, 자연어 처리 분야에서 다양한 문제들을 해결할 수 있습니다.
범주형 변수를 벡터로 나타내는 방법 중 하나이며 단어를 벡터화 할 때에도 사용할 수 있습니다.
하지만 단어간 유사도를 구할 수 없다는 치명적인 단점이 존재합니다.
단어 간 유사도를 구할 때에는 코사인 유사도(cosine similarity)가 자주 사용됩니다.
코사인 유사도를 구하기 위한 식은 다음과 같습니다.
원-핫 인코딩을 적용한 서로 다른 두 벡터의 내적은 항상 0이므로, 어떤 두 단어를 골라 코사인 유사도를 구하더라도 그 값은 0이 됩니다.
이렇게 두 단어 사이의 관계를 전혀 알 수 없다는 것이 원-핫 인코딩의 최대 단점입니다.
원-핫 인코딩의 단점을 해결하기 위해 등장한 것이 임베딩(Embedding)입니다.
단어를 고정 길이의 벡터, 즉 차원이 일정한 벡터로 나타내기 때문에 '임베딩'이라는 이름이 붙었습니다.
임베딩을 거친 단어 벡터는 원-핫 인코딩과는 다른 형태의 값을 가집니다.
예를 들어,
[0.04227, -0.0033, 0.1607, -0.0236, ...]
위와 같이 벡터 내의 각 요소가 연속적인 값을 가지게 됩니다.
어떻게 이런 벡터가 만들어지는지, 가장 널리 알려진 임베딩 방법인 Word2Vec
를 통해 알아보도록 하겠습니다.
2013년에 고안된 Word2Vec 은 말 그대로 단어를 벡터로(Word to Vector) 나타내는 방법으로 가장 널리 사용되는 임베딩 방법 중 하나입니다.
Word2Vec
은 특정 단어 양 옆에 있는 두 단어(window size = 2
)의 관계를 활용하기 때문에 분포 가설을 잘 반영하고 있습니다.
Word2Vec
에는 CBoW
와 Skip-gram
의 2가지 방법이 있습니다.
두 가지 방법이 어떻게 다른지에 대해서 알아보도록 하겠습니다.
CBoW
와 Skip-gram
의 차이는
에 따라서 달라집니다.
더 많은 정보를 바탕으로 특정 단어를 예측하기 때문에 CBoW의 성능이 더 좋을 것으로 생각하기 쉽지만,
역전파 관점에서 보면 Skip-gram에서 훨씬 더 많은 학습이 일어나기 때문에 Skip-gram의 성능이 조금 더 좋게 나타납니다.
물론 계산량이 많기 때문에 Skip-gram에 드는 리소스가 더 큰 것도 사실입니다
[예시]
"I love to eat pizza"
이때, CBoW 모델은 "love"라는 중심 단어를 예측하기 위해 "I", "to", "eat", "pizza"라는 문맥 단어들의 벡터를 평균내어 중심 단어를 예측합니다. 이렇게 학습된 CBoW 모델은 "I love to"나 "love to eat"와 같은 문맥에서 자주 등장하는 단어들을 유추할 수 있습니다.
반면, Skip-gram 모델은 "love"라는 중심 단어로부터 "I", "to", "eat", "pizza"라는 문맥 단어들을 예측합니다. 이를 위해 "love"라는 중심 단어의 벡터를 입력으로 사용합니다. 이렇게 학습된 Skip-gram 모델은 "love"와 같은 단어를 중심으로 자주 등장하는 단어들을 유추할 수 있습니다. 예를 들어, "I love to"나 "love to eat"와 같은 문맥에서는 "I", "to", "eat"과 같은 단어들이 자주 등장하므로, Skip-gram 모델은 이러한 단어들을 예측할 수 있습니다.
성능 덕분에 조금 더 자주 사용되는 Skip-gram을 기준으로 Word2Vec의 구조에 대해 알아보겠습니다.
아래 그림을 통해서 Word2Vec 모델의 개략적인 구조에 대해 알아보겠습니다.
논문에서는 총 10,000개의 단어에 대해서 300차원의 임베딩 벡터를 구했기 때문에
신경망 구조가 아래와 같아졌습니다.
효율적인 Word2Vec 학습을 위해서는 학습 데이터를 잘 구성해야 합니다.
Window 사이즈가 2인 Word2Vec 이므로 중심 단어 옆에 있는 2개 단어에 대해 단어쌍을 구성합니다.
예를 들어, "The tortoise jumped into the lake" 라는 문장에 대해 단어쌍을 구성해보겠습니다.
윈도우 크기가 2인 경우 다음과 같이 Skip-gram을 학습하기 위한 데이터 쌍을 구축할 수 있습니다.
이런 방법으로 학습 데이터를 만들면 다음과 같은 데이터쌍이 만들어 집니다.
중심단어 | 문맥단어 |
---|---|
the | tortoise |
the | jumped |
tortoise | the |
tortoise | jumped |
tortoise | into |
jumped | the |
jumped | tortoise |
jumped | into |
jumped | the |
into | tortoise |
into | jumped |
into | the |
into | lake |
... | ... |
학습이 모두 끝나면 10000개의 단어에 대해 300차원의 임베딩 벡터가 생성됩니다.
만약에 임베딩 벡터의 차원을 조절하고 싶다면 은닉층의 노드 수를 줄이거나 늘릴 수 있습니다.
아래 그림은 신경망 내부에 있는 크기의 가중치 행렬에 의해서
10000개 단어에 대한 300차원의 벡터가 생성되는 모습을 나타낸 이미지입니다.
Word2Vec을 통해 얻은 임베딩 벡터는 단어 간의 의미적, 문법적 관계를 잘 나타냅니다.
이를 대표적으로 잘 보여주는 것이 아래 그림입니다.
man - woman
사이의 관계와 king - queen
사이의 관계가 매우 유사하게 나타납니다.
생성된 임베딩 벡터가 단어의 의미적(Semantic) 관계를 잘 표현하는 것을 확인할 수 있습니다.
walking - walked
사이의 관계와 swimming - swam
사이의 관계가 매우 유사하게 나타납니다.
생성된 임베딩 벡터가 단어의 문법적(혹은 구조적, Syntactic)인 관계도 잘 표현하는 것을 확인할 수 있습니다.
고유명사에 대해서도 나라 - 수도 와 같은 관계를 잘 나타내고 있는 것을 확인할 수 있습니다.