LLM

[LLM] PAWS-X 한국어 데이터셋을 이용한 HuggingFace Embedding 모델 Finetuning

JustJunsu 2024. 10. 8. 17:50
728x90

이번 포스팅에서는 HuggingFace Embedding 모델을 활용하여 문장 쌍의 유사도를 계산하고, 모델의 성능을 평가하는 과정을 다룹니다. PAWS 한국어 데이터셋을 사용하여 모델을 Finetuning하고, 각 모델을 평가하며, 모델 성능을 확인해보겠습니다.

 

데이터셋 설명

PAWS(Paraphrase Adversaries from Word Scrambling) 데이터셋은 문장 쌍이 의미적으로 같은지 여부를 나타내는 데이터셋입니다. 이 데이터셋을 통해 우리는 문장 임베딩의 유사도를 평가할 수 있습니다. 훈련, 테스트, 검증 데이터셋으로 나누어져 있으며, 각 데이터셋은 학습 과정과 평가에 사용됩니다. 특히, PAWS는 유사한 문장의 순서가 바뀌었을 때 모델이 그 차이를 얼마나 잘 구별하는지를 평가할 수 있도록 설계되었습니다.

PAWS-X 데이터셋 다운로드: https://github.com/google-research-datasets/paws/tree/master/pawsx

 

paws/pawsx at master · google-research-datasets/paws

This dataset contains 108,463 human-labeled and 656k noisily labeled pairs that feature the importance of modeling structure, context, and word order information for the problem of paraphrase ident...

github.com

 

코드

1. 데이터 준비

1.1 데이터 다운로드

먼저, PAWS 한국어 데이터셋을 다운로드합니다. 이 데이터셋은 다양한 언어로 제공되며, 한국어 데이터셋을 활용하여 모델을 학습시킬 것입니다.

!wget https://storage.googleapis.com/paws/pawsx/x-final.tar.gz
!tar -zxvf x-final.tar.gz

 

1.2 Dataset 만들기

데이터를 로드하고 전처리하는 과정을 진행합니다. 결측치가 있는 행은 제거하여 모델 학습에 문제가 없도록 합니다.

import pandas as pd

# 데이터셋 준비
train_dataset = pd.read_csv("./x-final/ko/translated_train.tsv", delimiter="\t", skiprows=[1249, 1679, 2164, 7641, 15125, 18436, 25867, 29463, 37343, 38768])
test_dataset = pd.read_csv("./x-final/ko/test_2k.tsv", delimiter="\t")
dev_dataset = pd.read_csv("./x-final/ko/dev_2k.tsv", delimiter="\t")

train_dataset = train_dataset.dropna()
test_dataset = test_dataset.dropna()
dev_dataset = dev_dataset.dropna()

2. Data Loader 만들기

모델이 학습할 수 있는 형식으로 데이터를 변환합니다. InputExample을 사용하여 각 문장 쌍과 레이블을 준비한 후, DataLoader에 넣습니다. 이는 모델이 배치 단위로 데이터를 처리할 수 있도록 도와줍니다.

from sentence_transformers import InputExample
from torch.utils.data import DataLoader

def create_input_set(df):
    set = []
    for i, row in df.iterrows():
        set.append(InputExample(texts=[row['sentence1'], row['sentence2']], label=row['label']))
    return set

train_set = create_input_set(train_dataset)
test_set = create_input_set(test_dataset)
dev_set = create_input_set(dev_dataset)

train_dataloader = DataLoader(train_set, shuffle=True, batch_size=16)
dev_dataloader = DataLoader(dev_set, shuffle=False, batch_size=16)
test_dataloader = DataLoader(test_set, shuffle=False, batch_size=16)

3. Evaluator 만들기

모델의 성능을 평가하기 위해 검증 및 테스트 데이터셋을 활용하여 EmbeddingSimilarityEvaluator를 생성합니다. 이 평가는 문장 간의 유사도를 측정하여 모델이 얼마나 정확하게 유사도를 예측하는지 확인합니다. Cosine Similarity는 두 벡터 간의 각도를 기준으로 유사도를 측정하며, 유사도가 높을수록 두 문장이 의미적으로 더 유사하다는 뜻입니다.

from sentence_transformers.evaluation import EmbeddingSimilarityEvaluator, SimilarityFunction

evaluator = EmbeddingSimilarityEvaluator(
        sentences1=[row['sentence1'] for _, row in dev_dataset.iterrows()],
        sentences2=[row['sentence2'] for _, row in dev_dataset.iterrows()],
        scores=[row['label'] for _, row in dev_dataset.iterrows()],
        main_similarity=SimilarityFunction.COSINE
    )

