[딥러닝 NLP] 언어 표현, text embedding, representation 기존 방법 : word representation, word embedding, sentence(~document) embedding, sentence(~document) representation 에 대한 이해
자연어 처리는 사람들이 사용하는 언어를 컴퓨터로 처리한다는 것입니다. 컴퓨터로 처리하기 위해서는 입력인 언어를 숫자로 바꾸어야 합니다. 사람들이 쓰는 언어를 컴퓨터에서 처리할 수 있는 숫자로 바꾸는 것, 더 나아가 언어를 숫자로 잘 표현해 실제 언어의 세계를 한 숫자 공간에 잘 나타내는 것을 text embedding 혹은 text representation 이라고 이해하고 있습니다.
word representation
one-hot encoding
우선 언어의 기본이 되는 word 표현(word embedding)에 대해서부터 설명하고자 합니다. ( 여기서는 단어보다 더 작은 의미를 갖는 단위가 될 수 있습니다. 설명하기 쉽게 word로 표현합니다. )
단어를 가장 간단하게 숫자로 바꾸는 방법은 모든 단어에 대해 번호를 매기고 단어 갯수 만큼의 vector를 만든다음 단어가 들어오면 vector에서 해당 단어 번호의 index에 1을 넣는 one-hot encoding 방식입니다. 이런 방식은 단어를 표현하고 있는 vector의 대부분의 값이 0이기 때문에 sparse representation이라고도 합니다.
word2vec
이후 제한된 크기의 vector에 단어를 표현할 수 있는 값을 채워넣는 dense representation에 대한 방법들이 나옵니다.
가장 대표적인 것은 word2vec 입니다.
"단어의 의미(쓰임)은 주변 단어들로 파악할 수 있다." 라는 가정을 구현한 방법입니다. 학습법은 skip-gram( 주변 단어 예측) 과 CBOW(주변 단어를 보고 중간 단어 예측) 두 가지가 있습니다.
하지만 어떤 문장에서든 같은 단어면 같은 표현을 출력하기 때문에 문장 안에서의 단어의 쓰임 즉 문맥을 제대로 파악하지 못하며, 이 때문에 동의이의어도 구별을 못합니다. 또한 전체 corpus에서의 통계정보를 담고있지 못하고 있다는 단점도 있습니다.
* 잘 representation 되었다, 잘 embedding 되었다는 것은 어떻게 알 수 있을까 ?
이게 정말 잘 표현하고 있는지를 확인할 수 있는 방법인지는 깊이 있게 확인해보진 못했으나, 보통은 한 embedding space에 잘 표현되었으면, 표현된 vector 들 간에 +, - 연산을 사용해서 결과로 나온 vector를 다시 word로 바꿨을 때, 실제 word 사이의 관계가 잘 더해지거나 빼진다면 잘 표현되고 있다고 보고 있습니다.
비슷하게 같은 embedding space에 잘 표현됐다는 것은 embedding space에 존재하는 word 들 간의 관계가 거리로 잘 표현된다는 것입니다. 관계가 있는 word 들은 가깝게 뭉쳐있고, 관계가 없는 word와는 거리가 멀게 표현되어 있다면 word embedding을 잘 하고 있는 것입니다.
이런 점에서 word2vec은 word를 잘 표현하고 있다고 합니다.
가장 유명한 예시는 '한국' - '서울' + '도쿄' = '일본' 이 나오는 것입니다.
glove
Global Vectors for Word Representation(GloVE)는 통계정보를 담지 못하는 word2vec과 단어들 사이의 관계를 파악하지 못하는 카운트 기반 방식(LSA, Latent Semantic Analysis)을 합쳐 두 방식의 단점을 보완했습니다. 그렇지만 glove가 word2vec보다 항상 뛰어나다고는 할 수 없다고 합니다. task에 맞게 적절한 embedding 방식을 사용해야합니다.
glove에 대해서는 잘 설명한 글들이 많았습니다. 핵심은 중심 단어와 주변 단어 벡터의 내적이 동시 등장 확률이 되도록 loss 함수를 만든 것 입니다.
elmo
word2vec, LSA, glove 까지 word embedding 을 위한 다양한 방법들이 나왔습니다. 하지만 이 방법들은 여전히 문맥을 파악하고 있지는 못합니다. 그나마 word2vec에서 주변 단어들을 통해 embedding 하지만 결국 사용할 때는 주변 단어들을 보고 embedding 하는 것이 아니라 그 단어에 정해진 vector를 가져다 쓰는 것이기 때문에 문맥을 파악하지 못하고 있습니다. 문맥을 파악하지 못하는 것의 단점의 대표적인 예로는 동음이의어는 완전히 다른 뜻을 가지는데, 기존의 방법들은 이를 구분하지 못하고 모두 같은 vector를 사용하고 있습니다.
이를 해결하기 위해 나온 것이 elmo(Embeddings from Language Model) 입니다. 사전 훈련된 언어모델을 사용해서 문맥을 파악하는 word embedding 방법을 보였습니다.
입력으로 한 단어를 넣기보다는 문장을 입력으로 넣어주고 각 단어의 embedding을 출력합니다. 문맥을 파악하여 embedding을 만들어내기 때문에 같은 단어라도 입력 문장이 달라진다면 다른 vector가 나오게 됩니다.
BERT
BERT 에 대해서는 https://u-b-h.tistory.com/4 글에서 설명하였습니다. BERT가 word embedding model 인가에 대해서는 저도 명확히 생각이 정리되지 않았는데, 확실한 것은 BERT는 해당 문장에서 각 word의 의미를 잘 추출해낸다는 것입니다. BERT가 입력 문장에서의 각 word들의 의미를 잘 추출하기 때문에 NLP 다양한 task에서 SOTA를 찍을 수 있었습니다. 하지만 word embedding 만이 필요한 상황에서 BERT를 사용했을 때 word2vec, glove 같은 방법보다 좋은가 ? 에 대해서는 확신할 수 없습니다.
지금까지 단어의 의미를 표현하는 방법들에 대해 알아보았습니다. 문맥을 파악하여 단어의 의미를 표현하는 방법부터는 단어의 의미에 초점이 맞춰지기 보다는 문맥 파악에 초점이 맞춰진 것 같습니다. 물론 단어 하나하나의 의미를 잘 표현해야하는 task도 있겠지만 대부분의 자연어 문제들은 문장, 문서 단위를 이해하고 풀어나가야 하는 문제들이 많기 때문에 단어 의미표현을 활용한다던지 문맥 전체에 대한 표현을 사용해야 합니다.
sentence, paragraph, document, ... representation
두 개 이상의 단어로 구성되어 의미를 가지는 문장, 문장, 문서의 표현에 대해 설명하고자 합니다.
단어와 마찬가지로 sparse representation과 dense representation이 있습니다. sparse representation은 단어 빈도 수를 직접적으로 사용하여 표현하는 방식이고, dense representation은 문장을 어떻게 제한된 크기의 vector에 잘 표현할 것인지 다양한 방법이 제안되고 있습니다.
sparse representation, count 기반 방식
TF-IDF
모든 문서들에서 등장한 빈도와 target 문서에서 등장한 빈도로 query와 문서들 간의 관련도 점수를 매깁니다.
TF는 target passage에 등장한 단어 조합의 횟수이고, IDF는 각 단어 조합이 다른 문서에 얼마나 자주 등장했는지에 대한 역수입니다.
TF-IDF는 두 값을 곱해서 사용하는데, 그 의미는 target passage에 많이 등장했고 전체 BoW에서는 자주 등장하지 않은 단어가 target passage를 대표한다고 보는 것 입니다. 그래서 'a', 'the'와 같이 모든 문장에 등장하는 단어는 IDF가 0에 가까워서 TF-IDF가 낮게나오고, target passage에만 많이 등장하는 단어들이 TF-IDF가 높게나오게 됩니다.
간단하며 빠르고 생각보다 잘 찾아내서 여전히 쓰입니다. 아주 긴 문서에 대한 representation 방법으로 여전히 많이 쓰입니다. 전체 corpus 의 통계정보를 활용한다는 장점이 있습니다.
dense representation
word embedding 평균
위에 word embedding에 대해 설명했었습니다. 모든 글은 word로 구성되어 있기 때문에 word embedding이 잘되고 이것을 잘 합친다면 문장, 글도 embedding 할 수 있을 것으로 생각됩니다. 그래서 가장 쉽게 생각할 수 있는 방법으로 글에 포함된 모든 word를 각각 embedding 하고 이를 평균내는 방법으로 전체 문장을 embedding 할 수도 있습니다.
간단한 예시를 들기 위해 평균을 사용하였지만 평균은 너무 간단한 방법입니다. 문장을 제대로 표현할 수 없습니다.
문장, 문서는 결국 word 의 집합이기 때문에 word 표현을 잘 합친다, word 표현을 가져다가 쓴다는 것은 좋은 접근법이라고 생각합니다.
단순히 평균내지 않고 이를 RNN 계열 모델에 넣어 전체 표현을 뽑는다던지, 각 word 표현 사이의 관계를 보기 위해 attention을 적용하는 방법 등으로 word embedding 을 사용해서 좋은 문장, 문서 embedding을 만들 수 있다고 생각합니다.
doc2vec
word2vec의 아이디어를 기반으로 document도 표현하는 방법입니다. 방법은 간단합니다. word2vec할 때 주변 단어들을 입력 혹은 출력으로 삼았는데요, 이 때 매번 문장의 번호를 같이 넣어주는 것 입니다. 이렇게 되면 문장의 번호가 그 문장에 포함된 단어들을 학습할 때 들어가기 때문에 문장의 번호 vector를 보게되면 그 문장에 들어가 있는 단어의 vector들과 가까워져 있어 문장이 표현되게 됩니다. word2vec이 유사한 단어들 간에 가까운 거리를 갖는 vector로 잘 표현하는 방법이기 때문에 doc2vec도 유사한 문장간 거리를 가깝게 잘 표현하는 방법이 됩니다. 하지만 문장은 무한하게 많습니다. 존재하는 모든 문장에 번호를 매기고 이 방법으로 학습을 하기는 불가능에 가까워보입니다. 특정 task의 문장 dataset이 제한되어 있을 때는 사용할 수 있는 방법이지만 열려있는 자연어 처리 문제를 해결할 때 사용하기 어렵지 않을까 생각이 됐습니다.
elmo, BERT
word embedding에서도 설명한 문맥을 표현하는 모델입니다. 두 모델 모두 word들의 vector 가 출력이지만 그 vector들은 문맥을 파악하여 그 문맥 안에서의 단어 하나하나를 표현하고 있는 것이라 word embedding을 잘 했다기보다는 문맥을 잘 표현하고 있다고 볼 수 있습니다.
sentence embedding에서 BERT의 한계
보통 [CLS]는 문장 단위 classification 용 입력 vector로 사용하기 때문에 [CLS] token은 문장 embedding인가보다 라고 생각할 수 있지만, BERT는 문장 embedding을 위해 학습된 모델이 아닙니다. 따라서 [CLS]는 classification용으로 쓰라고 만들어놓은 vector는 맞지만 문장 embedding으로 볼 수 없습니다. [CLS] 보다는 각 word 출력들의 평균으로 sentence를 표현하는 것이 더 성능이 좋습니다.
하지만 두 방법 모두 sentence 를 표현하기에는 부족합니다. BERT는 문맥을 어느 정도 파악하고 있고, 이 모델을 task에 맞게 fine tuning 할 때 성능이 좋은 것이지 이 자체로 embedding model로 쓰기에는 부족함이 있습니다.
sentence BERT (Sentence-BERT: Sentence Embeddings using Siamese BERT-Networks., EMNLP'20 )논문에서도 이러한 점을 지적하고 있습니다. BERT의 CLS나 각 출력의 평균을 사용한 방법이 GloVe보다 STS 성능이 낮게나옵니다. ( * STS는 Semantic Textual Similarity 으로 embedding을 잘 한다는 것은 대상 간 유사도를 잘 나타낸다는 것으로 평가할 수 있으므로, STS로 평가하게 됩니다 )
Sentence BERT
위에서 본 것 처럼 BERT 출력인 [CLS] 나 token들의 embedding vector 평균 값으로 얻은 sentence embedding vector는 STS benchmark에서 성능이 좋지 않습니다. 즉 좋은 sentence representation이 아닙니다.
BERT는 MLM, 다음 문장 예측으로 학습하기 때문에 sentence representation 을 위한 학습법이 아닙니다. word embedding 과 비슷하게 setence embedding 도 embedding space에 잘 표현된다면 sentence embedding 간 차이가 잘 나타나야 합니다.
sentence BERT는 문장 간 차이를 잘 학습해보기 위해서 샴 네트워크 + 문장 차이 데이터셋으로 학습합니다.
sentence BERT는 embedding 성능은 뛰어나지만 fine-tuning에 한계가 있어서 BERT류 모델들보다 범용적으로 target task 성능이 좋지 않고 그대로 가져다가 embedding 을 뽑는것 아니면 쓰기 어렵다는 문제가 있습니다.
sentence BERT와 이후 나온 SET-FIT에 대해서는 여기서는 간략히 다루고 별도로 글을 작성하려고 합니다.