Few-shot Learning
퓨샷 러닝
소수의 예시만으로 새로운 작업을 학습하는 기법. LLM의 In-context learning 핵심 능력.
퓨샷 러닝
소수의 예시만으로 새로운 작업을 학습하는 기법. LLM의 In-context learning 핵심 능력.
Few-shot Learning은 소수의 예시(보통 1-5개)만으로 새로운 작업을 수행하는 학습 기법입니다. LLM에서는 프롬프트에 몇 가지 입출력 예시를 제공하여 모델이 패턴을 파악하고 같은 형식으로 응답하도록 유도합니다. Zero-shot(예시 없음), One-shot(1개 예시), Few-shot(2-5개 예시)으로 구분됩니다.
Few-shot Learning 개념은 2020년 GPT-3 논문 "Language Models are Few-Shot Learners"에서 대중화되었습니다. 이 논문은 175B 파라미터 모델이 파인튜닝 없이 프롬프트의 예시만으로 다양한 NLP 작업을 수행할 수 있음을 보였습니다. 이를 In-Context Learning(ICL)이라고 하며, LLM의 emergent ability(창발적 능력) 중 하나입니다.
Few-shot Learning의 핵심 원리는 모델이 프롬프트의 예시에서 작업 패턴을 추론하는 것입니다. 모델의 가중치는 변하지 않으며, 컨텍스트 내의 예시가 출력 분포를 조건화합니다. 예시의 형식, 순서, 다양성이 성능에 큰 영향을 미칩니다. 최근 연구에 따르면 예시의 레이블보다 형식이 더 중요한 경우도 있습니다.
실무에서 Few-shot Learning은 빠른 프로토타이핑과 데이터가 부족한 상황에서 유용합니다. 파인튜닝에 수천 개의 예시가 필요한 반면, Few-shot은 3-5개로 충분합니다. 다만, 복잡한 추론이 필요한 작업에서는 Chain-of-Thought 프롬프팅과 결합하여 사용합니다. 프로덕션에서는 예시 선택을 동적으로 하는 Dynamic Few-shot 기법이 성능을 높입니다.
from openai import OpenAI
client = OpenAI()
# 1. Zero-shot: 예시 없이 직접 질문
def zero_shot_sentiment(text):
response = client.chat.completions.create(
model="gpt-4",
messages=[
{"role": "system", "content": "텍스트의 감성을 '긍정', '부정', '중립' 중 하나로 분류하세요."},
{"role": "user", "content": text}
]
)
return response.choices[0].message.content
# 2. Few-shot: 예시와 함께 질문
def few_shot_sentiment(text):
few_shot_examples = """
다음은 감성 분류 예시입니다:
텍스트: 이 제품 정말 최고예요! 강력 추천합니다.
감성: 긍정
텍스트: 배송이 너무 늦고 제품 상태도 별로였습니다.
감성: 부정
텍스트: 평범한 제품이네요. 가격 대비 적당합니다.
감성: 중립
텍스트: {text}
감성:"""
response = client.chat.completions.create(
model="gpt-4",
messages=[
{"role": "user", "content": few_shot_examples.format(text=text)}
],
max_tokens=10
)
return response.choices[0].message.content.strip()
# 3. Chain-of-Thought + Few-shot (복잡한 추론)
def few_shot_math_reasoning(problem):
prompt = """
문제를 단계별로 풀어주세요.
문제: 사과 5개가 있는데 3개를 먹고, 다음날 2개를 더 샀습니다. 몇 개가 있나요?
풀이:
1. 처음 사과: 5개
2. 3개를 먹음: 5 - 3 = 2개
3. 2개를 더 삼: 2 + 2 = 4개
답: 4개
문제: 철수는 1000원이 있습니다. 300원짜리 과자 2개를 사면 얼마가 남나요?
풀이:
1. 처음 금액: 1000원
2. 과자 2개 가격: 300 * 2 = 600원
3. 남은 금액: 1000 - 600 = 400원
답: 400원
문제: {problem}
풀이:"""
response = client.chat.completions.create(
model="gpt-4",
messages=[{"role": "user", "content": prompt.format(problem=problem)}],
temperature=0
)
return response.choices[0].message.content
# 4. Dynamic Few-shot: 쿼리와 유사한 예시 자동 선택
from sentence_transformers import SentenceTransformer
import numpy as np
class DynamicFewShot:
def __init__(self, examples):
self.examples = examples
self.encoder = SentenceTransformer('all-MiniLM-L6-v2')
self.example_embeddings = self.encoder.encode(
[ex['input'] for ex in examples]
)
def get_similar_examples(self, query, k=3):
query_embedding = self.encoder.encode([query])[0]
similarities = np.dot(self.example_embeddings, query_embedding)
top_indices = np.argsort(similarities)[-k:][::-1]
return [self.examples[i] for i in top_indices]
def generate(self, query):
similar_examples = self.get_similar_examples(query)
prompt = "예시:\n"
for ex in similar_examples:
prompt += f"입력: {ex['input']}\n출력: {ex['output']}\n\n"
prompt += f"입력: {query}\n출력:"
return prompt
# 사용 예시
print(few_shot_sentiment("이번 업데이트 정말 마음에 들어요!"))
print(few_shot_math_reasoning("책 3권이 각각 2000원입니다. 10000원으로 몇 권 살 수 있나요?"))
"고객 문의 자동 분류에 Few-shot을 쓰고 있는데, 예시 3개일 때보다 5개일 때 정확도가 8% 올랐습니다. 다만 토큰 비용이 늘어나서, 비용 최적화를 위해 Dynamic Few-shot으로 바꿔볼까 합니다. 쿼리와 비슷한 예시만 선택하면 3개로도 충분할 것 같아요."
"Zero-shot으로는 우리 도메인 용어를 잘 못 이해해서 Few-shot으로 바꿨더니 해결됐습니다. 예시에 도메인 특화 용어와 출력 형식을 명확히 보여주니까 모델이 패턴을 잘 따라해요. 파인튜닝 안 해도 되니까 개발 속도가 훨씬 빠릅니다."
"Few-shot Learning이 작동하는 이유에 대해 여러 가설이 있는데, 가장 유력한 건 예시가 모델의 출력 형식을 조건화한다는 것입니다. 흥미롭게도 예시의 레이블을 랜덤하게 바꿔도 성능이 크게 떨어지지 않는 경우가 있어서, 레이블보다 형식이 더 중요하다는 연구 결과도 있습니다."
Few-shot 예시의 순서가 성능에 영향을 줍니다. 일반적으로 쉬운 예시를 먼저, 어려운 예시를 나중에 배치하는 것이 좋습니다. 또한 예시의 형식(구분자, 줄바꿈 등)을 일관되게 유지하세요. 형식이 불규칙하면 모델이 패턴을 파악하기 어렵습니다.
예시가 많을수록 좋지만, 모델의 컨텍스트 길이 제한이 있습니다. 긴 예시를 많이 넣으면 실제 쿼리가 들어갈 공간이 부족해집니다. 예시는 간결하게 작성하고, 핵심만 포함하세요. GPT-4의 128K 컨텍스트에서도 효율적인 예시 설계가 중요합니다.
편향된 예시는 편향된 출력을 만듭니다. 분류 작업에서 특정 클래스 예시만 많으면 그 클래스로 편향됩니다. 각 클래스별로 균등하게 예시를 배치하고, 경계 사례(edge case)도 포함하세요. 다양한 형태의 입력을 보여주는 것이 일반화에 도움됩니다.