[개발이야기] 나랏말싸미 NLP를 만나다 - 단어 임베딩 편 1

"블루펭귄 개발 과정"

Posted by 예띠 on January 6, 2020

블루펭귄 개발 과정

주식회사 와들의 첫 iOS 앱인 블루펭귄을 개발하는 과정을 담은 글이다.

지난 포스트에서는 한국어 데이터셋의 텍스트 전처리를 다루었다. 이번 포스트에서는 컴퓨터가 자연어를 계산할 수 있도록 처리하는 방식인 임베딩(embedding)에 대해서 알아보자.

임베딩이란

임베딩은 자연어를 벡터로 변환하는 과정이나 그 결과를 말한다. 벡터로 변환된 자연어는 다양한 모델의 입력값으로 사용된다. 임베딩은 단어, 혹은 문장 수준에서 이루어진다. 이 포스트에서는 단어 수준의 임베딩에 사용되는 모델의 특성을 다루고, 다음 편에서 문장 수준의 임베딩에 사용되는 모델의 특성을 살펴볼 것이다.

단어 수준의 임베딩은

단어 수준에서 이루어지는 임베딩은 문장 안의 단어를 따로따로 나누어 벡터로 만든다. 단어를 벡터로 변환하는 모델은 여러 가지가 있는데 Word2Vec, FastText, GloVe 등이 있다.

Word2Vec

Word2Vec은 단어 간 유사도를 반영하여 단어의 의미를 벡터화한 모델이다. Word2Vec은 임베딩에 분산 표상(distributed representation) 방법을 사용한다. 일반적으로 머신러닝에서 ‘representation’은 ‘표현’으로 번역되곤 하는데 다음의 페이스북 게시글을 참고하여 ‘표상’이라는 단어를 사용했다. 우리의 마음 속에 떠오르는 단어의 뜻을 벡터화한다는 점에서 표상이라는 말이 더 적절하다고 생각한다.

분산 표상은 ‘문장에서 비슷한 위치에 있는 단어는 비슷한 뜻을 가진다’는 분포 가설에 따라 만들어진 방법이다. 예를 들어, ‘나는 기쁘다’, ‘나는 행복하다’ 등의 문장이 나타날 때 분포 가설에 의하면 ‘기쁘다’와 ‘행복하다’는 의미적으로 가까운 단어가 된다. 따라서, 두 단어는 벡터 공간 상에서 가깝게 존재한다. Word2Vec이 분산 표상을 구현하는 방법은 CBOW와 Skip-gram 모델로 나뉜다.

CBOW

CBOW(Continuous Bag of Words)는 문장 내에서 이전 단어와 이후 단어를 통해 중간에 있는 단어를 예측하는 모델이다. 가운데 있는 단어를 ‘center word’, 주변 단어를 ‘context word’라고 한다. 주변 단어를 몇 개까지 볼 지는 윈도우(window)의 크기를 정하여 설정할 수 있다.

그래프가 있는 사진

CBOW는 입력층, 투사층, 출력층으로 이루어져 있다. 입력층은 모두 원-핫 벡터로 변환된 단어가 들어가야 한다. (원-핫 벡터는 벡터 요소 중 하나만 1인 벡터를 말한다.) 입력층과 투사층 사이의 가중치 W는 V x M 행렬이고, 투사층과 출력층 사이의 가중치 W’는 M x V 행렬이다. 따라서, 입력층에서 임베딩하고 난 벡터의 차원은 M이 된다. 그리고, M차원의 벡터는 W’를 거처 V차원의 벡터가 된다.

각 단어의 원-핫 벡터xi가 입력층을 지나 Vi로 변환되면 이 벡터들의 평균인 벡터를 구해야 한다. 구해진 평균 벡터는 W’와 곱해지고, 소프트맥스(softmax) 함수를 취하여 출력값을 결정한다. CBOW는 이렇게 구한 벡터 y’와 중심 단어의 실제 원-핫 벡터인 y와의 오차를 최소화하는 방향으로 W와 W’를 수정한다.

Skip-gram

한편 Skip-gram은 중심 단어로 주변 단어를 예측하는 모델이다.

그래프가 있는 사진

이 방식은 출력 과정에서 소프트맥스 함수를 계산할 때 계산량이 커진다. 수십만개의 언어 집합에서 어떤 단어들이 주변 단어일 확률이 올라간다면, 다른 단어들은 그 확률이 떨어져야 하는데 이 모든 것을 계산해야하기 때문이다.

이러한 문제를 해결하기 위해 Skip-gram은 포지티브 샘플과 네거티브 샘플을 도입한다. 포지티브 샘플은 중심 단어 근처에 있는 주변 단어들이고, 네거티브 샘플은 전체 집합에서 근처에 없는 단어들을 랜덤 추출한 표본이다. Skip-gram은 중심 단어와 주변 단어 쌍이 주어졌을 때 주변 단어가 실제로 중심 단어 근처에 있으면 포지티브 샘플, 그렇지 않으면 네거티브 샘플로 이진 분류하여 학습하는 네거티브 샘플링을 진행한다. 네거티브 샘플링을 통해 skip-gram은 소프트맥스 계산량을 1+k번으로 줄인다. (1개의 포지티브 샘플 1번, k개의 네거티브 샘플 k번)

Skip-gram은 두 단어 벡터의 내적값에 따라 이 단어 쌍이 포지티브 샘플인지 네거티브 샘플인지 분류한다. 벡터의 내적은 코사인 유사도와 비례하기 때문에, 내적 값이 클 수록 단어 벡터는 유사하다고 할 수 있다. 반대로, 내적 값이 작으면 단어 벡터는 벡터 공간 상에서 멀리 존재한다.

이 사이트에 접속하면 한국어 단어의 임베딩 벡터를 직접 연산해볼 수 있다.

FastText

한편, FastText는 페이스북에서 만든 임베딩 모델이다. FastText는 각 단어를 문자 단위 n-gram으로 표현한다. n-gram 방식은 정해진 길이의 단위로 단어를 자르는 것이다. 예를 들어, ‘자연어처리’를 n-gram (n = 3)으로 나누면 ‘자연어’, ‘연어처’, ‘어처리’가 된다. 문자 단위 n-gram은 단어의 임베딩을 문자 단위 n-gram 벡터의 합으로 나타낸다. 이 후의 학습 방식은 Word2Vec의 네거티브 샘플링과 유사하다.