전체 코드
(Colab에서 GPU A100 40GB 할당 받아 수행) 수행시간 약 4시간
더보기
import torch
import pandas as pd
from transformers import AutoTokenizer, AutoModelForCausalLM
from datasets import load_dataset
from sentence_transformers import SentenceTransformer, util
from nltk.translate.bleu_score import sentence_bleu, SmoothingFunction
import nltk
from tqdm import tqdm
from multiprocessing import Pool
nltk.download('punkt_tab', quiet=True)
# 1. 테스트 데이터 로드
data_path = "/content/drive/MyDrive/Colab Notebooks/Llama3.1 8B/db/emotional_data/test/test.jsonl"
test_dataset = load_dataset("json", data_files={"test": data_path}, split="test")
# 2. 테스트 데이터에서 입력과 정답 추출
def extract_conversation_pairs(dataset):
inputs = []
references = []
for conversation in dataset:
messages = conversation["messages"]
system_prompt = messages[0]["content"] # System 메시지
history = [system_prompt]
for i in range(1, len(messages) - 1, 2): # user-assistant 쌍 추출
if messages[i]["role"] == "user" and messages[i + 1]["role"] == "assistant":
user_message = messages[i]["content"]
assistant_message = messages[i + 1]["content"]
# 대화 히스토리와 함께 입력 구성
history.append(f"User: {user_message}")
inputs.append("\n".join(history))
references.append(assistant_message)
history.append(f"Assistant: {assistant_message}")
return inputs, references
inputs, references = extract_conversation_pairs(test_dataset)
print(f"총 평가 샘플 수: {len(inputs)}")
# 3. 모델 로드
# 미세 조정 전 모델
base_model_name = "meta-llama/Meta-Llama-3.1-8B"
base_tokenizer = AutoTokenizer.from_pretrained(base_model_name)
base_model = AutoModelForCausalLM.from_pretrained(base_model_name, torch_dtype=torch.float16, device_map="auto")
base_model.eval()
# 미세 조정 후 모델
finetuned_model_path = "/content/drive/MyDrive/Colab Notebooks/Llama3.1 8B/lora_finetuned_model/checkpoint-3227"
finetuned_tokenizer = AutoTokenizer.from_pretrained(finetuned_model_path)
finetuned_model = AutoModelForCausalLM.from_pretrained(finetuned_model_path, torch_dtype=torch.float16, device_map="auto")
finetuned_model.eval()
# 패딩 토큰 설정
base_tokenizer.pad_token = base_tokenizer.eos_token
base_tokenizer.padding_side = "left"
finetuned_tokenizer.pad_token = finetuned_tokenizer.eos_token
finetuned_tokenizer.padding_side = "left"
# 4. 배치 응답 생성 함수
def generate_response_batch(model, tokenizer, input_texts, batch_size=16, max_length=256):
model.eval()
responses = []
with torch.no_grad():
for i in tqdm(range(0, len(input_texts), batch_size), desc="Generating responses"):
batch = input_texts[i:i + batch_size]
inputs = tokenizer(batch, return_tensors="pt", max_length=max_length, truncation=True, padding=True).to("cuda")
outputs = model.generate(
**inputs,
max_length=max_length,
do_sample=True,
temperature=0.7,
pad_token_id=tokenizer.eos_token_id
)
decoded = tokenizer.batch_decode(outputs, skip_special_tokens=True)
# 입력 텍스트 제거 및 "Assistant:" 접두어 제거
batch_responses = [resp[len(input_text):].replace("Assistant:", "").strip()
for input_text, resp in zip(batch, decoded)]
responses.extend(batch_responses)
return responses
# 5. BLEU 계산 함수
def calculate_bleu(reference, candidate):
reference_tokens = [nltk.word_tokenize(reference)]
candidate_tokens = nltk.word_tokenize(candidate)
smoothie = SmoothingFunction().method4
return sentence_bleu(reference_tokens, candidate_tokens, smoothing_function=smoothie)
# 6. 코사인 유사도 계산 준비
sentence_model = SentenceTransformer('sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2').to("cuda")
def calculate_cosine_similarity_batch(references, candidates):
ref_embeddings = sentence_model.encode(references, batch_size=32, convert_to_tensor=True, device="cuda")
cand_embeddings = sentence_model.encode(candidates, batch_size=32, convert_to_tensor=True, device="cuda")
cosine_scores = util.cos_sim(ref_embeddings, cand_embeddings)
return torch.diag(cosine_scores).cpu().tolist()
# 7. 평가 수행
base_responses = generate_response_batch(base_model, base_tokenizer, inputs, batch_size=16)
finetuned_responses = generate_response_batch(finetuned_model, finetuned_tokenizer, inputs, batch_size=16)
# BLEU 병렬 계산
def compute_bleu(args):
ref, base_resp, finetuned_resp = args
base_bleu = calculate_bleu(ref, base_resp)
finetuned_bleu = calculate_bleu(ref, finetuned_resp)
return base_bleu, finetuned_bleu
with Pool(processes=4) as pool:
bleu_results = list(tqdm(pool.imap(compute_bleu, zip(references, base_responses, finetuned_responses)),
total=len(inputs), desc="Calculating BLEU scores"))
base_bleu_scores, finetuned_bleu_scores = zip(*bleu_results)
# 코사인 유사도 배치 계산
base_cosine_scores = calculate_cosine_similarity_batch(references, base_responses)
finetuned_cosine_scores = calculate_cosine_similarity_batch(references, finetuned_responses)
# 8. 평균 점수 계산
avg_base_bleu = sum(base_bleu_scores) / len(base_bleu_scores)
avg_finetuned_bleu = sum(finetuned_bleu_scores) / len(finetuned_bleu_scores)
avg_base_cosine = sum(base_cosine_scores) / len(base_cosine_scores)
avg_finetuned_cosine = sum(finetuned_cosine_scores) / len(finetuned_cosine_scores)
# 9. 결과 출력
print("\n=== 평가 결과 ===")
print(f"미세 조정 전 BLEU 점수: {avg_base_bleu:.4f}")
print(f"미세 조정 후 BLEU 점수: {avg_finetuned_bleu:.4f}")
print(f"미세 조정 전 코사인 유사도: {avg_base_cosine:.4f}")
print(f"미세 조정 후 코사인 유사도: {avg_finetuned_cosine:.4f}")
📊 BLEU 점수 & 코사인 유사도 개선 분석
샘플 약 18000개에 대한 답변을 평가하였습니다.
모델 | 평가 수행 시간 | BELU 점수 | 코사인 유사도 |
---|---|---|---|
Llama 3.1 8B 기본 모델 | 1시간 39분 | 0.0075 | 0.3891 |
한국어 감성 말뭉치로 학습된 Fine-tuning 모델 | 2시간 25분 | 0.0173 | 0.4741 |
1. BLEU 점수 개선 분석
BLEU(Bilingual Evaluation Understudy) 점수는 기계 번역 및 텍스트 생성 품질을 평가하는 지표로, 0~1 사이의 값을 가짐.
값이 높을수록 참조 텍스트와 유사한 텍스트를 생성했다고 평가할 수 있음.
📈 미세 조정 전후 변화
0.0075 → 0.0173
🔍 해석
- BLEU 점수가 약 130.67% 증가 (약 2.3배 개선).
- 하지만 여전히 낮은 편(0.0173).
- 일반적으로 0.3~0.5 이상이 되어야 사람이 보기에도 좋은 품질로 간주됨.
- ➡ 결론: BLEU 점수가 개선되었지만, 추가적인 개선이 필요할 가능성이 있음.
2. 코사인 유사도 개선 분석
코사인 유사도는 생성된 텍스트와 참조 텍스트의 의미적 유사도를 측정하는 지표로, 0~1 사이의 값을 가짐.
1에 가까울수록 의미적으로 더 유사함.
📈 미세 조정 전후 변화
0.3891 → 0.4741
🔍 해석
- 코사인 유사도가 약 21.84% 증가 (약 1.22배 개선).
- 의미적 일치도가 약 8.5%포인트 증가.
- 0.5에 가까워지고 있어 의미적 유사도가 향상된 것으로 판단 가능.
- ➡ 결론: 생성된 텍스트가 참조 텍스트와 의미적으로 더 가까워졌으며, 긍정적인 변화가 나타남.
📌 종합적인 개선 정도
✅ BLEU 점수: 130.67% 증가 (약 2.3배 개선)
→ 절대값은 낮지만, 미세 조정 후 품질이 상당히 향상됨.
✅ 코사인 유사도: 21.84% 증가 (약 1.22배 개선)
→ 의미적 유사도가 더 좋아졌으며, 0.5에 가까워지는 긍정적인 변화.
🎯 최종 요약
- BLEU 점수: 130.67% 증가 (약 2.3배 개선), 하지만 절대값이 낮아 추가 개선 필요.
- 코사인 유사도: 21.84% 증가 (약 1.22배 개선), 의미적 일치도가 더 나아짐.
- 미세 조정이 모델 성능에 긍정적인 영향을 미침!
- 하지만 BLEU 점수가 여전히 낮아 추가적인 개선이 필요할 수도 있음.
'LLM > LLM 개발' 카테고리의 다른 글
Llama 3.1 8B 파인튜닝 하기(1) - 전처리, 파인튜닝 (0) | 2025.03.17 |
---|---|
Llama 3.1 8B 로컬에서 실행하기 (0) | 2025.03.13 |