자연어처리 바이블, 딥 러닝을 활용한 자연어 처리 wikidocs 등을 참조해서 공부하며 정리했습니다.
과거의 단어 임베딩 기술이 채택했던 아이디어와 각 알고리즘의 단점을 개선하고자 했던 방법들을 알아본다.
0. 요약
Word2Vec 이전
- 1990년대 초부터 널리 사용
- 잠재 의미 분석(latent semantic analysis, LSA), 잠재 디리클레 할당(latent dirichlet allocation, LDA) 활용
Word2Vec
- 단어 임베딩 열풍을 불러옴
- ELMo 이전까지의 임베딩은 단어 단위 임베딩
- 2013년도 Mikolov et al.이 발표한 두 편의 논문에서 제안된 알고리즘의 이름
- 두 개 계층을 사용하는 얇은 것 : 학습 방법이 단순해서 더 많은 데이터를 활용할 수 있고 성능 향상됨. 이는 모델 복잡도보다 데이터의 양이 더 중요하다는 예시다.
- 학습에는 두 종류 모델을 사용할 수 있다. Continuous-Bag-Of-Words(CBOW)와 Skip-gram이다. 언어의 문맥이 양방향 의존성을 가지고 있다는 점을 잘 활용했다. CBOW 모델은 특정 단어를 중심으로 이전과 이후 n개의 단어가 주어졌을 때 중심 단어를 예측하는 것을 목표로 한다. 반대로 skip-gram 모델은 중심 단어가 주어졌을 때 이전과 이후 n개의 단어를 예측한다. 또한 확률적으로 더 먼 거리의 단어를 선택함으로써 넓은 의미의 문맥을 단어 벡터 학습에 활용할 수 있게 했다.
GloVe
- Pennnigton et al.의 2014년 논문에서 제안됨
- word2vec과 함께 가장 많이 쓰이는 단어 임베딩 기술
- word2vec의 부산물인 단어 벡터 공간에서의 연산을 통한 의미 표현(서울-한국+일본=도쿄)을 직접적인 학습 목표로 삼음.
- 이를 위해 단어 간 동시 발생 빈도의 비율이 벡터 공간상 차이로 나타나도록 단어 임베딩 수행.
- 따라서 GloVe 벡터의 학습에는 단어 간 동시 발생 빈도만 필요함. 말뭉치에서 이를 추출해서 학습.
FastText
- 2016년에 Facebook Research에서 공개함.
- 각 단어가 더 작은 단위로 나뉘어질 수 있다는 점에 착안함.
- 각 단어를 여러 n-gram들의 집합으로 분리한 후 각 n-gram에 대한 벡터를 학습한다.
- 구체적인 학습 방법은 word2vec과 거의 동일하다.
1. 워드 임베딩
텍스트를 컴퓨터가 이해하고 처리하도록 하기 위해서 단어를 숫자로 변환하는 작업이 필요하다.
Sparse Representation(희소 표현)과 원핫 인코딩
[감자, 고구마, 옥수수, 메밀] 이라는 단어의 집합이 있다고 할 때, 감자=<1, 0, 0, 0>, 고구마=<0, 1, 0, 0>, 옥수수=<0, 0, 1, 0>, 메밀=<0, 0, 0, 1> 처럼 각 단어의 위치에 해당하는 요소만 1이고 나머지는 0인 벡터로 바꾸는 인코딩을 원핫 인코딩이라고 하고, 이는 희소 표현에 해당한다.
이 방법은 단어의 개수가 늘어날수록 저장 공간이 계속 증가한다는 단점이 있다. 또한 원-핫 벡터는 단어의 유사도를 표현하지 못한다. 이는 검색 시스템 등에서 문제가 발생할 수 있으며 이를 해결하기 위해 카운트 기반의 벡터화 방법, 예측 기반의 벡터화 방법 등이 생겨났다. 카운트 기반으로는 LSA, 예측 기반으로는 Word2Vec, FastText 등이 있으며 두 가지 모두를 사용하는 방법으로는 GloVe가 있다.
Distributed Representation(분산 표현)
ex) 도마뱀 = <1.2 0.79 0.53.....>
이 경우 10,000개의 단어를 표현하기 위해 10,000개 차원의 벡터를 쓸 필요가 없다.
2. 카운트 기반의 단어 표현
Bag of Words(BoW)
<예시 글>
정부가 발표하는 물가상승률과 소비자가 느끼는 물가상승률은 다르다.
'정부': 0, '가': 1, '발표': 2, '하는': 3, '물가상승률': 4, '과': 5, '소비자': 6, '느끼는': 7, '은': 8, '다르다': 9
bag of words vector : [1, 2, 1, 1, 2, 1, 1, 1, 1, 1]
BoW는 단어 등장 횟수를 카운트하는 방법이므로 문서를 분류하거나 유사도를 구하는 문제에 주로 쓰인다. 예를 들어 ‘보리’, ‘쌀’, ‘트랙터’, ‘비료’ 등의 단어가 자주 등장하면 농업 관련 문서로 분류할 수 있을 것이고, ‘그물’, ‘어선’, ‘오징어’, ‘파도’ 등이 빈출한다면 이는 어업 관련 문서로 분류할 수 있다.
예시에서, 한국어에서의 불용어인 조사와 같은 것들을 제거한다면 더욱 정제된 BoW가 될 것이다.
DTM, Document-Term Matrix(문서 단어 행렬)
문서1 : 먹고 싶은 사과
문서2 : 먹고 싶은 바나나
문서3 : 길고 노란 바나나 바나나
문서4 : 저는 과일이 좋아요
이 방식은 간단하고 구현하기도 쉽지만 원-핫 벡터의 단점을 그대로 가지고 있다.
그리고 영어에서는 the 같은 불용어들이 문서마다 자주 등장할 수밖에 없다. 임의 문서 두 개의 유사도를 판단할 때 the가 둘 다 자주 등장한다고 해서 두 문서가 유사하다고 판단해서는 안 된다.(the는 불용어로 제거될 것이지만 이해하기 쉬운 예시를 들었다) 그래서 단어 간의 중요도에 대해 가중치를 주기 위해 TF-IDF 방법이 고안되었다.
TF-IDF, Term Frequency-Inverse Document Frequency
TF와 IDF를 곱한 값을 의미한다. 이를 식으로 표현하면,
- d: 문서, t: 단어, n: 문서의 총 개수
- tf(d, t) : ‘특정 문서 d에서의 특정 단어 t의 등장 횟수.
- df(t) : 특정 단어 t가 등장한 문서의 수
- idf(d, t) : df(t)에 반비례하는 수
$$ idf(d, t)=log(\frac{n}{1+df(t)}) $$
LSA, Latent Semantic Analysis(잠재 의미 분석)
위에서 알아본 DTM이나 TF-IDF 행렬은 오직 카운트 기반이기 때문에 단어의 의미를 전혀 고려하지 못한다는 단점을 갖는다. LSA는 DTM이나 TF-IDF 행렬에 truncated SVD(절단된 SVD)를 사용하여 차원을 축소시키고 단어들의 잠재 의미를 끌어낸다는 아이디어를 갖는다.
U는 topic을 위한 word들의 행렬, \(\Sigma\)는 topic들의 기여도(Scaling vector), V는 topic을 위한 document들의 행렬이다. 여기서 Truncated SVD를 적용하면...
값의 손실이 일어나며 기존의 A는 복구할 수 없지만 차원을 축소함으로써 중요한 데이터를 남기고 연산량을 줄일 수 있다.
쉽고 빠르게 구현이 가능하고 잠재의미를 이끌어 낼 수 있어서 유사도 계산 등에서 좋은 성능을 보여준다. 단점은, 이미 계산된 LSA에 새로운 데이터를 추가하기 위해서는 처음부터 다시 계산해야 한다는 점이다. 즉 새로운 정보로 업데이트가 어렵다. 때문에 LSA 대신 인공신경망 기반 방법론인 Word2Vec이 각광받기 시작했다.
3. Word2Vec - 2013
NNLM(Neural Net Language Model) (Word2Vec 이전)
- 2003년 Bengio에 의해 소개됨.
- 연속적인 단어가 주어졌을 때 이전 단어로 현재 타깃 단어를 예측하는 Predictive based model.
- 의미 있는 벡터로 임베딩할 수는 있었으나 학습 셋이 늘어나면 속도가 매우 느려짐.
- 다음 단어를 예측하는 모델이 목적이므로 임베딩할 수 있다는 점은 같지만 처음부터 임베딩이 목적인 Word2Vec과는 방향성이 다르다.
Word2Vec 임베딩은 벡터 간 유사도를 반영한다
서울 - 한국 + 일본 = 도쿄
queen - woman + man = king
Word2Vec 임베딩을 사용하면 위와 같은 연산이 가능하다.
이는 원-핫 인코딩과 같은 sparse representation(희소 표현)으로는 불가능한 동작이다. Word2Vec은 분산 표현(distributed representation) 방법을 채택하고 있다. 이는 기본적으로 분포 가설(distributional hypothesis), 즉 ‘비슷한 문맥에서 등장하는 단어들은 비슷한 의미를 가진다’를 가정한다.
예를 들어, 희소 표현에서 오징어=[0, 0, ..., 1, 0, 0, ..., 0] 이었다면, 분산 표현에서는 [0.1, 0.53, ..., 0.38, 0.01] 처럼 저차원의 공간에서 벡터의 각 요소들은 실수 값을 가진다.
CBOW(Continuous Bag of Words)
Word2Vec의 학습 방식은 두 가지로, CBOW와 Skip-Gram이 있다. CBOW는 주변에 있는 단어들을 입력으로 가운데에 있는 단어를 예측하는 방법이다. 그림을 보자.
중심 단어를 예측하기 위해 양 옆으로 몇 개의 단어를 볼 건지를 정한다. 그 범위를 window라고 하며, 이 예시에서는 window size가 2이다. 결국 실제로 참조하는 단어의 개수는 2*(window size) 인 4개다.
윈도우 크기가 정해지면 윈도우를 옆으로 움직이면서 학습을 위한 데이터 셋을 만든다.
CBOW의 신경망을 도식화하면 위 그림과 같다. fat, cat, on, the 네 개의 원핫 인코딩된 단어 벡터들로 sat을 예측할 수 있게 훈련한다.
Word2Vec의 신경망은 다수의 은닉층을 가진 딥러닝 모델이 아니라 은닉층이 한 개인 얕은 신경망(shallow neural network)이라는 것을 알 수 있다. 또한 Word2Vec에서는 일반적인 은닉층과 달리 활성화 함수가 존재하지 않는다. 훈련하는 과정을 더 자세히 살펴보면,
위와 같다.
그림에서 cat, on, fat 등은 1행 7열의 벡터로 원핫 인코딩되며, $W$는 7행 5열의 가중치 벡터이다. 윈도우 사이즈가 2이므로 4개의 임베딩된 벡터에 $W$를 곱해서 평균을 구한다. 그 평균값에 5행 7열의 $W'$ 벡터를 곱해서 가운데 있을 단어를 예측한다. 훈련하는 과정은 위 두 개의 가중치 행렬을 최적화하는 작업이다. 역전파를 수행하면 학습할 수 있다. CBOW는 손실 함수로 크로스 엔트로피 함수를 사용한다.
$$ cost(\hat{y}, y)=-\sum_{j=1}^{V}{y_jln(\hat{y}_j)} $$
Skip-gram
CBOW에서는 주변 단어를 통해 중심 단어를 예측했다면, Skip-gram에서는 반대로 중심 단어를 통해 주변 단어를 예측한다. 신경망은 다음과 같다.
중심 단어 하나를 입력으로 받기 때문에 CBOW에서처럼 벡터의 평균을 구하는 과정이 없다는 것이 가장 큰 특징이다. 자주 등장하지 않는(rare) 단어에 대해 Skip-gram이 CBOW보다 좋다고 알려져 있다.
왜 Skip-gram의 성능이 CBOW보다 좋은가?
https://code.google.com/archive/p/word2vec/ 에 따르면, skip-gram은 훈련 속도는 느리지만 자주 등장하지 않는 단어에 대해 성능이 좋은 반면 CBOW는 skip-gram보다 속도가 빠르다고 한다.
예를 들어 보자. yesterday was really [...] day. 라는 문장이 있다. [...] 안에 들어갈 단어는 beautiful 또는 nice일 것이다. CBOW 모델에서 delightful이라는 단어는 앞선 두 단어에 밀려서 고려되기 힘들 것이다. 하지만 skip-gram에서는 중심 단어로 문맥을 예측하기 때문에 delightful+문맥 또한 훈련 시 중요하게 고려된다. 그렇기 때문에 skip-gram에서는 더 많은 훈련 데이터가 필요하고 속도가 상대적으로 느린 대신 자주 등장하지 않는 단어에 대해 더 높은 성능을 보인다.
NNLM과의 차이
앞서 언급했던 것처럼 NNLM은 다음 단어를 예측하는 모델이고 Word2Vec은 워드 임베딩을 목적으로 NNLM의 느린 학습 속도와 정확도를 개선한 방법이다.
Word2Vec이 속도가 빠른 이유는 은닉층이 하나밖에 없어서인 이유도 있지만, 추가적으로 사용되는 기법들 덕분이기도 하다. 방법으로는 계층적 소프트맥스(hierarchical softmax)와 네거티브 샘플링(negative sampling)이 있다.
연산량은 다음 식과 같다.
$$ (n\times m)+(m\times log(V)) $$
계층적 소프트맥스에 대한 설명은 본 블로그의 이 글을 참조.
4. GloVe(Global Vectors for Word Representation) - 2014
스탠포드대 Glove 연구팀의 주장을 읽어보자.
While methods like LSA efficiently leverage statistical information, they do relatively poorly on the word analogy task, indicating a sub-optimal vector space structure. Methods like skip-gram may do better on the analogy ask, but they poorly utilize the statistics of the corpus since they train on separate local context windows instead of on global co-occurrence counts.
즉,
Word2Vec(예측 기반) : 윈도우 사이즈 안에서만 예측하잖아? 문장의 전체적인 통계 수치를 고려하지 못해!
LSA(카운트 기반) : 카운트 기반이라서 단어의 의미를 반영하지 못해! 유사도 측정하기 어려워!
→ → → 그럼 둘을 합치면 되지! GloVe 탄생.
결과 : Word2Vec과 GloVe 중 어느 것이 낫다 라고 할 수는 없고, 둘 다 써보고 나은 것을 그때그때 쓰면 된다.......
🍕
윈도우 기반 동시 등장 행렬(Window based Co-occurrence Matrix)
윈도우 크기가 1일 때, 다음 문장에서 단어들이 동시 등장하는 횟수를 행렬로 만들어 보자.
• I like deep learning
• I like NLP
• I enjoy flying
동시 등장 확률(Co-occurrence Probability)
\(i\) : 중심 단어, \(k\) : 주변 단어라고 했을 때, \(P(k|i)\)는 동시 등장 행렬로부터 i의 전체 등장 횟수를 세고, \(i\)가 등장했을 때 \(k\)가 등장한 횟수를 카운트하여 계산한 조건부확률이다.
예를 들어, 다음 표를 보자.
ice와 solid가 같이 등장할 확률 0.00019는 steam과 solid가 같이 등장할 확률 0.000022보다 8.9배 크다는 의미이다. 다른 변수들에서도 비슷한 맥락을 확인할 수 있다.
water과 ice, water과 steam은 둘 다 관련성이 높으므로 조건부확률을 나누었을 때 1.36이라는 1에 가까운 값이 나온다. 반대로 ice와 fasion, steam과 fasion은 둘 다 관련성이 낮은 상황에도 확률을 나누면 0.96이라는 1에 가까운 값이 나온다.
손실 함수 설계
단어 벡터 공간에서의 연산을 통한 의미 표현(왕-남자+여자=여왕)이 직접적인 목표.
→ 임베딩 된 중심 단어와 주변 벡터의 내적이 전체 코퍼스에서의 동시 등장 확률이 되도록 하는 것.
$$ w_i\cdot w_k \approx P(k|i)=P_{ik} \)
사실 정확히는,
\( w_i\cdot w_k \approx logP(k|i)=P_{ik} \)
가 되도록 임베딩 벡터를 설계한다.
설계 과정을 생략한, 최종적으로 일반화된 손실 함수는...
$$ Loss=\sum_{m, n=1}^{V}f(X_{mn})(w^T_m \bar{w_n}+b_m+\bar{b_n}-logX_{mn})^2 $$
이다. \(X_{mn}\)은 동시 등장 행렬에서 m이 등장했을 때 n이 등장하는 횟수, f는 동시 등장 빈도에 대한 가중치, b는 편향이다.
5. FastText - 2016
FastText에서는 각 단어를 글자 단위 n-gram으로 취급한다.
예를 들어 potato는 시작과 끝을 의미하는 <과 >를 붙여서 n=2로 하면,
‘<p’, ‘po’, ‘ot’, ‘ta’, at’, ‘to’, ‘o>’
실제 사용할 때는 n의 최소값과 최대값으로 범위를 설정할 수 있다. n의 최소값이 3, 최대값이 6이라면 ‘<po’, ..., ‘<pot’, ..., ‘<pota’, ..., ‘otato>’ 이런 단어들에 대해 Word2Vec을 수행한다. 그러면 potato의 벡터값은 이 n-gram들의 벡터값들의 총 합으로 이루어진다.
모르는 단어(Out Of Vocabulary, OOV)에 대한 대응
예를 들어 ‘nobleman’이라는 단어를 모른다고 해 보자ㅏ. Word2Vec, GloVe에서는 모르는 단어에 대해 대응할 수 없지만, FastText는 이에 대한 벡터를 얻을 수 있다.
단어 집합 내 빈도 수가 적었던 단어(Rare Word)에 대한 대응
Word2Vec에서는 등장 빈도 수가 적은 단어에 대해 임베딩의 정확도가 높지 않다는 단점이 있다. 하지만 FastText에서는 희귀 단어의 n-gram이 다른 단어의 n-gram과 겹치는 경우 높은 임베딩 벡터값을 얻을 수 있다.
오타에 대한 대응
potaato, corelation 등 typo 오타에 대해서 맞는 단어와 n-gram이 많이 겹치므로 비교적 높은 성능을 보여줄 수 있다.
한국어에서의 FastText
음절 단위, 자모 단위에 대한 시도가 있었다. 자모 단위로 가게 되면 오타나 노이즈 측면에서 더 강한 임베딩을 기대해볼 수 있다. 자모 단위 임베딩시 종성이 존재하지 않을 때는 ‘_’ 라는 토큰을 사용할 수 있다. 이때 예를 들어 ‘농부’라는 단어에 n=3 n-gram을 적용한다면,
< ㄴ ㅗ, ㄴㅗㅇ, ㅗㅇㅂ, ㅇㅂㅜ, ㅂㅜ_ , ㅜ_>
이렇게 임베딩할 수 있다.
'NLP lab > 엔엘피' 카테고리의 다른 글
Generative model, Discriminative model (0) | 2022.04.08 |
---|---|
ELMo (0) | 2022.03.12 |
계층적 소프트맥스(Hierarchical Softmax, HS) in word2vec (3) | 2022.03.11 |
Context Free Grammar, CYK(CKY) 알고리즘 (2) | 2022.03.01 |
오토마타 이론과 형식 언어 (2) | 2022.03.01 |