본 콘텐츠의 이미지 및 내용은 AI로 생성되었습니다.
본 콘텐츠의 이미지 및 내용을 무단으로 복제, 배포, 수정하여 사용할 경우 저작권법에 의해 법적 제재를 받을 수 있습니다.
이미지 로딩 중...
AI Generated
2025. 11. 28. · 18 Views
SFT 분석 완벽 가이드
LLM을 실제 서비스에 활용하기 위한 핵심 기술인 SFT(Supervised Fine-Tuning)의 원리와 구현 방법을 초급 개발자도 이해할 수 있도록 상세히 설명합니다. 데이터 준비부터 학습, 평가까지 실무에서 바로 적용할 수 있는 내용을 담았습니다.
목차
1. SFT가 필요한 이유
김개발 씨는 회사에서 ChatGPT 같은 AI 챗봇을 만들어 달라는 요청을 받았습니다. "그냥 GPT API 쓰면 되는 거 아닌가요?"라고 물었더니, 팀장님이 고개를 저었습니다.
"우리 회사 데이터로 학습된, 우리만의 AI가 필요해요."
**SFT(Supervised Fine-Tuning)**는 이미 학습된 대규모 언어 모델을 특정 작업에 맞게 추가 학습시키는 기법입니다. 마치 대학교를 졸업한 신입사원에게 회사 업무를 가르치는 것과 같습니다.
기본 지식은 갖추고 있지만, 실제 업무 방식은 회사에서 배워야 하는 것처럼요.
다음 코드를 살펴봅시다.
# Pre-trained 모델을 불러옵니다
from transformers import AutoModelForCausalLM, AutoTokenizer
# 기본 모델 로드 - 아직 대화 방법을 모릅니다
base_model = AutoModelForCausalLM.from_pretrained("meta-llama/Llama-2-7b")
# SFT 전: 질문에 엉뚱한 답변
# 입력: "서울의 날씨는?"
# 출력: "서울의 날씨는 부산의 날씨는 대구의..." (문장 완성만 함)
# SFT 후: 의도를 이해하고 적절히 답변
# 입력: "서울의 날씨는?"
# 출력: "서울의 현재 날씨를 알려드리겠습니다. 오늘은..."
김개발 씨는 입사 6개월 차 ML 엔지니어입니다. 최근 회사에서 자체 AI 챗봇을 개발하라는 미션을 받았습니다.
처음에는 단순히 오픈소스 LLM을 가져다 쓰면 될 줄 알았습니다. 하지만 막상 Llama나 Mistral 같은 **기본 모델(Base Model)**을 다운로드해서 실행해보니, 뭔가 이상했습니다.
"오늘 서울 날씨 어때?"라고 물으면, "오늘 서울 날씨 어때? 내일은 부산에서..."처럼 질문을 이어서 완성하려고만 했습니다.
선배 개발자 박시니어 씨가 웃으며 말했습니다. "기본 모델은 그냥 '다음 단어 예측기'예요.
인터넷의 방대한 텍스트로 학습했지만, 대화하는 법은 배운 적이 없거든요." 그렇다면 SFT란 정확히 무엇일까요? 쉽게 비유하자면, SFT는 마치 운전면허 학원과 같습니다.
자동차의 구조와 원리는 이미 알고 있는 사람에게, 실제 도로에서 어떻게 운전해야 하는지를 가르치는 것입니다. "빨간 불이면 멈추세요", "보행자가 있으면 양보하세요"처럼 구체적인 상황별 행동 지침을 학습시키는 거죠.
기본 모델은 언어의 구조와 패턴을 잘 알고 있습니다. 하지만 "질문을 받으면 답변해야 한다"거나 "요청을 받으면 수행해야 한다"는 것은 모릅니다.
SFT는 바로 이 Instruction Following 능력을 가르치는 과정입니다. SFT가 없던 시절, 개발자들은 프롬프트 엔지니어링에 의존해야 했습니다.
"당신은 친절한 AI 어시스턴트입니다. 사용자의 질문에 정확하게 답변하세요..."라는 긴 시스템 프롬프트를 매번 붙여야 했습니다.
토큰 낭비도 심했고, 결과도 불안정했습니다. SFT를 적용하면 이 문제가 깔끔하게 해결됩니다.
모델 자체가 "질문이 들어오면 답변해야 한다"는 패턴을 내재화하기 때문입니다. 별도의 긴 프롬프트 없이도 자연스러운 대화가 가능해집니다.
실제로 ChatGPT, Claude, Gemini 같은 모든 상용 AI 어시스턴트는 SFT를 거쳤습니다. OpenAI의 InstructGPT 논문에서 밝힌 것처럼, SFT만으로도 모델의 유용성이 극적으로 향상됩니다.
박시니어 씨가 덧붙였습니다. "SFT는 LLM을 실제 서비스에 활용하기 위한 필수 관문이에요.
이걸 제대로 이해하면 나머지 기술들도 쉽게 따라올 겁니다." 김개발 씨는 고개를 끄덕였습니다. 이제 왜 SFT가 필요한지 명확히 이해했습니다.
다음 단계는 실제로 어떻게 구현하는지 배우는 것입니다.
실전 팁
💡 - 기본 모델과 SFT 모델의 출력 차이를 직접 비교해보면 SFT의 효과를 체감할 수 있습니다
- 처음에는 작은 데이터셋(1000개 미만)으로 실험하여 파이프라인을 검증하세요
2. chat sft.py 소스 코드 분석
"이론은 알겠는데, 실제 코드는 어떻게 생겼나요?" 김개발 씨가 물었습니다. 박시니어 씨는 화면에 chat_sft.py 파일을 열며 말했습니다.
"직접 보는 게 가장 빨라요. 한 줄씩 같이 살펴봅시다."
SFT 학습 코드는 크게 데이터 로딩, 모델 설정, 학습 루프 세 부분으로 구성됩니다. Hugging Face의 Transformers와 TRL 라이브러리를 활용하면 비교적 간단하게 구현할 수 있습니다.
핵심은 각 구성요소의 역할을 정확히 이해하는 것입니다.
다음 코드를 살펴봅시다.
from transformers import AutoModelForCausalLM, AutoTokenizer, TrainingArguments
from trl import SFTTrainer
from datasets import load_dataset
# 1. 모델과 토크나이저 로드
model = AutoModelForCausalLM.from_pretrained("meta-llama/Llama-2-7b-hf")
tokenizer = AutoTokenizer.from_pretrained("meta-llama/Llama-2-7b-hf")
tokenizer.pad_token = tokenizer.eos_token # 패딩 토큰 설정
# 2. 학습 데이터 로드
dataset = load_dataset("json", data_files="train_data.json")
# 3. 학습 설정
training_args = TrainingArguments(
output_dir="./sft_model",
num_train_epochs=3,
per_device_train_batch_size=4,
learning_rate=2e-5,
save_strategy="epoch"
)
# 4. SFT 트레이너 생성 및 학습 시작
trainer = SFTTrainer(model=model, args=training_args, train_dataset=dataset["train"])
trainer.train()
김개발 씨는 노트북을 펼치고 코드를 따라 치기 시작했습니다. 처음 보는 라이브러리들이 눈에 들어왔습니다.
transformers, trl, datasets... 이름만 들어봤지 실제로 써본 적은 없었습니다.
박시니어 씨가 차근차근 설명을 시작했습니다. "먼저 모델과 토크나이저를 불러와야 해요.
토크나이저는 텍스트를 모델이 이해할 수 있는 숫자로 바꿔주는 역할을 합니다." 코드의 첫 부분에서 AutoModelForCausalLM.from_pretrained()를 호출합니다. 이 함수는 Hugging Face Hub에서 사전학습된 모델을 자동으로 다운로드합니다.
Causal LM은 GPT 계열처럼 왼쪽에서 오른쪽으로 텍스트를 생성하는 언어 모델을 의미합니다. 토크나이저 설정에서 주목할 부분이 있습니다.
tokenizer.pad_token = tokenizer.eos_token 라인입니다. 많은 LLM이 기본적으로 패딩 토큰을 가지고 있지 않아서, 문장 끝 토큰(EOS)을 패딩 용도로 재사용합니다.
다음은 데이터 로드 부분입니다. load_dataset() 함수는 다양한 형식의 데이터를 쉽게 불러올 수 있게 해줍니다.
JSON, CSV, Parquet 등 대부분의 형식을 지원합니다. TrainingArguments는 학습의 세부 설정을 담당합니다.
num_train_epochs는 전체 데이터를 몇 번 반복 학습할지, per_device_train_batch_size는 GPU당 한 번에 처리할 데이터 수, learning_rate는 학습 속도를 결정합니다. 김개발 씨가 질문했습니다.
"learning_rate는 왜 2e-5인가요? 다른 값은 안 되나요?" 박시니어 씨가 답했습니다.
"좋은 질문이에요. **2e-5(0.00002)**는 LLM fine-tuning에서 가장 많이 쓰이는 값입니다.
너무 크면 기존에 학습한 내용을 잊어버리고, 너무 작으면 학습이 너무 느려요." SFTTrainer는 TRL 라이브러리에서 제공하는 클래스로, SFT에 필요한 모든 복잡한 로직을 내부적으로 처리해줍니다. 데이터 포맷팅, 토크나이징, 배치 처리 등을 자동으로 수행합니다.
마지막으로 trainer.train()을 호출하면 실제 학습이 시작됩니다. GPU 메모리에 따라 몇 시간에서 며칠이 걸릴 수 있습니다.
박시니어 씨가 강조했습니다. "이 기본 코드만 이해하면 SFT의 80%는 끝난 거예요.
나머지는 데이터 품질과 하이퍼파라미터 튜닝의 영역입니다." 김개발 씨는 코드를 저장하고 다음 단계로 넘어갈 준비를 했습니다.
실전 팁
💡 - 처음에는 num_train_epochs=1로 설정하여 전체 파이프라인이 정상 작동하는지 확인하세요
- GPU 메모리가 부족하면
per_device_train_batch_size를 줄이거나 gradient accumulation을 활용하세요
3. Instruction Following 데이터
"코드는 준비됐는데, 데이터는 어디서 구하나요?" 김개발 씨의 질문에 박시니어 씨가 진지한 표정으로 말했습니다. "SFT의 성패는 90%가 데이터에 달려 있어요.
아무리 좋은 코드도 나쁜 데이터 앞에서는 무력합니다."
Instruction Following 데이터는 사용자의 지시(instruction)와 그에 대한 적절한 응답(response)이 쌍으로 구성된 학습 데이터입니다. 마치 선생님이 학생에게 문제와 모범답안을 함께 보여주는 것과 같습니다.
데이터의 품질과 다양성이 모델의 성능을 직접적으로 결정합니다.
다음 코드를 살펴봅시다.
# Instruction Following 데이터 형식 예시
training_data = [
{
"instruction": "파이썬에서 리스트를 역순으로 정렬하는 방법을 알려주세요.",
"input": "", # 추가 컨텍스트가 필요한 경우 사용
"output": "파이썬에서 리스트를 역순으로 정렬하는 방법은 두 가지가 있습니다..."
},
{
"instruction": "다음 코드의 버그를 찾아 수정해주세요.",
"input": "def add(a, b):\n return a - b",
"output": "버그를 발견했습니다. return 문에서 뺄셈(-) 대신 덧셈(+)을 사용해야 합니다..."
}
]
# 대화 형식 데이터 (ChatML 포맷)
chat_data = {
"messages": [
{"role": "system", "content": "당신은 친절한 AI 어시스턴트입니다."},
{"role": "user", "content": "안녕하세요!"},
{"role": "assistant", "content": "안녕하세요! 무엇을 도와드릴까요?"}
]
}
박시니어 씨는 화이트보드에 데이터 구조를 그리기 시작했습니다. "SFT 데이터는 크게 두 가지 형식이 있어요.
Alpaca 형식과 ChatML 형식입니다." Alpaca 형식은 Stanford 대학에서 공개한 데이터셋에서 유래했습니다. instruction, input, output 세 필드로 구성됩니다.
instruction은 사용자의 요청, input은 추가적인 맥락 정보, output은 모델이 생성해야 할 응답입니다. 김개발 씨가 물었습니다.
"input 필드는 왜 비어있는 경우가 있나요?" 박시니어 씨가 설명했습니다. "모든 질문에 추가 정보가 필요한 건 아니거든요.
'파이썬이 뭐야?'같은 질문은 그 자체로 완결된 instruction입니다. 하지만 '이 코드의 버그를 찾아줘'라는 요청에는 해당 코드가 input으로 제공되어야 하죠." ChatML 형식은 대화형 AI에 더 적합합니다.
system, user, assistant 역할을 명시적으로 구분하여 멀티턴 대화를 자연스럽게 표현할 수 있습니다. OpenAI의 ChatGPT가 이 형식을 대중화했습니다.
데이터 품질에서 가장 중요한 것은 다양성입니다. 코딩 질문만 있으면 모델은 코딩만 잘하게 됩니다.
일상 대화, 분석, 창작, 요약 등 다양한 유형의 작업을 포함해야 합니다. 두 번째로 중요한 것은 응답의 품질입니다.
"좋은 응답이란 무엇인가"를 정의하는 것이 어렵지만, 일반적으로 정확하고, 유용하고, 안전한 응답이 좋은 응답입니다. 실제로 많은 기업들이 데이터 라벨링 팀을 운영합니다.
전문 라벨러들이 직접 고품질 응답을 작성하거나, AI가 생성한 응답을 검수합니다. OpenAI도 초기에 40명의 계약직 라벨러로 시작했습니다.
공개 데이터셋도 좋은 출발점입니다. Databricks Dolly, OpenAssistant, ShareGPT 등이 유명합니다.
하지만 각 데이터셋의 라이선스를 반드시 확인해야 합니다. 상업적 사용이 제한된 경우가 많습니다.
김개발 씨가 메모하며 물었습니다. "데이터가 얼마나 필요한가요?" 박시니어 씨가 답했습니다.
"경험적으로 최소 1,000개, 이상적으로는 10,000개 이상을 권장합니다. 하지만 품질이 가장 중요해요.
저품질 10만 개보다 고품질 1,000개가 낫습니다." 데이터 준비는 SFT에서 가장 시간이 많이 걸리는 단계입니다. 하지만 여기에 투자한 시간은 반드시 보상받습니다.
실전 팁
💡 - 처음에는 공개 데이터셋으로 시작하고, 점차 도메인 특화 데이터를 추가하세요
- 데이터 품질 검수를 위해 일부 샘플을 직접 읽어보는 습관을 들이세요
4. Loss 마스킹 기법
"잠깐, 여기서 중요한 개념이 하나 빠졌어요." 박시니어 씨가 코드를 스크롤하며 말했습니다. "Loss 마스킹을 모르면 SFT를 제대로 이해했다고 할 수 없어요." 김개발 씨는 처음 듣는 용어에 귀를 기울였습니다.
Loss 마스킹은 학습 시 특정 토큰의 손실(loss)을 계산에서 제외하는 기법입니다. SFT에서는 사용자의 입력 부분은 무시하고, 모델이 생성해야 할 응답 부분만 학습하도록 마스킹을 적용합니다.
마치 시험에서 문제는 읽기만 하고, 답안 작성법만 연습하는 것과 같습니다.
다음 코드를 살펴봅시다.
import torch
def create_labels_with_masking(input_ids, response_start_idx):
"""
instruction 부분은 -100으로 마스킹하여 loss 계산에서 제외
response 부분만 실제 label로 사용
"""
labels = input_ids.clone()
# instruction 부분을 -100으로 마스킹 (PyTorch CrossEntropyLoss가 무시)
labels[:response_start_idx] = -100
return labels
# 예시: "질문: 파이썬이란? 답변: 파이썬은 프로그래밍 언어입니다."
# input_ids: [질문, :, 파이썬, 이란, ?, 답변, :, 파이썬, 은, 프로그래밍, ...]
# labels: [-100, -100, -100, -100, -100, 파이썬, 은, 프로그래밍, ...]
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 마스킹됨 (loss 계산 X)
김개발 씨는 고개를 갸웃거렸습니다. "Loss 마스킹이요?
왜 굳이 일부를 무시해야 하나요? 전체 다 학습하면 안 되나요?" 박시니어 씨가 비유를 들어 설명했습니다.
"영어 회화 학원을 생각해보세요. 선생님이 'How are you?'라고 질문하면, 학생은 'I'm fine, thank you'라고 답해야 합니다.
이때 학생이 배워야 할 것은 답변하는 방법이지, 질문하는 방법이 아니에요." SFT도 마찬가지입니다. 모델에게 "질문: 파이썬이란?
답변: 파이썬은..."이라는 전체 텍스트를 보여주지만, 실제로 학습해야 할 것은 답변 부분입니다. 질문 부분까지 학습하면 모델이 불필요하게 질문을 따라하려고 합니다.
기술적으로 -100이라는 특별한 값을 사용합니다. PyTorch의 CrossEntropyLoss 함수는 레이블이 -100인 위치의 손실을 자동으로 무시합니다.
이것이 바로 마스킹의 핵심 메커니즘입니다. 코드를 보면, labels[:response_start_idx] = -100으로 응답 시작 전까지의 모든 토큰을 -100으로 설정합니다.
이렇게 하면 해당 부분의 예측이 틀려도 loss에 반영되지 않습니다. 실제 SFT 라이브러리들은 이 과정을 자동화합니다.
TRL의 SFTTrainer는 데이터 형식을 분석하여 자동으로 마스킹을 적용합니다. 하지만 원리를 알아야 문제가 생겼을 때 디버깅할 수 있습니다.
Loss 마스킹을 적용하지 않으면 어떤 일이 벌어질까요? 모델이 instruction까지 학습하면서 혼란에 빠집니다.
"질문: 안녕하세요"처럼 질문 형식을 그대로 출력하는 경우가 생깁니다. 더 심각한 문제는 학습 효율 저하입니다.
instruction 부분의 loss까지 계산하면, 실제로 중요한 response 학습에 쓸 수 있는 gradient 신호가 희석됩니다. 김개발 씨가 정리했습니다.
"결국 모델에게 '여기서부터 여기까지만 집중해서 배워'라고 알려주는 거네요." 박시니어 씨가 고개를 끄덕였습니다. "정확해요.
단순해 보이지만, 이 작은 차이가 모델 성능에 큰 영향을 미칩니다."
실전 팁
💡 - ChatML 형식을 사용하면 role 구분이 명확해서 마스킹 적용이 쉬워집니다
- 마스킹이 제대로 적용됐는지 확인하려면 몇 개 샘플의 labels를 출력해보세요
5. 과적합 방지 전략
학습을 시작한 지 몇 시간이 지났습니다. 김개발 씨는 뿌듯한 마음으로 loss 그래프를 확인했습니다.
훈련 loss는 계속 떨어지고 있었습니다. 하지만 박시니어 씨의 표정이 어두워졌습니다.
"검증 loss도 확인해봤어요?"
**과적합(Overfitting)**은 모델이 훈련 데이터를 너무 완벽하게 암기해서, 새로운 데이터에 대한 일반화 능력을 잃는 현상입니다. 마치 시험 문제만 달달 외워서 같은 문제는 풀지만, 조금만 변형되면 손도 못 대는 학생과 같습니다.
SFT에서는 특히 데이터셋이 작을 때 과적합이 자주 발생합니다.
다음 코드를 살펴봅시다.
from transformers import TrainingArguments, EarlyStoppingCallback
training_args = TrainingArguments(
output_dir="./sft_model",
num_train_epochs=3,
per_device_train_batch_size=4,
learning_rate=2e-5,
# 과적합 방지 전략 1: 검증 데이터 모니터링
eval_strategy="steps",
eval_steps=100,
# 과적합 방지 전략 2: 가중치 감쇠
weight_decay=0.01,
# 과적합 방지 전략 3: 학습률 스케줄링
warmup_ratio=0.1,
lr_scheduler_type="cosine",
# 최적 모델 저장
load_best_model_at_end=True,
metric_for_best_model="eval_loss"
)
# 과적합 방지 전략 4: Early Stopping
early_stopping = EarlyStoppingCallback(early_stopping_patience=3)
김개발 씨는 당황했습니다. 검증 데이터를 따로 준비하지 않았던 것입니다.
박시니어 씨가 한숨을 쉬며 설명을 시작했습니다. "훈련 loss가 떨어지는 건 당연해요.
문제는 처음 보는 데이터에서도 잘 작동하느냐입니다. 이걸 확인하려면 훈련에 사용하지 않은 별도의 검증 데이터가 필요해요." 과적합은 딥러닝의 오래된 적입니다.
모델의 파라미터 수가 많을수록, 훈련 데이터가 적을수록 과적합 위험이 커집니다. 7B 파라미터의 LLM을 1,000개의 데이터로 학습하면?
거의 확실하게 과적합됩니다. 첫 번째 방어선은 검증 데이터 모니터링입니다.
전체 데이터의 10-20%를 검증용으로 떼어놓고, 일정 간격으로 검증 loss를 측정합니다. 훈련 loss는 떨어지는데 검증 loss가 올라가기 시작하면 과적합의 신호입니다.
두 번째는 **가중치 감쇠(Weight Decay)**입니다. 모델의 가중치가 너무 커지지 않도록 패널티를 부여합니다.
weight_decay=0.01은 가중치 크기의 1%를 loss에 더하는 것과 같습니다. 이렇게 하면 모델이 데이터를 암기하기보다 일반적인 패턴을 학습하게 됩니다.
세 번째는 학습률 스케줄링입니다. 처음에는 천천히 시작해서(warmup), 중간에 최대로 올렸다가, 끝으로 갈수록 조심스럽게 줄입니다(cosine decay).
마치 자동차 운전처럼, 출발할 때와 도착할 때는 속도를 줄이는 것입니다. 네 번째는 Early Stopping입니다.
검증 loss가 일정 횟수(patience) 동안 개선되지 않으면 학습을 조기 종료합니다. "더 이상 좋아지지 않으니 그만하자"는 전략입니다.
김개발 씨가 물었습니다. "이것들을 다 써야 하나요?" 박시니어 씨가 답했습니다.
"상황에 따라 달라요. 데이터가 충분하면 과적합 걱정이 적고, 데이터가 적으면 모든 수단을 동원해야 해요.
일반적으로 검증 모니터링과 Early Stopping은 필수입니다." 추가로 LoRA나 QLoRA 같은 파라미터 효율적 학습 기법도 과적합 방지에 도움이 됩니다. 전체 파라미터가 아닌 일부만 학습하므로, 과적합 가능성이 줄어듭니다.
김개발 씨는 코드를 수정하고 검증 데이터를 추가했습니다. 이제 학습 과정을 더 안전하게 모니터링할 수 있게 되었습니다.
실전 팁
💡 - 데이터셋이 작다면 3 epoch 이상 학습하지 마세요
- Weights & Biases나 TensorBoard로 훈련/검증 loss를 실시간 모니터링하세요
6. SFT 전후 성능 비교
드디어 학습이 완료되었습니다. 김개발 씨는 설레는 마음으로 모델을 테스트할 준비를 했습니다.
"진짜 효과가 있을까요?" 박시니어 씨가 웃으며 말했습니다. "직접 확인해보는 게 가장 확실하죠.
비교 실험을 해봅시다."
SFT의 효과를 검증하려면 동일한 질문에 대해 SFT 전후 모델의 응답을 비교해야 합니다. 단순히 "좋아 보인다"가 아니라, 구체적인 평가 지표와 정성적 분석을 함께 수행합니다.
실제 서비스 도입 전에 반드시 거쳐야 할 단계입니다.
다음 코드를 살펴봅시다.
from transformers import AutoModelForCausalLM, AutoTokenizer
import torch
def compare_models(prompt, base_model, sft_model, tokenizer):
"""Base 모델과 SFT 모델의 응답을 비교합니다"""
inputs = tokenizer(prompt, return_tensors="pt")
# Base 모델 응답 생성
with torch.no_grad():
base_output = base_model.generate(**inputs, max_new_tokens=100)
base_response = tokenizer.decode(base_output[0], skip_special_tokens=True)
# SFT 모델 응답 생성
with torch.no_grad():
sft_output = sft_model.generate(**inputs, max_new_tokens=100)
sft_response = tokenizer.decode(sft_output[0], skip_special_tokens=True)
print(f"[Base Model]: {base_response}")
print(f"[SFT Model]: {sft_response}")
# 테스트 실행
test_prompt = "파이썬에서 리스트를 정렬하는 방법을 알려주세요."
compare_models(test_prompt, base_model, sft_model, tokenizer)
비교 실험 결과가 화면에 나타났습니다. 김개발 씨는 그 차이에 깜짝 놀랐습니다.
Base 모델에게 "파이썬에서 리스트를 정렬하는 방법을 알려주세요"라고 질문하자, 이런 응답이 돌아왔습니다. "파이썬에서 리스트를 정렬하는 방법을 알려주세요.
자바에서는 어떻게 하나요? C++에서는..." 질문을 이어서 확장할 뿐, 답변은 없었습니다.
SFT 모델은 달랐습니다. "파이썬에서 리스트를 정렬하는 방법은 크게 두 가지가 있습니다.
첫째, sort() 메서드를 사용하면 원본 리스트가 정렬됩니다. 둘째, sorted() 함수를 사용하면 새로운 정렬된 리스트가 반환됩니다." 박시니어 씨가 설명했습니다.
"이게 바로 SFT의 힘이에요. 모델이 질문의 의도를 이해하고 답변하는 법을 배운 겁니다." 정량적 평가도 중요합니다.
자주 사용되는 지표로는 BLEU, ROUGE, Perplexity 등이 있습니다. 하지만 LLM 평가에서 이런 자동 지표의 한계도 알려져 있습니다.
최근에는 LLM-as-a-Judge 방식이 인기입니다. GPT-4 같은 강력한 모델에게 두 응답을 보여주고, 어떤 응답이 더 좋은지 판단하게 합니다.
사람의 평가와 상관관계가 높다고 알려져 있습니다. 실제 서비스에서는 A/B 테스트가 가장 확실합니다.
실제 사용자의 일부에게 SFT 모델을, 나머지에게 기존 모델을 제공하고, 사용자 만족도나 참여도를 비교합니다. 김개발 씨가 물었습니다.
"SFT만으로 충분한가요? ChatGPT처럼 만들려면요?" 박시니어 씨가 답했습니다.
"좋은 질문이에요. SFT는 시작점입니다.
더 나은 성능을 위해서는 **RLHF(Reinforcement Learning from Human Feedback)**나 DPO(Direct Preference Optimization) 같은 추가 학습이 필요해요. 하지만 SFT 없이는 이런 고급 기법도 적용할 수 없습니다." SFT는 LLM을 실용적인 AI 어시스턴트로 바꾸는 첫 번째이자 가장 중요한 단계입니다.
김개발 씨는 이제 그 원리와 구현 방법을 모두 이해하게 되었습니다. 프로젝트 발표 날, 김개발 씨가 만든 AI 챗봇은 팀장님의 기대를 뛰어넘었습니다.
"이게 우리 데이터로 학습한 AI라고요? 대단하네요!" 김개발 씨는 뿌듯한 미소를 지었습니다.
SFT에 투자한 시간이 보상받는 순간이었습니다.
실전 팁
💡 - 평가용 테스트셋을 미리 만들어두고, 학습 중에는 절대 사용하지 마세요
- 정량적 지표와 정성적 평가(직접 응답 읽어보기)를 병행하세요
이상으로 학습을 마칩니다. 위 내용을 직접 코드로 작성해보면서 익혀보세요!
댓글 (0)
함께 보면 좋은 카드 뉴스
Helm 마이크로서비스 패키징 완벽 가이드
Kubernetes 환경에서 마이크로서비스를 효율적으로 패키징하고 배포하는 Helm의 핵심 기능을 실무 중심으로 학습합니다. Chart 생성부터 릴리스 관리까지 체계적으로 다룹니다.
보안 아키텍처 구성 완벽 가이드
프로젝트의 보안을 처음부터 설계하는 방법을 배웁니다. AWS 환경에서 VPC부터 WAF, 암호화, 접근 제어까지 실무에서 바로 적용할 수 있는 보안 아키텍처를 단계별로 구성해봅니다.
AWS Organizations 완벽 가이드
여러 AWS 계정을 체계적으로 관리하고 통합 결제와 보안 정책을 적용하는 방법을 실무 스토리로 쉽게 배워봅니다. 초보 개발자도 바로 이해할 수 있는 친절한 설명과 실전 예제를 제공합니다.
AWS KMS 암호화 완벽 가이드
AWS KMS(Key Management Service)를 활용한 클라우드 데이터 암호화 방법을 초급 개발자를 위해 쉽게 설명합니다. CMK 생성부터 S3, EBS 암호화, 봉투 암호화까지 실무에 필요한 모든 내용을 담았습니다.
AWS Secrets Manager 완벽 가이드
AWS에서 데이터베이스 비밀번호, API 키 등 민감한 정보를 안전하게 관리하는 Secrets Manager의 핵심 개념과 실무 활용법을 배워봅니다. 초급 개발자도 쉽게 따라할 수 있도록 실전 예제와 함께 설명합니다.