본문 바로가기
카테고리 없음

[LLM] Sentence_transformers를 이용해 커스텀 EmbeddingSimilarityEvaluator 만들기

by JustJunsu 2024. 10. 16.
반응형

1. 개요

문장 임베딩을 사용한 유사도 분석에서 다양한 평가 지표들이 활용됩니다. 이 포스팅에서는 sentence_transformers 라이브러리와 sklearn의 평가 지표를 활용하여, 문장 간 유사도를 평가하는 커스텀 EmbeddingSimilarityEvaluator 클래스를 구현하는 방법을 소개합니다.

 

문장 임베딩의 유사도 분석은 여러 NLP 작업에 필수적이며, 특히 문장 간 의미적 유사성을 측정하는 것이 중요합니다. 이를 보다 심도 있게 평가하기 위해 다양한 평가 지표를 활용하여 정확도를 높이고, 분석의 결과를 다각적으로 살펴볼 수 있습니다.

2. 사용한 라이브러리 및 환경 설정

pip install sentence-transformers sklearn scipy pandas

다음은 이 프로젝트에서 사용한 주요 라이브러리들입니다:

  • sentence_transformers: 문장 임베딩 및 유사도 계산을 위한 라이브러리
  • sklearn.metrics: 분류 성능 평가를 위한 다양한 메트릭
  • scipy.stats: 상관 계수 계산을 위한 라이브러리

3. 커스텀 EmbeddingSimilarityEvaluator 클래스

기존의 EmbeddingSimilarityEvaluator를 확장하여, 다양한 지표로 문장 간 유사도를 평가할 수 있는 클래스를 정의합니다. 이 클래스는 pearson, spearman 상관 계수와 AUC-ROC, F1-Score, 정확도 등의 다양한 평가 지표를 활용하여 임베딩의 유사도를 측정합니다.

주요 코드

from sentence_transformers.evaluation import EmbeddingSimilarityEvaluator
from sklearn.metrics.pairwise import paired_cosine_distances
from sklearn.metrics import roc_auc_score, accuracy_score, f1_score, precision_score, recall_score
from scipy.stats import pearsonr, spearmanr
import numpy as np

class CustomEmbeddingSimilarityEvaluator(EmbeddingSimilarityEvaluator):
    def __call__(self, model, output_path=None, epoch=-1, steps=-1):
        # 한 번만 임베딩 계산
        embeddings1 = model.encode(self.sentences1, batch_size=self.batch_size, convert_to_numpy=True)
        embeddings2 = model.encode(self.sentences2, batch_size=self.batch_size, convert_to_numpy=True)

        # 유사도 계산 및 성능 지표
        cosine_scores = 1 - (paired_cosine_distances(embeddings1, embeddings2))
        eval_pearson_cosine, _ = pearsonr(self.scores, cosine_scores)
        eval_spearman_cosine, _ = spearmanr(self.scores, cosine_scores)
        
        threshold = 0.5
        predicted_labels = (cosine_scores >= threshold).astype(int)
        
        eval_auc_roc = roc_auc_score(list(map(int, self.scores)), cosine_scores)
        eval_accuracy = accuracy_score(list(map(int, self.scores)), predicted_labels)
        eval_f1 = f1_score(list(map(int, self.scores)), predicted_labels)
        eval_precision = precision_score(list(map(int, self.scores)), predicted_labels)
        eval_recall = recall_score(list(map(int, self.scores)), predicted_labels)

        # 성능 결과 반환
        metrics = {
            "pearson_cosine": eval_pearson_cosine,
            "spearman_cosine": eval_spearman_cosine,
            "auc_roc": eval_auc_roc,
            "accuracy": eval_accuracy,
            "f1": eval_f1,
            "precision": eval_precision,
            "recall": eval_recall,
        }

        return metrics

 

  • 유사도 계산: paired_cosine_distances를 통해 두 임베딩 간의 코사인 유사도를 계산합니다.
  • 상관 계수: pearsonr 및 spearmanr 상관 계수를 사용해 예측 유사도와 실제 유사도의 관계를 평가합니다.
  • 이진 분류 성능: AUC-ROC, 정확도, F1 스코어, 정밀도, 재현율 등을 계산합니다.

