Skip to content

Text Embedding

warmwall edited this page Feb 9, 2020 · 14 revisions

인공신경망 모델의 입력값은 숫자이다. 텍스트를 딥러닝에 이용하려면 숫자 형태로 되어 있는 Vector 형태로 바꿔주어야 한다. 이 것을 단어/문장/글을 임베딩(Embedding)한다고 부른다.

1. 통계 기반 단어 임베딩

1-1. 분포 가설(distributional hypothesis)

  • 단어의 의미는 주변 단어에 의해 형성된다
  • 단어를 벡터로 표현하는 최근 연구도 대부분 이 가설을 따라 형성됨

1-2. 분산 표현(distributional representation)

  • 단어의 의미를 정확하게 파악할 수 있는 벡터 표현

1-3. 동시발생 행렬

  • 어떤 단어에 주목했을 때 그 주변에 단어가 몇 번 등장하는지를 세어 집계하는 방법
  • you say goodbye and I say hello.라는 문장이 있을 때, window size=1인 경우 동시발생 행렬은 아래와 나타낼 수 있다.
  • 벡터 간 유사도는 코사인 유사도를 이용해 계산할 수 있다.
word you say goodbye and I say hello .
you 0 1 0 0 0 0 0 0
say 1 0 1 0 1 1 1 0

1-4. 점별 상호정보량(Pointwise Mutual Information, PMI)

image

1-5. 차원 감소

  • 중요한 정보는 최대한 유지하면서 벡터의 차원을 줄이는 기법

1) 특이값분해(Singular Value Decomposition, SVD)

  • X = USV^T)
  • U, V는 직교행렬(orthogonal matrix)이고, 그 열벡터는 서로 직교한다.
  • S는 대각행렬(digonal matix). 해당 축의 중요도로 간주할 수 있는 특잇값(singular value)이 큰 순서대로 나영되어 있음.
  • S 행렬에서, 특잇값이 적은 원소를 잘라내는 방식으로 벡터 차원을 감소시킬 수 있다.

2. Word2vec의 등장

  • NLP (Natural Language Processing, 자연어처리) : 컴퓨터가 인간이 사용하는 언어를 이해하고 분석할 수 있게 하는 분야
    • ex) 'Naive Bayes'를 사용한 스팸 메일 분류기
  • 성능 자체는 좋지만, 단어가 다른 단어와 어떤 차이점을 가지는지는 이해할 수 없다 -> 벡터화 고안

NNLM -> RNNLM -> CBOW, Skip-gram (2013) -> word2vec

2-1. word2vec 이전의 모델

1) NNLM(Feed-Forward Neural Net Language Model)

image

a. 구성

Input layer, projection layer, hidden layer, output layer

  1. 문장에서 현재 보고 있는 단어 이전의 단어 N개를 one-hot encoding으로 vector화 한다
  2. vocab size를 V라 하고, projection layer의 size를 P라 했을 때, 1.의 vector들은 VxP 크기의 projection matrix에 의해 다음 레이어로 들어간다
  3. 2.의 값을 input이라 생각하고, 크기 H의 hidden layer를 거쳐 output layer에서 각 단어들이 나올 확률을 계산한다
  4. 이를 back-propagation해서 네트워크의 weight를 최적화한다
  • 1-4에서 사용하게 될 단어의 vector들은 projection layer의 값으로서, 각 단어들은 크기 P의 vector가 된다
  • 현재의 neural network 기반 단어 학습 모델은 거의 이 모델에서부터 발전

b. NNLM의 단점

  • 몇개의 단어를 볼 건지에 대한 파라미터 N이 고정되어야 하고, 따로 정해줘야 한다
  • 이전의 단어들에 대해서만 신경쓰고 뒤의 단어는 고려하지 못한다
  • 느리다 (치명적)

c. 계산 시간

  • 단어들을 projection 시키는 것 (2) : NxP
  • projection layer에서 hidden layer로 넘어가는 것 (3) : NxPxH
  • hidden layer에서 output layer로 넘어가려면 모든 단어에 대한 확률 계산 (3) : HxV

=> parameter 개수 = NxP + NxPxH + HxV

  • 보통 vocab size V는 1,000만 개 정도. N=10, P=500, H=500.

=> O(HxV) = O(50억)

d. 개선

HxV -> Hxln(V) : O(NxPxH) = O(250만)

2) RNNLM(Recurrent Neural Network)

image

  • NNLM을 RNN형태로 변형 (projection layer가 없다)

a. 구성

Input, hidden, output layer

hidden layer에 recurrent한 연결이 있어 이전 시간의 hidden layer의 입력이 다시 입력되는 형식

  • U : word embedding으로 사용
  • H : hidden layer의 크기