tester = EmbeddingSimilarityEvaluator(
        sentences1=[row['sentence1'] for _, row in test_dataset.iterrows()],
        sentences2=[row['sentence2'] for _, row in test_dataset.iterrows()],
        scores=[row['label'] for _, row in test_dataset.iterrows()],
        main_similarity=SimilarityFunction.COSINE
    )

4. model 만들기

SentenceTransformer 모델을 불러옵니다. HuggingFace에서 제공하는 다양한 모델 중에서 선택할 수 있으며, 이 예시에서는 all-MiniLM-L6-v2 모델을 사용했습니다.

from sentence_transformers import SentenceTransformer

model_name = "sentence-transformers/all-MiniLM-L6-v2"
model = SentenceTransformer(model_name,trust_remote_code=True)

5. Loss Function 만들기

모델을 Finetuning하기 위해 CosineSimilarityLoss 손실 함수를 사용합니다. 이 손실 함수는 문장 임베딩의 유사도를 학습시키는 데 적합합니다.

from sentence_transformers import losses

train_loss = losses.CosineSimilarityLoss(model)

6. 모델 Finetuning 하기

DataLoader와 손실 함수를 사용하여 모델을 학습시킵니다. 학습 중에는 주기적으로 평가를 진행하여 성능을 확인할 수 있습니다.

Finetuning: 사전 학습된 모델을 특정 태스크에 맞게 미세 조정하는 과정입니다. Finetuning을 통해 모델이 해당 태스크에 더 적합하게 학습될 수 있습니다.

model.fit(
        train_objectives=[(train_dataloader, train_loss)],
        epochs=1,
        evaluation_steps=500,
        evaluator=evaluator, 
        output_path=f"./finetune/{model_name}"
    )

 

6. 모델 평가하기

기존 모델과 Finetuning된 모델을 테스트 데이터셋을 이용해 각각 평가하고, 결과를 비교합니다. 이를 통해 Finetuning이 모델 성능에 미치는 영향을 확인할 수 있습니다. 먼저, 사전 학습된 원본 SentenceTransformer 모델을 평가하고, 그 결과를 출력합니다. 그 다음, Finetuning된 모델을 테스트 데이터셋에 대해 평가하여 성능 차이를 분석합니다.

# 기존 모델 평가
model1 = SentenceTransformer(model_name)
result1 = model1.evaluate(tester)
print(f"기존 모델 평가 결과: {result1}")

# Finetuning된 모델 평가
model2 = SentenceTransformer(f'./finetune/{model_name}')
result2 = model2.evaluate(tester)
print(f"Finetuning된 모델 평가 결과: {result2}")
기존 모델 평가 결과: {'pearson_cosine': 0.06618380782181696, 'spearman_cosine': 0.07363272071159599, 'pearson_manhattan': 0.0706390322935152, 'spearman_manhattan': 0.0733424171814407, 'pearson_euclidean': 0.07157744373978166, 'spearman_euclidean': 0.07362480845366957, 'pearson_dot': 0.06618381138317346, 'spearman_dot': 0.07365444069493612, 'pearson_max': 0.07157744373978166, 'spearman_max': 0.07365444069493612}
Finetuning된 모델 평가 결과: {'pearson_cosine': 0.09289440749712949, 'spearman_cosine': 0.08963490759477705, 'pearson_manhattan': 0.1028526780701269, 'spearman_manhattan': 0.08920862313980303, 'pearson_euclidean': 0.1039259898471214, 'spearman_euclidean': 0.08961477845462872, 'pearson_dot': 0.09289440989395883, 'spearman_dot': 0.08965312027714303, 'pearson_max': 0.1039259898471214, 'spearman_max': 0.08965312027714303}

 

이번 포스팅에서는 PAWS 한국어 데이터셋을 사용하여 HuggingFace Embedding 모델을 Finetuning하고, 문장 간의 유사도를 평가하는 방법을 살펴보았습니다. 사전 학습된 모델과 Finetuning된 모델을 테스트 데이터셋으로 평가하여 성능 차이를 비교했습니다.

Finetuning을 통해 모델의 성능을 더 높일 수 있었으며, 이를 통해 다양한 자연어 처리(NLP) 태스크에서의 활용 가능성을 확인할 수 있었습니다.

앞으로는 다른 모델을 사용하거나, 더 많은 데이터를 사용하여 추가적으로 Finetuning을 진행함으로써 성능을 더욱 개선해볼 수 있을 것입니다.

 

Reference

https://www.sbert.net/docs/sentence_transformer/training_overview.html#dataset

 

Training Overview — Sentence Transformers documentation

If you want to load data from the Hugging Face Datasets, then you should use datasets.load_dataset(): from datasets import load_dataset train_dataset = load_dataset("sentence-transformers/all-nli", "pair-class", split="train") eval_dataset = load_dataset("

www.sbert.net

 

728x90