James • Head of AI
텍스트 임베딩 1편에서는 임베딩에 대한 개념과 이를 딥러닝 모델로 학습한 단어 임베딩인 word2vec에 대해서 알아보았습니다. word2vec은 여러가지 장점이 있긴 하지만 어떤 문맥에 대해서 사용되었는지, 그리고 나오지 않은 단어에 대해서는 임베딩을 구하기도 어렵다는 것이 한계였습니다.
따라서 word2vec 같은 단순한 단어 임베딩 보다는 단어 그 자체가 아닌 단어가 사용된 문맥까지 반영해서 임베딩을 만드는 문맥 기반 단어 임베딩 (Contextualized Word Embedding)이 나오게 되었습니다.
딥러닝을 이용해서 텍스트 임베딩 모델을 학습하기 위해서 언어모델이라는 것을 학습하게 됩니다. 텍스트 임베딩은 언어모델을 학습하는 과정에서 얻어지는 부산물이라고 볼 수 있으며 때로는 언어모델 자체가 사용되는 경우도 매우 많습니다.
언어모델이라는 것은 말그대로 사람이 사용하는 언어를 수식을 이용하여 구조를 모델로 표현하는 것을 말합니다. 좀 더 자세히 설명하자면 어떤 문장이 주어졌을 때 이 문장이 나올 확률을 계산하는 식을 만드는 것이 언어 모델링이 하는 일이라고 볼 수 있습니다.
딥러닝에서는 언어모델을 크게 두 가지 방식으로 학습합니다.
인과적(causal)이라는 것은 이전의 나온 단어들을 바탕으로 다음 단어의 확률을 추론하는 방식을 의미합니다. 어떤 단어가 출현할 확률을 이전 단어들에 의해 결정 된다는 전제가 깔려있습니다.
따라서 어떤 텍스트가 주어졌을 때 언어모델이 텍스트의 확률을 추론하는 방식은 각 단어들이 나올 확률의 곱으로 표현하고 각 단어들이 나올 확률은 그 단어 이전에 나왔던 단어들을 기반으로 추론하게 학습합니다. (실제로 최근 모델들은 단어를 추론 단위로 사용하지 않고 그보다 더 작은 BPE나 subword를 token 단위로 사용합니다. 하지만 이해를 돕기 위해 단어 단위로 설명합니다.)
수식으로 표현하자면 텍스트의 각 단어를 x라고 할 때 언어모델은 다음을 만족하는 확률 모델 P를 의미합니다.
인과적 언어모델은 초기에 LSTM 구조를 활용해서 많이 학습되어 사용되었습니다. LSTM 모델은 RNN구조를 가지는 딥러닝 모델의 일종입니다. (LSTM에 대한 자세한 설명은 생략합니다)
하지만 LSTM 이후 Transformer라는 혁신적인 딥러닝 모델이 발표되면서 Transformer를 활용한 causal LM이 많이 등장하게 됩니다. GPT 모델이 대표적인 transformer로 학습한 causal LM 모델이며 지금도 많이 쓰이고 있다는 것은 다들 잘 아실 거라 생각합니다.
transformer에 대한 자세한 설명도 생략하겠지만 transformer가 causal LM을 학습하기 위해서는 transformer의 decoder 구조만을 활용하게 됩니다.
transformer의 decoder 자체가 주어진 입력에 대해서 그 다음에 나올 출력에 대한 확률 분포를 학습하는 모델이므로 causal LM을 학습하기에 적절한 구조입니다.
그림에서 볼 수 있듯이 transformer는 small, talk, big 이라는 단어를 입력으로 받고 그 다음에 올 단어들의 확률을 계산해주게 되는데 이 확률이 results라는 단어에 대해서 더 큰 값을 갖도록 학습하게 합니다.
인과적 언어 모델을 학습하고 나면 각 단어 위치 별로 벡터가 생성되고 이 벡터를 그 단어 다음에 올 단어에 대한 확률을 계산하는데 쓰게 되는데 이때 이 확률을 임베딩 모델로 활용할 수 있게 됩니다.
그림에서 보이듯이 단어를 예측하기 직전의 벡터가 임베딩 벡터가 되죠. 인과적 언어 모델은 좋은 언어 모델이긴 하지만 임베딩 벡터 자체가 그 이전 단어들의 정보로만 학습이 되므로 참고되는 정보의 범위에 한계가 있습니다.
그 이전 단어들 뿐만 아니라 이후 단어들까지 같이 참고해서 임베딩 벡터를 만들게 된다면 좀 더 정보가 충분히 반영된 벡터를 얻을 수도 있다는 기대를 자연스럽게 할 수 있습니다.
인과적 언어모델과 달리 이 양방향 언어모델은 어떤 단어의 출현 확률을 단순히 그 이전 단어로 한정하지 않고 그 이후의 단어까지도 활용하여 확률을 예측하게 되고 이를 통해서 임베딩 벡터까지도 구할 수 있습니다.
하지만 기본적으로 그 위치의 단어를 예측하는 언어모델을 만들기 위해서는 해당 단어를 보면 안되기 때문에 단순한 방식으로는 양방향 언어모델을 학습하는 것이 쉬운 일은 아닙니다.
이런 어려움을 극복하고 만든 대표적인 양방향 언어모델로 BERT라는 모델이 있습니다. 이 모델 또한 아주 유명한 모델이고 역시나 transformer를 활용한 모델입니다.
앞서 나온 GPT와는 다르게 양방향 학습을 위해서 BERT에는 transformer encoder가 활용되는데요. 양방향 언어모델 학습 기법은 마스크 언어모델(Masked Langauge Model)이라는 방법으로 무작위로 선택된 위치에 해당하는 단어에 대해서 이 단어에 마스크를 씌워서 그 위치의 단어가 무엇일지 맞추게끔 모델을 학습시켜서 그 위치에 나올 수 있는 단어에 대한 확률 분포를 학습하는 것입니다. (실제로는 선택된 위치에 대해서 전부 마스크를 씌우진 않고 일부는 그대로 보여주고 예측하게도 합니다)
이 모델 또한 임베딩 벡터는 그 단어를 예측하기 직전의 벡터를 활용하게 됩니다. 한마디로 Masked LM 학습은 임베딩 벡터를 만들기 위한 훈련 방법에 불과한 것으로 볼 수 있습니다. (물론 Masked LM 자체가 필요해서 언어모델을 학습할 수 있고 이를 실제로 사용할 수도 있습니다)
Masked LM만이 유일한 bidirectional LM을 만드는 학습방법은 아닙니다. 실제로 여러가지 방법이 있을 수 있고 ELECTRA라는 학습 모델도 bidirectional LM을 만드는데 많이 활용되며 성능도 더 좋은 경우가 많이 있습니다. 아까 causal LM에 사용되었던 LSTM을 활용하여 ELMo라는 bidirectional LM이 사실 그보다 더 이전에 발표되기도 했구요.
어떤 방식이든 bidirectional LM은 단어의 이전 정보만 활용하는 것이 아니라 그 이후의 정보도 활용한다는 점에서 장점이 있습니다. 이 방식이 임베딩 벡터를 학습하는데는 특히나 더 좋은 방식으로 여겨져서 현재는 임베딩 벡터를 위한 학습에는 BERT 기반의 bidirectional LM이 많이 쓰이고 있는 것으로 보입니다.
지금까지는 각 단어들의 임베딩을 이전 단어들 혹은 이전과 이후 단어들을 참고하여 문맥을 반영한 단어 임베딩을 구하는 모델들에 대해서 알아봤습니다. 그런데 문장 혹은 그 이상의 긴 텍스트에 대한 임베딩을 한번에 구하려면 어떻게 할까요? 그런게 가능 하다면 우리는 문장 자체를 벡터로 만들어서 문장간의 유사도를 비교할 수 있고 이를 통해서 문장을 검색하거나 분석, 예측을 하는데 활용할 수 있을 것입니다.
문장 임베딩을 위해서 보통 앞에 나왔던 bidirectional LM을 사용하며 BERT와 마찬가지로 transformer encoder로 학습을 합니다. 보통 transformer는 각 단어 별로 임베딩을 만들어주지만 우리가 원하는 것은 문장 전체의 임베딩이므로 보통 첫 위치의 임베딩(CLS 토큰)을 활용하거나 전체 단어 임베딩의 평균을 문장의 임베딩으로 활용하게 됩니다. 여기서는 평균을 활용하는 것을 기본으로 생각해보겠습니다.
그렇다면 BERT로 학습된 모델에서 나온 단어 임베딩들의 평균이 그 문장을 표현하는 텍스트 임베딩이라고 간주할 수 있을까요? 아주 관련이 없지는 않겠지만 그렇게 될 만한 필연적인 이유는 없을 것입니다. 그러므로 우리는 이 평균 임베딩이 실제로 문장을 표현할 수 있도록 추가적인 학습을 해주는 것이 필요할 것입니다.
문장 임베딩을 위해서는 어떤 학습이 필요할까요? 다시 블로그 처음에 언급했던 좋은 임베딩이 무엇인지에 대한 정의를 다시 기억해봅시다. 좋은 임베딩이란 비슷한 것들은 거리가 가깝게, 관련 없는 것들은 거리가 멀게 표현해주는 임베딩이라고 했습니다.
문장 임베딩도 마찬가지 입니다. 관련 있는 문장은 가깝게, 관련 없는 문장은 멀게 하는 학습이 필요합니다. 이런 목적에 맞는 학습 방법이 contrastive learning입니다. 이 학습 방법은 보통 데이터에 가까워져야 할 샘플과 멀어져야 할 샘플을 준비해서 각각의 거리를 가깝게 또 멀게 하는 손실 함수를 구성하여 학습합니다.
이때 각 문장들의 거리는 transformer가 제공하는 임베딩의 평균 벡터에 대한 코사인 유사도를 활용합니다. (코사인 유사도가 낮을 수록 거리가 멀게)
그림과 같은 상황에서는 A-B가 최소가 되도록 손실함수를 구성할 수 있을 것입니다. 이런 방식으로 transformer를 다시 학습한다면 처음에 원했던대로 관련된 문장은 가깝게 (코사인 유사도가 높게) 관련이 없는 문장은 멀게 (코사인 유사도가 낮게) 하는 문장 임베딩을 얻을 수 있을 것입니다.
이렇게 얻어진 문장 임베딩은 매우 다양한 용도로 쓰일 수 있습니다. 대표적인 활용 예시로 의미기반 검색(semantic search)을 생각해볼 수 있을 것 같습니다. 전통적인 키워드 기반 검색은 텍스트가 주어졌을때 얼마나 많은 글자 혹은 단어가 일치하는지를 보고 유사도를 측정하여 검색을 하는 방식이라면 의미기반 검색 방식은 임베딩 벡터를 활용하여 얼마나 벡터 간 유사도가 높은지를 측정하여 관련된 텍스트를 검색할 수 있게 됩니다.
이렇게 한다면 글자는 많이 겹치지 않더라도, 혹은 오타로 인해서 글자가 다른 경우라도 의미가 비슷하면 벡터 유사도가 높게 나오면서 검색 품질을 좀 더 높이는데 활용 될 것입니다.
이 뿐만 아니라 최근에 LLM(Large Language Model)을 이용하여 채팅을 하는 경우에 관련된 지식을 검색하여 더 풍부한 채팅을 할 수 있게 하는 RAG (Retrieval Augmented Generation) 모델에도 임베딩 벡터와 이를 통한 유사도 기반 검색 방식이 활용되는 것을 볼 수 있습니다.
문장 임베딩은 앞으로도 더 많은 분야에서 사용될 것으로 예상되고 저희 채널 팀도 문장 임베딩을 통해 다양한 AI 서비스를 채널톡을 통해 제공하기 위해 노력하고 있습니다. 다음 블로그에서는 문장 임베딩을 어떻게 활용하여 서비스를 개발하고 있는지에 대해서 좀 더 구체적으로 설명드리도록 하겠습니다. 많은 기대해주세요!
참고 문헌
Merity, Stephen, Nitish Shirish Keskar, and Richard Socher. "Regularizing and optimizing LSTM language models." arXiv preprint arXiv:1708.02182 (2017).
Vaswani, Ashish, et al. "Attention is all you need." Advances in neural information processing systems 30 (2017).
Radford, Alec, et al. "Improving language understanding by generative pre-training." (2018).
Devlin, Jacob, et al. "Bert: Pre-training of deep bidirectional transformers for language understanding." arXiv preprint arXiv:1810.04805 (2018).
Clark, Kevin, et al. "Electra: Pre-training text encoders as discriminators rather than generators." arXiv preprint arXiv:2003.10555 (2020).
Matthew E. Peters et al. "Deep Contextualized Word Representations." (2018)
Reimers, Nils, and Iryna Gurevych. "Sentence-bert: Sentence embeddings using siamese bert-networks." arXiv preprint arXiv:1908.10084 (2019).
Lewis, Patrick, et al. "Retrieval-augmented generation for knowledge-intensive nlp tasks." Advances in Neural Information Processing Systems 33 (2020): 9459-9474.
We Make a Future Classic Product
채널팀과 함께 성장하고 싶은 분을 기다립니다