각 단어는 길이 H의 vector로 표현된다.

b. RNNLM의 특징

  • NNLM과 다르게 몇 개의 단어인지에 대해 정해줄 필요가 없다.
  • 학습시켜줄 글의 단어를 순차적으로 입력하는 방식으로 학습 진행
    • recurrent한 부분이 short-term memory 역할을 하면서 이전 단어를 보는 효과

c. RNNLM의 연산량

  • input layer에서 hidden layer로 넘어가는 것 : H
  • hidden(t-1)에서 hidden(t)로 넘어가는 vector 계산 : HxH
  • hidden layer에서 output결과를 내기 위해 모든 단어에 대해 확률계산 : HxV
  • 복잡도 : O(HxH + HxV)

d. 개선

  • V -> ln(V).
  • 복잡도 : O(HxH)
  • H = 500 -> O(24만)
  • NNLM이 O(250만)이었던 것을 생각하면 1/N배 줄어든 것

2-2. word2vec과의 성능 비교

1) Analogy Reasoning Task

image

  • 성능 비교 실험
  • pair / (Athens, Greece) -> Oslo -> 결과 를 주는 방식
  • semantic : 수도, 화폐, 주, 도시에 관련된 것
  • syntactic : 문법에 관련된 것

위의 표에서는 v(Greece)-v(Athens)+v(Oslo) = v(Norway)

2) 모델 비교

image

  • 단어 벡터 길이 : 640

  • RNNLM, NNLM에 비해 CBOW, Skip-gram이 Semantic, Syntactic에 대해 더 좋은 결과

    • Skip-gram이 Syntactic에 대한 정확도는 낮다
    • 하지만 Semantic에 대해서는 훨씬 높은 결과

3) 모델을 300dimension Skip-gram으로 고정한 결과

image

  • NEG-k : k개 단어를 선택한 negative sampling
  • HS-Huffman : Huffman Tree를 이용한 Hierarchical Softmax
  • NCE-k : negative sampling과 유사한 방법. Noise Contrastive Estimation
    • 이 방법을 기초로 하여 목적함수를 조금 바꿔 negative sampling 생성

전체적으로 Hierarchical softmax를 사용한 것보다 negative sampling이 더 좋은 결과

자주 등장하는 단어를 subsampling하면 학습시간이 줄어들고, 성능도 향상

하지만, 여기서 Hierarchical softmax가 안좋게 나왔다고 실제 나쁜 방법은 아님!

  • phrase에 대해 실험을 하면 Hierarchical softmax >> Negative sampling
  • 어떤 문제에 적용하는지에 따라 성능이 달라진다.

  • NNLM, RNNLM 은 단어를 벡터화하는 데 좋은 방법이지만, 학습이 너무 느리다.
  • 이걸 해결하기 위해 word2vec이 등장하였다.

3. Word Embedding model

  • 제한된 차원으로 단어를 vector로 나타내는 방법

    • 장점
      • 단어 벡터 간의 유사도를 코사인 유사도로 구할 수 있다. (one-hot encoding의 단점 해결)
      • 필요한 벡터 차원 수가 적다.
  • Word Embedding의 예

    • 근처에 나온 단어/비슷한 단어일수록 벡터 간의 유사도가 높다.
      예를 들어 '아이폰 성능'이라는 문장이 나오는 빈도가 높다면 '아이폰' 벡터와 '성능' 벡터의 위치가 비슷할 것이다. (두 벡터 간의 유사도가 높다.)
    • 단어 벡터 간의 덧셈/뺄셈 후에도 그 관계가 유지. 벡터의 위치와 거리가 실제 단어 간의 관계를 반영.
      예를 들어 의사-여자+남자와 같은 연산을 하면 '남의사' 벡터와 가까운 결과가 나오게 된다.
  • 딥러닝 기반 자연어처리 기법의 최근 연구 동향: 2017년 8월 기준.

  • Cosine Similarity - 코사인 유사도

3-1. Word2Vec

단어를 하나의 벡터로 임베딩하는 방법 중 하나이다. 임의의 차원(128차원 등)을 가진 벡터 공간의 한 점이 하나의 단어를 의미한다. 한 단어가 있을 때 주변에 나온 단어와의 거리를 좁히고, 주변에 안 나온 단어와의 거리는 넓히는 방식으로 학습한다.

1) 한국어 Word2Vec

word2vector는 bin 형식이나 tsv 형식으로 되어 있다. gensim 라이브러리를 이용해서 쉽게 로딩할 수 있다.

