Books/한국어 임베딩

[Books] 행렬 분해 기반 언어 모델 (LSA, GloVe, Swivel)

언킴 2022. 3. 24. 20:31
반응형

행렬 분해는 단어-문서 행렬이나 TF-IDF 행렬 등의 행렬 구조에 차원 축소 방법을 적용해 차원의 수를 줄여 계산 효율성을 키우고, 행간에 숨어 있는 잠재 의미를 파악하는 것이 목표다. 언어 모델이 가질 수 있는 행렬은 단어-문서 행렬, TF-IDF 행렬, 단어-문맥 행렬, 점별 상호 정보량(PMI) 등이 존재하는데, 이번 글에서는 PMI 행렬의 특수한 버전인 PPMI 행렬에 대해서 다루어볼 것이다. 

 

PMI는 두 확률변수 사이의 상관성을 계량화한 지표이며, 두 단어의 등장이 독립을 가정했을 때 대비 얼마나 자주 같이 등장하는지를 수치화한 것이고, 수식은 다음과 같다. 

PMI(A,B)=logP(A,B)P(A)×P(B) 

P(A)×P(B)는 두 단어가 독립이라고 가정했을 때의 조건부 확률이며, PMI가 음수가 될 경우 두 단어가 독립일 때보다 더 적은 빈도로 동시에 등장한다는 것을 의미한다. 하지만 보통 corpus에서의 단어 하나가 등장할 확률을 0.001 이하로 매우 작은 편인데, 두 단어가 동시에 나타날 확률은 엄청나게 작아야 한다. 또한 A,B가 단 한 번도 같이 등장하지 않을 경우 0의 값을 가지는데, log(0)은 정의할 수 없기에 값을 구할 수 없다. 

 

이와 같은 문제로 인해 자연어처리에서는 PMI 대신 PPMI(Positive Pointwise Mutual information)을 사용한다. PPMI는 0보다 작은 값은 전부 0으로 치환해 무시하는 방법이며, 수식은 다음과 같다. 

PPMI(A,B)=max(PMI(A,B),0) 

그 외 Shifted PMI(SPMI)도 있는데, 이는 PMI에서 logk를 빼준 값을 의미하며, kR+이다. Shifted PMIWord2Vec과도 깊은 연관이 있다는 논문도 존재하며, SPMI의 수식은 다음과 같다. 

SPMI(A,B)=PMI(A,B)logk 

 

LSA는 truncatedSVD로 차원을 축소해 분석을 수행할 수 있다. truncatedSVD는 특이값 가운데 가장 큰 d개의 특이값을 가지고 원래 행렬을 근사하는 방식이다. SVD에 대한 내용은 여기를 참고하면 보다 자세히 설명하고 있다. 

 

SPMI, Word2Vec

Levy and Goldbert는 네거티브 샘플링 기법으로 학습된 SGNS(Skip-gram with Negative Sampling) 모델의 학습은 SPMI 행렬을 UV로 분해하는 것과 같다는 것을 증명해 주목을 받았다.[논문] 다음과 같은 관계도가 존재한다. 

AijSGNS=UiVj=PMI(i,j)logk 

여기서 k는 Skip-gram 모델의 네거티브 샘플 수를 의미한다. 네거티브 샘플 수가 1인 경우 Skip-gram은 PMI 행렬을 분해하는 것과 동일하다고 언급한다. 단어 i와 단어 j가 의미상 얼마나 관련이 있는지 정도가 UiVj 내적 값으로 나타나며 관련성이 높을수록 당연히 내적의 값은 커지게 된다. 

 

GloVe

GloVe는 여기에 보다 상세기 작성해두었으니 참고하길 바란다. 간략히 설명하자면, 임베딩된 두 단어 벡터의 내적이 말뭉치 전체에서의 동시 출현 빈도의 로그 값이 되도록 목적 함수(Object Function)을 정의했다. 임베딩된 단어 벡터 간 유사도 측정을 수월하게 하면서도 말뭉치 전체의 통계 정보를 잘 반영하자는 목표를 지향한다. 

J=i,j=1|V|f(Aij)(UiVj+bi+bjlogAij)2 

bf(Aij)는 임베딩 품질을 높이기 위해 고안된 장치이다. 동시 출현 빈도의 로그 값을 구하기 위해서는 먼저 동시 출현 빈도 행렬을 구축해야 한다. 처음에는 UV를 랜덤으로 초기화한 후 목적 함수를 최소화하는 방향으로 학습해 나간다. 이외에 U+VT, UVT를 이어 붙여 임베딩으로 사용하기도 한다. 

 

 

Swivel

Swivel (Submatrix-Wise Vector Embedding Learner)은 구글에서 2016년 발표한 행렬 분해 기반 임베딩 기법이다. PMI 행렬을 UV로 분해하고, 학습이 완료되면 U를 단어 임베딩으로 사용할 수 있다. 이처럼 단어-문맥 행렬이 아닌 PMI 행렬을 분해한다는 점에서 GloVe와는 다른 방법이다. 

J=12f(xij)(UiVjPMI(i,j))2 

하지만 PPMI 행렬이 아닌 PMI 행렬은 두 단어가 한 번도 동시에 등장하지 않았을 때 PMI는 음의 무한대로 발산하기에 이와 같은 케이스에 한해 다음과 같이 목적함수를 별도로 설정했다. 

J=log(1+exp(UiVjPMI(i,j))) 

PMI(i,j)=logP(i,j)P(i)×P(j)=logAij/|D|Ai/|D|×Aj/|D|=logAij×|D|Ai×Aj=logAij+log|D|logAilogAj 

|D|는 corpus의 길이를 의미하고, Ai,Aj는 각각 i의 단독 빈도, j의 단독 빈도를 의미한다. P(i,j)ij가 동시에 출현할 확률을 의미하기에 Aij|D|로 표현할 수 있을 것이며, 나머지 확률도 동일하게 구할 수 있다. 위 수식을 목적함수에 대입하면 다음과 같다. 

J=log(1+exp(UiVjlog|D|+logAi+logAj))

본 논문에서는 학습하기에 앞서 다음과 같은 두 가지 가정을 가지고 학습을 수행한다. 

 

1. i,j가 각각의 빈도 수는 높지만, 동시 출현 빈도 수가 0이라면 두 단어는 의미상 무관계한 단어일 것이다.

2. i,j가 각각의 빈도 수가 낮고, 동시 출현 빈도 수가 0이라면 두 단어는 의미상 관계가 일부 존재할 것이다.

 

첫 번째의 경우 직관적으로 이해할 수 있다. 두 번째의 경우에는 두 단어의 빈도 수가 적은 것이 우리의 데이터 확보가 적기 때문에 빈도 수가 적게 나타난 것 일수도 있기에 일부 관계가 있다고 판단해 학습을 할 때 약간 크게 되도록 학습을 수행한다. 

 

LSA와 GloVe, Swivel의 코드는 여기를 참고하면 된다.