KR-SBERT 모델
SBERT란?
SBERT란 Sentence BERT의 줄임말로, 기본적으로 BERT의 문장 임베딩 성능을 우수하게 개선한 모델이다. BERT의 문장 임베딩 방식은 총 세 가지가 있다.
-
[CLS]
token의 출력 벡터를 문장 벡터로 간주한다. - 입력 token의 모든 단어의 출력 벡터에 대해 Average Pooling을 수행한 벡터를 문장 벡터로 간주한다.
- 입력 token의 모든 단어의 출력 벡터에 대해 Max Pooling을 수행한 벡터를 문장 벡터로 간주한다.
이때 Average Pooling은 모든 입력 token의 의미를 반영하겠다는 의미이고, Max Pooling은 입력 token들 중 중요한 token의 의미를 반영하겠다는 것에 가깝다. SBERT는 위 세 가지의 문장 임베딩을 응용하여 BERT를 fine-tuning한다.
1. 문장 쌍 classification task로 fine-tuning
문장 쌍 classification task는 대표적으로 NLI(Natural Language Inference)가 있다. NLI란, 두 개의 문장이 주어졌을 때 앞 문장이 뒤따르는 문장에 대해 entailment, contradiction, neutral을 판단하는 classification task이다.
2. 문장 쌍 regression task로 fine-tuning
문장 쌍 regression task는 대표적으로 STS(Semantic Textual Similarity)가 있다. STS란, 두 개의 문장이 주어졌을 때 두 문장이 의미적으로 얼마나 유사한지를 0-5의 값으로 regression하는 task이다.
KR-SBERT
KR-SBERT란, 한국어 데이터셋을 사용하여 한국어에 특화된 SBERT이다. Hugging Face에 가보면 서울대에서 개발하고 업로드한 KR-SBERT의 여러 버전을 확인할 수 있다. 기본적으로 BERT 기반이기 때문에 tokenizer로는 WordPiece 알고리즘이 적용되었다.
이 모델을 STS task에 적용해보고 싶은데 이미 fine-tuning을 수행한 모델을 또 fine-tuning을 해도 되는 건지, epoch 수를 완전히 감소하거나 inference만 수행해야 될지 고민이 된다.
그런데 KR-SBERT의 버전이 너무 많다… 찾을 수 있는 자료를 찾아 정리해보도록 하겠다.
KR-SBERT-V40K-klueNLI-augSTS 🔗Link
모델은 KR-BERT의 변형인 KR-BERT-V40K를 사용했다. 기존 KR-SBERT의 vocab size는 119,547이기 때문에 V40K는 vocab size가 40k 즉, 40,000개라는 것을 의미하며 최적화를 한 듯하다.
NLI task 학습을 위해서 KLUE의 NLI 데이터셋을 사용했고, STS task 학습을 위해서는 KorSTS 데이터셋에 augmentation을 수행하였다.
KR-SBERT-Medium-klueNLI-klueSTS 🔗Link
모델은 Medium이기 때문에 V40K보다 많은 양의 vocab을 가지는 KR-SBERT를 사용한 듯하다.
NLI task 학습을 위해 위와 동일하게 KLUE의 NLI 데이터셋을 사용했고, STS task 학습을 위해서는 KorSTS가 아닌 KLUE의 STS 데이터셋을 사용하여 fine-tuning한 모델이다.
KR-SBERT 사용해보기
일단 BERT 기반이고, embedding 방식을 잘 학습했다고 하니 적용을 해보기로 했다.
1. fine-tunig
일반적으로 down-stream task를 잘 수행하는 방법인 fine-tuning을 해보기로 했다.
1
2
3
4
dataset: 한국어 STS 데이터셋
model: snunlp/KR-SBERT-V40K-klueNLI-augSTS
loss: cosine similarity loss
epoch: 10
위와 같이 설정하고 학습을 수행했는데 validation dataset으로 평가를 진행할 때마다 pearson-cosin 계수가 점점 작아진다..?
2. embedding 벡터 사용하기
embedding 방식을 잘 배운 모델이므로 이 자체로 task를 수행하기보다는 SBERT의 embedding 벡터를 사용해서 다른 모델의 input으로 사용하는 방법을 생각해보았다.
하지만 현재 baseline code가 hugging face의 trainer 모듈을 사용하는 코드이기 때문에 input 형식(input_ids, token_type_ids, attention_mask, labels)을 지켜야 한다. 또한 모델은 다른 SBERT가 아닌 다른 모델을 사용할 텐데, 이때 해당 모델에 적합한 tokenizer를 사용하지 않고 다른 모델의 embedding을 쓰는 것이 과연 옳은 일인가 싶었다. 이전에 다른 모델의 tokenizer를 사용했다가 최종 출력이 0-5사이 값을 벗어나는, STS task에서 유효하지 않은 값이 출력된 적이 있었기 때문에 일단 보류했다.
3. SBERT 자체로 추론하기
SBERT로 입력 문장에 대해서 embedding을 출력하고 similarity 함수를 사용해서 유사도를 측정한다면? 정확도가 80%밖에 나오지 않는다.
어떻게든 tuning을 하거나 다른 모델에 넣어야 할 것 같은데 마감 기한이 얼마 남지 않아 그냥 패스할까 한다.