Pre-trained word vectors of 30+ languages는 wikipedia database backup dump를 기반으로 만들어진 word vector으로, 30여 개 언어의 word vector를 제공한다. 사실상 한국어로 된 유일한 word vector이다. 여기서 제공하는 code를 이용해 새롭게 word vector를 만들 수도 있다. 기본으로 제공하는 model은 최대 2만개 단어만 있으므로 이 개수를 늘릴 수 있다.

>>> import gensim
>>> model = gensim.models.Word2Vec.load('ko.bin') # word vector 로딩

>>> model['인공지능'] # 인공지능 word vector를 numpy array 형태로 출력
array([-0.06324194, -0.6008734 , -0.26231512,  1.3287116 , -0.32701576,
        0.5631857 , -0.7717267 ,  0.31624222, -0.02853541, -0.39608407,
(중략)
       -0.2817213 ,  0.3327664 ,  0.15192133,  0.14019588, -0.8833335 ],
      dtype=float32)

>>> model.most_similar(['한국어', '미국'], ['한국']) 
# word vector를 "한국어 + 미국 - 한국"으로 계산했을 때 가장 가까운 것. 미국의 한국어, 즉 미국의 언어를 의도함.
[('영어', 0.6886879801750183), ('일본어', 0.549891471862793), ('영문', 0.5408982038497925), 
('언어', 0.5347272157669067), ('독일어', 0.5142326951026917), ('프랑스어', 0.5100058317184448), 
('모국어', 0.47583508491516113), ('스페인어', 0.46559274196624756), 
('중국어', 0.4549825191497803), ('영어권', 0.4537474513053894)]

>>> model.n_similarity('한국', '한국어') 
# '한국' word vector와 '한국어' word vector 간의 코사인 유사도
0.76380414

>>> model.n_similarity('한국', '영어') 
# 한국-한국어 간의 similarity가 한국-영어 간의 similarity보다 큰 것에 주목.
0.08317596

# 미국과 영어와의 similarity는 낮은데 영국과 영어의 similarity는 높음. 미국의 공용어도 영어인데 similarity가 낮게 나왔음. 
이와 같이 word2vec이  학습되지 않은 사례가 있을  있음.
>>> model.n_similarity('미국', '영어')
0.11053801
>>> model.n_similarity('영국', '영어')
0.42289335

이 외 더 자세한 사용 방법은 gensim model example을 참고하면 된다.

  • 한국어 Word2Vec: 한국어 word2vec 모델을 만드는 방법을 설명한 글.
  • 한국어 Word2Vec 데모: 단어 벡터 간의 연산(덧셈, 뺄셈)을 해서 가장 가까운 단어를 찾아 주는 데모. 꽤 쓸만한 품질을 보여준다.

3-2. Doc2Vec

한 문장이나 문단, 문서를 하나의 Vector로 임베딩하는 방법이다. Word2Vec을 확장한 개념으로, document vector가 각 문장/문단/문서에 나온 단어 vector들과 가까워지도록 학습을 시킨다. word2vec과 마찬가지로 doc2vec도 gensim에서 구현이 되어 있기 때문에 라이브러리로 바로 쓸 수 있다.

두 문장이 있을 때 그 문장에 있는 단어들의 word vector가 유사할수록 document vector도 유사하게 나온다. 예를 들어 "고양이가 길을 건넌다."와 "강아지가 길을 건넌다."에서는 고양이와 강아지의 word vector가 유사하기 때문에 document vector도 유사하게 나올 것이다. 그런데 "강아지가 길을 건넌다"와 "로봇이 길을 건넌다"에서 강아지와 로봇의 word vector는 덜 유사할 것이기 때문에 document vector도 앞선 예시보다는 덜 유사할 것이다.

3-3. Sent2Vec

  • 문장 하나를 하나의 벡터로 임베딩하는 방법
  • 학습 방법
    • CBOW를 변형하여 Context를 학습한다.
      • Window Size를 문장 전체로 고정: 문장 전체의 의미를 살리기 위해 문장의 모든 n-gram을 조합하여 학습하므로
      • Subsampling을 사용하지 않음: 중요한 n-gram 쌍 생성을 방해할 수 있기 때문에.
    • 변형된 CBOW를 사용하여 문자 n-gram 쌍, 단어 n-gram 쌍을 Context로 하여 학습한다. 여기서 n-gram은 일반적인 n-gram이 아니라, bi-gram의 최대 거리를 의미한다. 단, 한글에선 조합 가능한 문자 수 특성상 문자 n-gram은 사용하지 않는다.
    • Sent2Vec을 구할 땐 가능한 모든 Context 벡터의 평균을 내어 구한다.
  • 문장을 Sent2Vec으로 바꾸고, Sent2Vec 간의 코사인 유사도를 구하면 문장 간의 유사도를 구할 수 있다.

관련 논문

Clone this wiki locally