부제 : 헉 나 또 까먹었다 !!
자, 언어모델부터 다시 시작이다.
언어모델이란 언어라는 현상을 모델링하고자 단어 sequence에 확률을 할당하는 모델을 의미한다. 실생활에서 사용되는 언어의 확률 분포에 근사한 모델, 즉 가장 자연스러운 단어 sequence를 찾아내는 모델이 가장 optimal한 언어모델이라고 볼 수 있다.
언어모델은 크게 두 부류로 나눠볼 수 있다.
현재는 인공신경망을 활용한 언어모델이 주류를 이루지만, 언어모델의 전통적인 접근 방법은 통계적 언어 모델이다. 예전처럼 활발히 쓰이고 있지는 않지만, 시사하는 바가 꽤 많은 접근 방식이니 간단히 짚고 넘어가보도록 하겠다.
통계적 언어 모델 (이후 SLM으로 통일) 은 위에서 언급했듯 언어 모델의 전통적인 접근 방법이다. 해당 방법에서는 문장에 대해 확률적으로 접근한다. 다시 말해, 어떠한 문장이 구성될 때 가장 높은 확률을 가진 단어가 순차적으로 선택된다고 보는 것이다.
따라서 SLM에서는 문장에 대한 확률을 각 단어들이 이전 단어가 주어졌을 때 다음 단어로 등장할 확률의 곱으로 계산한다. 예시와 함께 찬찬히 살펴보자.
이 때 단어가 등장할 확률은 어떻게 구하나 ? 하는 의문이 들 수도 있는데, 대체적으로 count 기반의 확률을 활용한다.
아래와 같이 계산된다는 건데,
쉽게 말하자면 전체 코퍼스에서 'You are my'가 100번 등장하고, 그 중에 my 다음에 angel이 등장하는 횟수가 17번이라면 'You are my' 다음에 'angel'이 등장할 확률이 17%가 된다는 거다.
그런데 위에서 언급한 count 기반 접근은 명백한 한계점이 있다.
언어모델의 학습을 위해서는 대량의 코퍼스가 필요하다. 그런데 아무리 다량의 데이터를 모아 코퍼스를 구축한다고 하더라도, 그렇게 얻은 코퍼스가 현실의 언어 세계를 전부 반영할 수 있을까 ? 아마 아닐 것이다. 코퍼스에는 없지만 현실에는 존재하는 언어 표현이 있을 수 있다. 신조어나 은어 등을 생각해보면 이해가 쉬울 것이다.
이처럼 충분한 데이터를 관측하지 못해 언어를 정확히 모델링하지 못하는 문제를 바로 희소문제 (Sparsity Problem) 이라고 한다.
희소문제의 해소를 위해 n-gram 언어모델 등 다양한 alternative들이 고안되었지만, 근본적인 해결책은 되지 못하였다. 언어모델링에 있어 기존의 SLM 방식에서 인공신경망을 활용하는 방식으로 전환된 데에는 이러한 배경이 깔려있다.
위에서 N-gram 언어모델이 희소문제의 근본적인 해결책이 되지 못했다고 언급했지만.. 여전히 NLP 분야에서 쓰이고 있는 중요한 모델이기 때문에 가볍게 다루고 넘어가보도록 하겠다.
SLM의 대표적인 한계점은 위에서 언급한 희소문제이다. 확률을 계산해야하는 문장이 길어질수록 코퍼스에 문장이 존재하지 않을 가능성이 높아지는 것은 너무도 자명하다.
그렇다면 앞 단어 전체를 참고하지 말고, 앞 단어 중 일부만 참고해보는 방식은 어떨까 ?
해당 아이디어를 기반으로 고안된 언어모델이 바로 N-gram 언어모델이다.
N-gram 언어모델은 근본적으로 기존의 SLM 모델과 닮아있다. 해당 방식에서도 count 기반 통계적 접근을 채택하고 있다. 다만 SLM 모델과 달리, n-gram 언어모델에서는 이전에 등장한 모든 단어를 고려하는 것이 아니라, 일부 단어만 고려하는 방식을 택한다. N-gram에서의 n은 몇 개의 '일부 단어'를 보느냐를 의미한다.
수식으로 표현하자면 다음과 같다.
다시 말해, 단어의 확률을 구할 때 기준 단어의 앞 단어를 전부 포함하여 count하지 말고, 앞 단어 중 임의의 개수만 count해서 근사하자 ! 라는 개념인 것이다. 이렇게 되면, 갖고 있는 코퍼스에 해당 단어 sequence가 포함되어있을 가능성이 필연적으로 높아질 수 밖에 없다.
이쯤 오면 오키 다 잘 알겠는데.. 당최 n-gram 이란 게 무엇을 의미하는거지 ? 라는 의문이 들 수 있다.
N-gram이란 n개의 연속적인 단어 나열을 의미한다. 아래 예시를 통해 명확히 이해해보자.
e.g., 'You are my angel'
- unigrams : you, are, my, angel
- bigrams : you are, are my, my angel
- trigrams : you are my, are my angel
- 4-gram : you are my angel
N-gram 언어모델에서는 해당 개념을 다음과 같이 활용한다.
e.g., 'You are my __' , 3-gram
→Youare my __
즉, 다음 나올 단어의 예측에 있어 오직 n-1개의 단어에만 의존하는 것이다.
N-gram 언어모델은 정말 멋지지만 아쉽게도 명백한 한계점이 있다.
문맥적 차원
N-gram 언어모델은 앞의 단어 몇 개만 참고하여 뒤에 나올 단어를 예측하는 방식을 채택하고 있는데, 방식 특성상 의도한 대로 문장을 끝맺음하지 못하는 경우가 발생할 수 밖에 없다. 앞뒤 문맥이 전혀 연결되지 않는 경우가 생길 수도 있고, 이에 따라 전체 문장을 고려한 언어 모델보다 정확도가 현저히 떨어질 수 있다.
희소문제
SLM보다는 낫지만 n-gram 언어 모델도 희소문제에 대한 근본적인 해결책은 되지 못한다. 코퍼스에 특정 데이터가 존재하지 않는 경우 n-gram 모델 또한 희소문제를 겪을 수 밖에 없다.
n값의 선택 = trade-off !
n값이 커질 수록 모델 성능이 좋아진다는 것은 필연적인 일이다. 그런데 n이 커질수록 코퍼스에서 해당 n-gram을 count할 수 있는 확률 또한 감소한다. 희소문제가 악화되는 것이다. 반면 n이 작아질수록 n-gram을 count할 수 있는 확률은 증가한다. 다만 모델의 정확도는 현저히 떨어질 수 밖에 없다. 다시 말해, n의 선택과 모델 성능은 trade-off 관계에 있다는 것이다. 따라서 n-gram 언어모델을 활용할 때에는 적당한 n을 선택하는 것이 중요한데, 연구 결과에 따르면 n의 값이 최대 5를 넘어서는 안된다고 권고하고 있다고 한다~
Perplexity (이후 PPL로 통일)는 언어모델을 평가하기 위한 평가지표이다. 문장확률을 문장 길이로 정규화한 값에 역수를 취한 값이며 수치가 낮을수록 언어모델의 성능이 좋다는 것을 의미한다. ( 문장확률이 높을수록 역수값이 감소하니까, 당연히 수치가 낮을 때 성능이 좋은 것이겠지 ? )
언어모델에 있어 PPL은 선택할 수 있는 가능한 경우의 수라고 해석할 수 있는데, 다시 말해 언어 모델이 특정 시점에서 평균적으로 몇 개의 선택지를 가지고 고민하고 있는가를 나타낸 것이다. ( PPL이 10인 언어모델은 모든 시점에서 평균적으로 10개의 선택지를 놓고 고민한다는 것 ! ) 적은 수의 선택지를 가지고 고민하는 모델이 더 나은 결과를 도출할 가능성이 높을 수 밖에 없으므로.. PPL 수치가 낮을수록 언어모델의 성능이 좋다는 것은 자명한 일 !
그러나 PPL은 테스트 데이터 상에서 높은 정확도를 보인다는 의미이지, 사람이 느끼기에 좋은 언어 모델이라는 것을 의미하는 것은 아니다. 다만 간단하게 언어모델의 성능을 비교할 때는 효용이 있다는 것 !
단어를 수치화하는 방법에는 크게 두 가지가 있다.
직관적으로 알 수 있겠지만 분산표현의 경우에는 국소표현과 달리 그 단어의 의미와 뉘앙스를 표현할 수 있다는 이점이 있다. 이어서 다룰 count 기반 단어 표현 방식들은 국소표현에 해당되며, 분산표현은 추후에 이어서 다뤄보도록 하겠다.
BoW는 단어의 등장 순서를 고려하지 않는 빈도수 기반 단어 표현 방법이다. 다시 말해, 각 단어가 등장한 횟수만을 수치화하는 텍스트 표현 방법이라고 볼 수 있겠다.
BoW는 다음과 같은 과정을 거쳐 형성된다.
BoW는 빈도수만을 고려한 단어 표현 방법이므로, 어떤 단어가 얼마나 등장했는지를 기준으로 문서가 어떤 성격의 문서인지를 판단하는 작업 (분류 / 문서 간 유사도 측정)에 주로 쓰인다.
문서 단어 행렬 (이후 DTM으로 통일) 은 서로 다른 문서들의 BoW를 결합하여 다수의 문서에서 등장하는 각 단어들의 빈도를 행렬로 표현한 것을 의미한다.
DTM의 표기법은 다음과 같다.
e.g.,
문서 1 : You are my angel baby
문서 2 : You came out of the blue
문서 3 : My eyes are not blue
you | are | my | angel | baby | came | out | of | the | blue | not | eyes | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
문서1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
문서2 | 1 | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 0 | 0 |
문서3 | 0 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 1 |
위에서 알 수 있듯, DTM은 문서 간 서로 비교할 수 있도록 수치화가 가능하다는 이점이 있다.
그러나 DTM에는 명확한 한계가 존재한다.
DTM의 두번째 한계점의 대안으로 고안된 방식이다. DTM 내 각 단어에 대한 중요도를 계산할 수 있는 방식이라고 보면 된다.
구체적으로, 단어 빈도-역 문서 빈도 (이후 TF-IDF로 통일) 는 단어의 빈도와 역 문서 빈도(문서의 빈도에 특정 식을 취함)를 사용해 DTM 내의 각 단어들마다 중요한 정도를 가중치로 주는 방식이다.
TF-IDF는 문서 유사도를 구하거나 문서 내 특정 단어의 중요도를 구하는 작업 등에서 주로 사용된다고 한다.
TF-IDF는 우선 DTM을 만들고 → TF-IDF 가중치를 부여하는 방식으로 계산된다.
을 계산하는 방식이라고 보면 된다.
d = 문서 , t = 단어 , n = 문서의 총 개수
라고 할 때,
워드 임베딩 또한 언어를 수치화하는 방식의 일종이다. 다만 두 가지 측면에서 다른 언어 수치화 방식과는 차별성을 가진다.
- 단어를 밀집표현으로 변환해 공간 낭비를 완화
- 단어를 분산표현으로 변환하여 단어 간 의미적 유사성 반영
갑자기 밀집표현은 뭐고 분산표현은 뭐냐 ? 싶을 수 있는데, 하나하나 차근히 짚고 넘어가보자
밀집표현과 분산표현은 다른 맥락에서 발생한 용어이나, 두 용어 모두 희소표현의 대척점에 서있는 개념이다. 하나씩 살펴보자.
위에서 여러번 언급했지만, 희소표현은 벡터 혹은 행렬 값이 대부분 0으로 표현되는 방식을 의미한다. 대표적인 희소벡터로는 원-핫 벡터가 있다. 원-핫 벡터는 대충 이렇게 생겼다.
희소표현은 구현이 간편하다는 장점이 있지만, 두 가지 치명적인 단점이 있다.
단어 개수 = 벡터 차원
이건 다시 말해 벡터차원이 한없이 커질 수 있다는 건데, 가뜩이나 0이 많은 희소벡터에서 벡터차원이 한없이 커지게 된다 ? 공간적 낭비가 아닐 수 없음 !
단어 의미 표현 불가
단어 집합에 있는 단어들에 단순히 인덱스만 부여하는 방식이므로.. 어떠한 의미도 부여할 수가 없음. 물론 빈도수 기준으로 sort해서 인덱스를 부여한다면 조금의 의미는 부여할 수 있겠지만 큰 효용은 없음 !
밀집표현 (Dense Representation) 은 희소표현과 달리 사용자가 설정한 값으로 단어의 벡터 차원을 맞추는 방식이다. 이에 따라 벡터가 조밀해지며, 벡터값도 0, 1에 국한되지 않는 실수값을 가지게 된다.
( 이런 느낌 ! )
희소표현의 첫번째 단점을 해소할 수 있는 표현 방식이라고 보면 된다 !
분산표현 (Distributed Representation) 은 단어의 의미를 다차원 공간에 벡터화하는 방법이다. 분산표현은 '비슷한 문맥에서 등장하는 단어들은 비슷한 의미를 가진다'는 분포가설을 따른다. 다시 말해, 단어를 수치화할 때 문맥 정보를 반영한다는 것이다. 분산표현도 일종의 밀집표현이기에 희소표현에 비해 상대적으로 저차원 벡터가 도출된다.
희소표현의 두가지 단점들을 모두 해소할 수 있는 표현 방식이라고 보면 되는데, 분산표현의 가장 대표적인 사례가 바로 이어 정리할 Word2Vec이다.
드디어 Word2Vec 까지 왔다. 끼얏호 !
Word2Vec의 학습 방식에는 두 가지가 있다.
CBOW 부터 살펴보자. 위에서 언급했듯 CBOW는 주변 단어를 입력으로 중간에 있는 단어를 예측하는 Word2Vec 의 학습 방식이다. 예시를 통해 자세히 살펴보자.
e.g., I just wanna live in this moment forever.
['I', 'just', 'wanna', 'in', 'this', 'moment', 'forever'] 에서 'live' 을 예측하는 방식이 CBOW !
CBOW 뿐 아니라 Word2Vec이라는 개념을 학습하기 위해서 필수적으로 알아야하는 용어들이 있다. 빠르게 정리하고 넘어가보도록 하겠다.
용어로만 보면 이해가 직관적이지 않으니 예시를 통해 어떤 식으로 슬라이딩 윈도우가 진행되는지 살펴보자.
위 예시에서 알 수 있듯, 윈도우 크기가 n일 때, 실제 중심단어를 예측하기 위해 참고하는 주변단어 수는 2n개이다.
CBOW의 architecture은 다음과 같다.
( ' I just wanna live in this moment forever. ' 이라는 예문은 너무 예쁜 문장이지만 너무 길기 때문에 앞으로 모든 예시는 ' I just wanna live here ' 이라는 예문을 기반으로 할 예정 ! )
위 도표를 보면 짐작 가능하겠지만, Word2Vec은 은닉층이 1개인 얕은 신경망 모델이고 (딥러닝 모델 아님), 은닉층에도 activation function이 없다. 실제로 Word2Vec의 은닉층에서는 룩업테이블이라는 연산만을 담당한다.
Architecture에 대해 조금 더 깊이 들어가보자.
위의 그림에서 볼 수 있듯, Word2Vec 모델의 input과 output은 모두 원-핫 벡터이다.모델의 훈련 전에 W와 W'는 랜덤한 값을 가지며, 더 나은 output을 도출하게끔 가중치 행렬 W와 W'가 학습된다.
여기서 주목해야할 점은 W가 look-up table로 작용한다는 점이다. look-up table이 뭐지 ? 싶을 수 있는데 예시와 함께 이해해보자.위의 사례에서 볼 수 있듯 원-핫 벡터와 가중치 W 행렬에 대한 행렬곱의 결과값은 W행렬의 (원핫벡터1의인덱스)번째 행을 그대로 읽어오는 것(lookup)과 동일하다. 그래서 이 경우 W행렬이 lookup table로 작용한다고 하는 것이다 !
기억해야 할 것은 가중치 W 행렬이 단순한 lookup table이 아니라는 점이다. W의 각 행 벡터는 Word2Vec 학습 후 각 단어의 M차원 임베딩 벡터로 간주된다. 쉽게 말해 W 행렬 자체가 임베딩 결과값의 모음집이 되는 것이다. 그래서 W를 제대로 학습시키는 것이 중요하다.
흠 근데 그럼 어떻게 Word2Vec을 학습시키는걸까 ? 도표를 통해 자세히 살펴보자.
우선, 윈도우 범위에 있는 단어들의 원-핫 벡터와 가중치 행렬 W가 곱해진다. CBOW의 경우 주변 단어로 중심 단어를 예측하는 방식으로 학습되기 때문에 윈도우 범주에 있는 단어들과 행렬 W의 행렬곱 결과값의 평균이 도출되고, 이 결과값이 또다른 가중치 행렬 W'과 곱해져 Z라는 벡터가 도출된다. 해당 벡터는 softmax 함수를 거쳐 각 원소의 값이 0 이상 1 이하의 값 & 각 원소의 합이 1인 벡터가 되고 이 값이 모델의 예측값이 되고, 해당 예측값 과 실제 정답인 간의 오차함수는 cross entropy가 사용된다. CBOW에서는 이러한 절차를 거쳐 Word2Vec 모델이 학습되는 것이다.
Skip-gram은 위에서 언급했듯 중간에 있는 단어를 입력으로 주변 단어를 예측하는 Word2Vec 의 학습 방식이다. 이외의 부분은 CBOW와 유사하므로 architecture만 rough하게 다루고 넘어가보도록 하겠다. Skip-gram은 중심단어로 주변단어를 예측하는 방식이므로 CBOW 처럼 투사층에서 벡터의 평균을 구하는 절차가 생략된다. 연구 결과에 따르면 Skip-gram의 성능이 CBOW보다 좋다고 함 〰
Word2Vec의 output layer는 softmax function을 지난 단어집합 크기의 벡터와 실제값인 원-핫 벡터 간의 오차를 구하고 이로부터 가중치 W 에 있는 모든 단어에 대한 임베딩 벡터값을 업데이트한다. 이러한 방법은 단어집합이 커질수록 모델의 학습 부담이 커진다는 문제점을 가진다.
이러한 문제점을 극복하기 위해 나온 개념이 Negative Sampling 이다.
Negative Sampling 은 Word2Vec 학습과정에서 전체 단어집합이 아니라 일부 단어 집합에만 집중할 수 있도록 하는 방법이다. 이건 또 무슨 얘긴가 싶을 수 있는데, 예시를 통해 천천히 살펴보자.
e.g., 현재 집중하고 있는 단어 = '강아지', '고양이' 일 때,
'컴퓨터', '볼펜', '이어폰' 등 주변 단어가 아닌 단어를 단어집합에서 일부 가져와서 새로운 (작은) 단어집합을 만들어 학습시키는 방식 !!
하나의 중심단어에 대해 전체 단어집합보다 훨씬 작은 단어집합을 만들어놓고 마지막 단계를 이진분류 문제로 전환하는 방식이라고 이해하면 된다. 구체적으로 주변단어들은 positive, 랜덤으로 샘플링된 단어들을 negative로 라벨링함으로써 구현될 수 있다.
해당 방법은 이진분류 문제를 푸는 방식이기에 단어집합 크기만큼의 선택지를 두고 다중클래스 분류문제를 푸는 기존의 Word2Vec 방식보다 연산량 측면에서 효율적이다.
Word2Vec이 언뜻 짱짱맨인 것 같지만, 단점 또한 존재한다. 그러한 단점을 지적하며 나온 새로운 워드 임베딩 방법이 바로 지금 소개할 GloVe이다. 다만 지금은 GloVe를 딥하게 다루지 않을 생각이고, 추후에 논문 리뷰를 하면서 자세히 살펴보고자 한다. 우선 지금은 기본적인 개념 수준만 훑고 넘어가겠다.
근본적으로 GloVe는 count 기반(LSA), 예측 기반(Word2Vec) 방식을 모두 사용하는 워드 임베딩 방법론이다. GloVe를 소개한 논문에서는 기존의 count 기반, 예측 기반 방식을 모두 비판하고 나섰다. 그들의 논리는 다음과 같았다.
LSA : DTM / TF-IDF 행렬같이 '각 단어의 빈도수를 count한 행렬'이라는 전체적인 통계정보를 입력받은 후 행렬의 차원을 축소하여 잠재의미를 끌어내는 방법론
→ 단어 의미를 유추하는 작업에서는 성능이 떨어진다 !!
Word2Vec : 실제값과 예측값에 대한 오차를 손실함수를 통해 줄여나가는 예측 기반 방법론
→ 유추 작업은 비교적 잘하지만, 임베딩 벡터가 윈도우 크기 내에서만 주변 단어를 고려하는 방식으로 도출되므로 코퍼스 전체적 통계 정보를 반영하기 어렵다 !!
따라서 연구진들은 count, 예측 기반 방식을 모두 사용하여 임베딩된 단어 벡터 간 유사도 측정을 수월하게 하면서도 말뭉치 전체 통계 정보를 더 잘 반영할 수 있는 워드 임베딩 방법인 GloVe를 제안했다.
GloVe의 목적은 임베딩된 중심단어 벡터와 주변단어 벡터의 내적이 전체 코퍼스에서의 '동시등장확률'이 되도록 만드는 것이다. 다시 말해, 중심단어로 어떤 것이 주어지느냐에 따라 단어 간 내적값이 달라지도록 만드는 것이다.
→ 해당 방법을 따르면, 문서를 임베딩한다고 했을 때 문서 전체의 모든 단어가 중심단어로 설정되므로 최종적으로 문서 전체를 반영하면서도 유사도를 반영한 임베딩이 가능하다.
FastText는 Word2Vec 모델을 확장한 것으로, 대부분 Word2Vec과 유사한 방식을 채택하였다. 다만 Word2Vec이 단어를 쪼개질 수 없는 단위로 여기는데 반해, FastText에서는 단어를 쪼개질 수 있는 단위로 보고, 해당 단어의 subword를 고려한다.
FastText는 기본적으로 각 단어를 글자 단위 n-gram의 구성으로 취급한다. 예시를 통해 더 구체적으로 알아보자.
e.g., 'angel', n=3
<an, ang, nge, gel, el>, < angel >
여기서 <과 >는 단어의 처음과 끝을 알리는 장치이며, 기존 단어에 <, >를 붙인 토큰도 추가된다.
다만 FastText를 실사용할 때는 n의 최솟값과 최댓값의 범위를 설정할 수 있다.
e.g., 'angel', n=3~6
<an, ang, nge, gel, el>, <ang, ange, ngel, gel>, <angel, angel>, < angel >
FastText에서는 단어의 n-gram을 구한 후, subword들에 대해 Word2Vec을 수행한다. subword들의 벡터값을 얻고 난 후, 'angel'이라는 단어의 벡터값은 해당 벡터값들의 총 합으로 구성되는 것이다. 요컨대 다음과 같은 방식이다.
angel = <an + ang + nge+ ... + <angel + angel> + < angel >
FastText는 크게 두 가지 장점이 있다.
OOV에 대한 대응 가능
: FastText는 모든 단어의 각 n-gram에 대해 워드임베딩을 수행하므로 dataset만 충분하다면 subword를 통해 OOV에 대해서도 다른 단어와의 유사도를 계산할 수 있다. (↔ GloVe, Word2Vec)
단어집합 내 빈도수가 적었던 단어(rare word)에 대한 대응
cf. Word2Vec의 경우, rare word에 대해 임베딩 정확도가 떨어지는 단점이 있다. 참고할 수 있는 경우의 수가 적으면 정확히 임베딩할 수 없다는 거다.
반면 FastText의 경우 rare word라도 그 단어의 n-gram이 다른 단어의 n-gram과 겹친다면 Word2Vec과 비교해봤을 때 비교적 정확한 임베딩 벡터값을 얻을 수 있다. 이는 noise가 많은(오타 / 잘못된 맞춤법) corpus에서 강점으로 작용한다.