4. 모델 성능 평가

다음은 실제로 학습된 여러 모델들에 대해 CustomEmbeddingSimilarityEvaluator를 활용해 성능을 평가하는 코드입니다.

 

데이터셋 로딩 함수:

import pandas as pd
from sentence_transformers import InputExample

def load_kor_sts_data(filename):
    # 파일을 pandas DataFrame으로 읽기
    df = pd.read_csv(filename, delimiter='\t', encoding='utf8', on_bad_lines='skip')
    df = df.dropna()
    data = []
    # 각 행을 반복하면서 필요한 데이터를 추출
    for _, row in df.iterrows():
        score = float(row['score']) / 5.0  # Normalize score to range 0 ... 1
        data.append(InputExample(texts=[row['sentence1'], row['sentence2']], label=score))
    
    return data

def load_kor_paws_data(filename):
    # 파일을 pandas DataFrame으로 읽기
    df = pd.read_csv(filename, delimiter='\t', encoding='utf8', on_bad_lines='skip')
    df = df.dropna()
    data = []
    # 각 행을 반복하면서 필요한 데이터를 추출
    for _, row in df.iterrows():
        label = row['label']
        data.append(InputExample(texts=[row['sentence1'], row['sentence2']], label=label))
    
    return data

 

모델 성능 평가 코드:

from sentence_transformers import SentenceTransformer
import pandas as pd
from tqdm import tqdm


model_list = ["BAAI/bge-m3","sentence-transformers/all-MiniLM-L6-v2"]

df = pd.DataFrame(columns=['model', 'pearson_cosine', 'spearman_cosine', "auc_roc", "accuracy", "f1", "precision", "recall"])  
    test_dataset = load_kor_sts_data(./KorNLUDatasets/KorSTS/sts-train.tsv)
    test_evaluator = CustomEmbeddingSimilarityEvaluator.from_input_examples(test_dataset, batch_size=16)

    for model_name in tqdm(model_list):
        model = SentenceTransformer(model_name, trust_remote_code=True)
        row = pd.DataFrame([test_evaluator(model)])
        row['model'] = model_name
        df = pd.concat([df, row], ignore_index=False)
df.to_csv(f"./results.csv", index=False)
  • 모델 리스트: 다양한 사전 학습된 Sentence Transformer 모델을 평가합니다.
  • 평가 데이터셋: 한국어 STS 데이터셋을 로드하여 평가합니다.
  • 결과 저장: CSV 파일로 성능 지표들을 저장해 각 모델의 평가 결과를 비교할 수 있습니다.

5. 결과 분석

성능 평가 결과는 CSV 파일로 저장됩니다. 이를 통해 각 모델이 다양한 지표에서 어떤 성능을 보이는지 확인할 수 있습니다. 예를 들어, 특정 모델이 AUC-ROC에서는 우수하나 F1 스코어에서는 낮을 수 있습니다. 이처럼 다양한 지표를 통해 문장 임베딩 모델의 유사도 분석 성능을 다각도로 평가할 수 있습니다.

 

Reference

https://github.com/kimjunsu97/ko-sentence-transformers-finetune/tree/main

 

GitHub - kimjunsu97/ko-sentence-transformers-finetune: this is finetune

this is finetune. Contribute to kimjunsu97/ko-sentence-transformers-finetune development by creating an account on GitHub.

github.com

https://github.com/UKPLab/sentence-transformers/blob/master/sentence_transformers/evaluation/EmbeddingSimilarityEvaluator.py

 

sentence-transformers/sentence_transformers/evaluation/EmbeddingSimilarityEvaluator.py at master · UKPLab/sentence-transformers

State-of-the-Art Text Embeddings. Contribute to UKPLab/sentence-transformers development by creating an account on GitHub.

github.com

 

반응형