Embedding 모델과 Sentence-Transformer Training

Embedding 전문 모델들 ...

 

임베딩은 중요한 영역이다.

LLM이든 sLLM이든, 결국 컴퓨터가 '자연어'를 처리하기 위해서는 일종의 변환 과정을 거쳐야 한다.

 

잠재 공간에 이러한 Text 혹은 Sentence를 매핑하는 과정을 우리는 임베딩이라 부른다.

이런 과정을 통해, 컴퓨터는 문장을 숫자로 변환시키고, 이를 연산에 활용할 수 있게 된다.

또한 적절한 잠재공간을 통해, 그 문장이 어떤 문장과 '가까운 공간'에 위치하게 되는지도 알 수 있다.

 

여러모로 유용한 방법이다보니 활용처가 많다.

특히 LLM의 성능이 비약적으로 발전하며, RAG를 구축하는 비율이 높아지면 그 관심이 커지고 있다.

 

대표적인 영역은 다음과 같다.

 

1. Sentence Similarity

2. Sentence Classification

3. Sentence Reranking

4. Sentence Retrieval

 

나름 구분을 해 놓긴 하였지만 결론적으로 보면 똑같다.

결국 임베딩 된 벡터가 적절한지를 판단하는 것으로 끝이다.

(물론 Cross Encoding 모델 처럼 조금 느낌이 다른 것도 있지만 .. 일단 넘어가자)

 

문장의 유사도는 결국 Embedding Vector의 거리로 계산하며

Embedding Vector를 통해 Class를 결정하며

Embedding Vector를 통해 유사한 문장을 Ranking시키며, Retrieval 한다.

 

오늘 정리할 것은 이러한 임베딩 모델을 어떤 방식으로 만드냐는 것이다.


1. Pre-Training

시작은 건너 뛰기가 가능하다.

잘 학습된 Pre-Trained Model은 Hugging Face에 널리고 널렸다.

 

적절하게 한국어를 처리할 수 있는지 ... 정도만 고려하면 되겠다.

만약 직접 만든다면, MLM과 같은 Task를 통해 수많은 문장을 학습시키면 되겠다.

 

좋은 문장을 가져오는 것이 굉장히 중요한 작업이다.

 

수많은 사람들이 시도를 거듭하며 얻어진 결론은 ...

 

1. 도서와 같은 Text의 품질이 매우 좋음.

2. 신문 기사 등의 Text의 품질이 좋음.

3. 정제된 Wiki 등도 나쁘지 않음.

4. Namuwiki같은 것이나 ... 댓글 데이터는 모델이 좀 어려워 함 (본인의 경우 기울기 폭발이 계속 발생함)

5. 그 밖의 비 정제된 무작위 크롤링 데이터 (심심하면 터짐)

 

문제는 도서 ... 는 기본적으로 저작권이 있는 자료이며

신문 기사 등도 원칙적으로는 저작권이 있는 자료다.

 

무엇보다 데이터에 대한 사용 권한의 문제를 차치하고서라도, "한국어" 정제 텍스트를 구한다는 것 자체가 힘들다.

(영어는 좋은 자료가 참 많다.)

 

어찌 됐건 최대한 구한 뒤 MLM Task로 학습을 진행하면 준비 끝이다.

 

*(항상 명심하자. Trash In Trash Out이다 ...)


2. Down-Stream Task: Data Pre-Processing

이제부터 지옥시작이다.

지옥은 아닌데, 막막함 시작이다.

 

우리가 아까 고민한 Embedding 모델의 핵심 4가지 Task는 단순하게 MLM만 학습시킨다고 잘하지 않는다.

(이상하리만큼 Classification 점수는 높다 ...) MLM Task로 학습된 KoModernBERT-base 모델의 MTEB Benchmark 점수

예시를 보자.

ModernBERT를 한국어 데이터로 Tuning시킨 모델은 현재 13순위에 Rank되어있다.
(모델 크기가 큰 것과 비교하면 당연히 더 큰 차이가 난다 ...)

 

이 모델을 향상시키기 위해서는 모델들이 다양한 작업을 처리하는 방식을 배워야(Trained) 한다.

대표적인 작업들이 몇 가지 있는데 ...

 

1. 문장의 함의, 모순, 중립 등을 구분하는 작업 (Natural Language Inference; NLI)

2. 문장의 유사도를 추론하는 작업 (Semantic Textual Similarity; STS)

3. 주어진 쿼리와 유사한 문장(Positive)을 찾고, 비 유사 문장(Negative)을 구분하는 작업 

 

이런 것들을 생각해 볼 수 있다.

어려운 이유는 이러한 DownStream Fine-Tune이 실제 Embedding 작업 성능을 상당한 수준으로

향상시킴에도 불구하고, 한국어 데이터가 정~~말 조금 밖에 존재하지 않기 때문이다.

위 작업들에 필수적인 Triplet 데이터는 HuggingFace에서 한국어로 검색시 단 3건 존재한다...

 

최근 DeepSeek의 R1 학습방법은 강화학습을 적용하여 그 성능을 끌어올리고 있음을 보이고 있다.

즉, 어떠한 행동(Action)에 대한 보상(Reward)이 적절하게 이뤄질 때 그 성능이 제대로 나온다는 것이다.

 

물론 이런 얘기를 하려는 것이 아니고, 최근의 트렌드를 이야기 하고자 하는 것이다.

 

