본문 바로가기
기계학습/자연어 처리 머신러닝

워드 임배딩 - 딥러닝을 이용한 자연어처리 입문

by tryotto 2020. 1. 28.

# 워드 임베딩


- 정의 : 단어를 벡터로 표현 + 밀집 표현





# 희소표현 vs 밀집 표현


- 희소 표현 : 벡터 또는 행렬이 대부분 0으로 채워져 있는 경우

> 단점 :

1) 공간적 낭비 : 쓸데없는 것까지도 다 표현을 해야 함 (0으로 표시)

유사 사례) DTM 방식

2) 단어의 의미를 담지 못함 -> 단어간의 유사성을 찾지 못함

> sol : 분산표현 (밀집표현 방식이 약간 섞임) ->이 연산의 결괏값인 벡터 = "임베딩 벡터"


- 밀집 표현 

> 장점 : 

1) 사용자가 설정한 차원수만큼으로 줄일 수 있다.

2) 0, 1로만 구성된 것이 아니라, 0이상 1이하의 실수 값을 갖는다

3) 단어 간 유사도를 담을 수 있다.


- 분산표현 

> 가정 : 비슷한 위치에서 등장하는 단어들은 비슷한 의미를 가진다 (=분포가설)

> 방식 : 단어의 의미를 "여러 차원에 분산시킴" 

-> 이렇게 해서, 가까이 있는 단어들끼리는 유사함을 드러낼 수 있음

> 예시 : NNLM, RNNLM, word2Vec





# word2Vec


- 종류 :

1) skip-gram : 중간에 있는 단어 -> 주변 단어 예측

2) CBOW : 주변 단어 -> 중간에 있는 단어 예측

> skip-gram 성능 > CBOW 성능


- CBOW 방식

- 윈도우 크기 설정 : n 으로 설정할 경우, 양쪽에 있는 2n 개의 단어들을 관찰

> 계속 오른쪽으로 차근차근 움직여가며 단어 중간 단어 예측

- 입출력 형식 : 원핫벡터

- 중간 레이어 : projection layer

> 중간 레이어가 하나밖에 없음 : 딥러닝 방식이 아님

> 또한, 중간 레이어 치고는 활성화 함수가 없음

> projection 으로 들어갈때 필요한 행렬 + 출력층으로 나갈때 필요한 행렬 

: 이렇게 두 가지 행렬 필요 (transpose한거 아님)

- 이때, 각 행렬의 i 번째 행은 i 번째 입력 원핫벡터에 대해 word2Vec을 적용을 시킨 후의, 바뀐 차원을 갖는 값들이다

> 따라서, CBOW의 목적 = 이 행렬들을 잘 훈련시키는 것.

- 원핫벡터와 행렬의 곱? -> 사실상, look up 테이블 방식으로 작동하는 것과 다름없다.

- 행렬의 각 i 번째 벡터 = 임베딩 벡터  라고 볼 수 있다.

> 행렬 곱이 끝난 다음엔, 평균값을 구해줘야 한다 

-> skip gram과의 차이점 (skip gram은 애초에 단어 하나를 가지고 주변단어를 예측. 평균 할 이유가 없음)

- 출력 층 : softmax 함수 적용, 함수로 표현됨 (=score vector)

> 오차를 줄이기 위해, 손실함수로 cross entropy 사용

(일반적으로, softmax 를 거친 경우는 cross entropy를 사용하는 편임)

- 학습 : projection 의 입출력을 담당하는 행렬을 학습함





# NNLM  vs  word2Vec


- 속도 비교 : NNLM << word2Vec

> 이유 1 : 은닉층의 존재여부 

- 은닉층 없을수록 빠름

> 이유 2 : 추가 기법의  사용 <- 소프트맥스, 네거티브 샘플링

- 추가기법 사용할수록 더 빨라짐


- 은닉층(hidden layer) 의 존재여부 

> NNLM : 은닉층 있음

> word2Vec : 은닉층 없음


- 네거티브 샘플링 사용여부

> NNLM : 사용 안함 

   word2Vec : 사용 함

> 효과 : 시간 복잡도를 V 에서 logV 로 줄일 수 있음







# 네거티브 샘플링


- word2Vec 의 주요 기법 : SGNS = skip gram negative sampling


- 의의 : word2Vec 방식으로 파라미터들을 학습하는 과정에서, "모든" 단어들을 softmax 처리해서 역전파로 학습함 -> 비효율적이지 않나?

> 굳이 관련이 적은 단어들까지 매번 학습을 시킨다면, 연산량이 너무 많음

> 관련 없는 단어들의 경우, 몇 개만 선별해서 고르자! 그렇게 선별된 일부의 단어들만 학습하자!

= negative sampling


- 결론 : 두 가지 방식을 모두 활용하자!!






# Glove


- Glove vs word2Vec

> 의의 : 카운트 기반 LSA, 예측 기반 word2Vec 의 단점을 보완하려고 했음 (실제로 보완이 된건지는 논란)

1) 카운트 기반 : 각 단어들의 빈도 check -> 차원 수 감축 -> 잠재된 의미 추출

2) 예측 기반 : 실제 값과 모델의 예측값을 계속 비교하며 오차를 줄여나가는 방식

> 각 방식들의 한계

1) 카운트 기반 : 전체 통계량을 고려하긴 하지만, 의미 추론이나 예측에는 약함

2) 예측 기반 : 의미 예측, 추론에는 강하지만, window 크기만 고려하기 때문에 전체 corpus 의 의미를 고려하지 못한다는 한계점


-  윈도우 기반 동시 등장 행렬 (window based co-occurrence matrix)

1) corpus 에서 단어들이 총 몇 가지가 등장했는지 세기

2) n 개의 단어가 등장했다고 했을때, n*n 행렬을 만들기

3) 윈도우 크기를 k 라고 했을때, arr[i][j] 는 i 행의 단어와 j 열의 단어가 윈도우 크기 k 보다 거리가 짧을 경우, 숫자를 1 늘려준다

> 이런 방식 때문에, transpose 해도 똑같은 matrix 를 보인다


- 동시 등장 확률 (co-occurence probobility)

> 식 : P( k | i ) : i 단어가 등장했을 때,주변에 k 단어가 등장할 확률

> 사용 방법 : P( a | i ) / P( b | i ) 의 값이 큰지, 작은지를 고려해야 함


- Glove 의 기본 아이디어 : 임베딩 된 중심 단어의 벡터와 주변 단어 벡터의 내적이, 전체 코퍼스의 동시 등장 확률이 되도록 만드는 것

> 순서 (반드시 링크 확인하기)

1) 기본 아이디어 그대로 식을 완성시키고 싶음 -> 쉽지 않다

2) 이걸 해결하기 위해, 앞서 배웠던 동시 등장 확률을 이용

3) 자유로운 교환 연산이 가능하도록 하기 위해선, "준동형" (=Homomorphism) 을 만족해야 함

4) exponential 을 적용하면 완벽하게 만족함

5) logX를 계산하는게 만만치 않음 -> 편향 값인 b 로 대체해서 계산하기

6) logX 에서, X 값이 0 이 나올수도 있음(모순) -> log(1+X) 로 식을 수정

7) 희소행렬처럼 비춰짐 -> 연산이 비효율적임 -> 가중치 함수를 도입

- 목표 : 등장 빈도가 적은 경우, 1보다 작은 소수를 곱해서 영향력을 더 줄이고,

           등장 빈도가 어느정도 있다고 하더라도 폭발하지 않도록 1 이 최대 가중치가 되도록 함