Direct Preference Optimization: Your Language Model is Secretly a Reward Model

이것은 DPO라는 방법론을 주장한 논문이다.

제목에서도 알 수 있듯이, 어떠한 Reward Modeling을 통해 성능을 향상시킨다는 것이다.

 

DPO는 쉽게 HuggingFace의 Trainer에도 구현되어 있는데 ...

이 때 요구하는 데이터가 바로 Triplet 형태의 데이터이다.

 

즉, 선호 정답과 비선호 정답으로 구성된 Triplet 형태의 데이터를 통해 성능이 향상된다는 것이다!

 

몇 가지 더 살펴보자.

Embedding 관련 연구들을 살펴보다보면 한 번씩을 봤을법한 그 녀석들이다.

이 녀석들의 공통점을 찾아보면, 비슷한 Loss Function의 구조를 띄고 있음을 알 수 있다.

뭔가 비슷비슷한 느낌이 난다 ...

 

이 구조들은 전부 조금씩 상이하지만, 목표는 결국 똑같다.

선호되는 정답과의 거리는 가깝게 하며, 나머지 비선호 정답에 대한 거리는 멀어지도록 학습시키는 것이다.

 

실제로 이러한 방식이, 정답 데이터만 가지고 학습을 진행하는 것 보다 훨씬 더 좋은 성능을 보이고 있다.


3. Loss Function

다시 돌아와서 ... 본 글에서 쓰고 싶었던 것은 바로 Sentence-Transformer의 Loss Function이다.

결국 [데이터의 어떤 패턴] 을 제대로 알려주기 위해서는, 이것을 위한 [손실 함수] 를 잘 만들어야 한다.

 

앞선 논문들에서도 계속 확인하였듯, 적절한 Loss Function이 핵심적인 역할을 담당한다는 것이다.

그래서 적절한 데이터와 Loss Function을 구성하는 것이 매우 중요한데 ...

 

Sentence Transformer는 이러한 모든 Loss를 적절하게 구현해 놓았다.

 

등등등 ...

 

이런 로스들의 특징은 결국 Positive 데이터 하나로만 학습을 진행하도록 하는 것이 아니라

어떤 방식으로든 Negative 항을 만들어 이러한 데이터와는 멀어지도록 학습한다는 것이다.

 

세부적인 수식은 여기서는 다루지 않고, 우리는 컨셉을 집중해서 살펴보자.

가장 간단한 Triplet Loss의 수식이다.

TripletLoss
loss = max(||anchor - positive|| - ||anchor - negative|| + margin, 0)

 

일종의 거리의 문제로, 간단하게 Positive와의 거리는 가깝게, Negative와의 거리는 멀게 만든다.

가장 간단하게 생각할 수 있는 방법이다.

 

MultipleNegativesRankingLoss

 

여기서는 로그-우도를 작게 만드는 문제로 변한다.

정답 I를 제외한 나머지는 모두 Random하게 추출된 Negative 항이다.

이들을 작아지도록 만드는 것이 목표이다.

 

MultipleNegativesSymmetricRankingLoss

Given a list of (anchor, positive) pairs, this loss sums the following two losses:

  1. Forward loss: Given an anchor, find the sample with the highest similarity out of all positives in the batch. This is equivalent to MultipleNegativesRankingLoss.
  2. Backward loss: Given a positive, find the sample with the highest similarity out of all anchors in the batch.

 

앞선 Loss의 변형이다.

지금까지 본 것은 입력된 [문장] 에 대해 [Positive]와 [Negative]를 이용한 것이다.

 

즉, 입력 문장에 대해 적절한 [Positive]를 찾는 것을 목표로 했던 것이다.

그러면 [Positive]에 적절한 입력 문장은 무엇인가? 이것을 강화하는 Loss Function인 것이다.

 

이 Loss Function에서는 추가적으로

[Positive]에 대해 적절한 [문장] 하나와, [나머지 문장]을 동일한 방식으로 사용한다.

 

이렇게 함으로써 [문장] - [Positive]의 관계를 더욱 강화하는 것이다.

 

GISTEmbedLoss

 

그런데 과연 나머지 문장을 Negative로 생각하는 것이 옳은가?

랜덤하게 뽑아지는 문제는 분명하게 무조건 Negative는 아닐 가능성이 존재한다.

 

이를 보정하는 방법이 바로 GIST(Guided In-sample Selection of Training Negatives)라는 방법이다.

말 그대로 일종의 Guide 모델을 통해, 뽑아진 Random Negative가 실제 True Negative인지 검증하는 것이다.

 

이런 방식을 통해 더욱 정교하게 Triplet 형태의 학습을 진행하게 되는 것이다.


간단하게 Sentence Transformer의 Loss Function들에 대해 알아보았다.

실제로는 단순 Triplet보다 Multi Negative를 활용한 방식이 훨씬 효과가 좋고.

 

이러한 Multi Negative의 크기가 크면 클 수록 효과가 더 좋다고 알려져있다.

(*In-Batch의 크기를 미친듯이 늘리기 위해 보통은 Cache를 활용한 방식을 많이 사용한다.)

 

때문에 Sentence-Transformer에서는 이러한 기능이 내장된 Cache ~ Loss Function들이 많이 존재한다.

이해하는 것이 크게 어렵지는 않으니 읽어보고 적절하게 사용하도록 하자.

  • 네이버 블로그 공유
  • 네이버 밴드 공유
  • 페이스북 공유