🤖 AI/ML

Zero-Shot Learning

제로샷 학습

예시 없이 새로운 작업을 수행하는 능력. 사전 학습된 지식만으로 일반화하는 AI 기술.

📖 상세 설명

Zero-Shot Learning(제로샷 학습)은 모델이 특정 작업에 대한 예시나 학습 데이터 없이 새로운 작업을 수행할 수 있는 능력을 말합니다. "제로"는 작업별 학습 예시가 0개라는 의미로, 모델이 사전 학습(pre-training) 과정에서 습득한 일반적인 지식만을 활용해 처음 보는 작업을 해결합니다.

이 개념은 2013년 컴퓨터 비전 분야에서 처음 제안되었으며, 본 적 없는 객체 클래스를 인식하는 문제에서 시작되었습니다. 이후 GPT-3(2020)가 등장하면서 LLM에서의 Zero-Shot 능력이 주목받기 시작했고, 프롬프트만으로 다양한 NLP 작업을 수행할 수 있다는 것이 입증되었습니다.

Zero-Shot의 핵심 원리는 시맨틱 공간(semantic space)에서의 지식 전이입니다. 모델은 대규모 데이터로 학습하면서 개념 간의 관계와 언어 패턴을 습득합니다. 새로운 작업이 주어지면, 이 일반적 지식을 활용해 작업의 의미를 이해하고 적절한 출력을 생성합니다. LLM에서는 "이 텍스트의 감정을 분류하세요"라는 지시만으로 감정 분석이 가능해집니다.

실무에서 Zero-Shot Learning은 레이블된 데이터가 부족하거나 빠른 프로토타이핑이 필요할 때 유용합니다. Few-Shot(소수 예시)이나 Fine-tuning(미세 조정) 대비 정확도는 낮을 수 있지만, 데이터 수집/라벨링 비용 없이 즉시 활용할 수 있는 장점이 있습니다. 특히 GPT-4, Claude 등 최신 LLM에서는 Zero-Shot 성능이 크게 향상되어 많은 작업에서 실용적인 수준에 도달했습니다.

💻 코드 예제

# Zero-Shot Learning 예제: 다양한 NLP 작업
from openai import OpenAI

client = OpenAI(api_key="your-api-key")

# Zero-Shot 감정 분석 (예시 없이 작업 수행)
def zero_shot_sentiment(text: str) -> str:
    response = client.chat.completions.create(
        model="gpt-4",
        messages=[
            {"role": "system", "content": "당신은 텍스트 감정 분석 전문가입니다."},
            {"role": "user", "content": f"""
다음 텍스트의 감정을 분석하세요.
긍정(positive), 부정(negative), 중립(neutral) 중 하나로 답하세요.

텍스트: {text}

감정:"""}
        ],
        max_tokens=10,
        temperature=0
    )
    return response.choices[0].message.content.strip()

# Zero-Shot 텍스트 분류 (커스텀 카테고리)
def zero_shot_classification(text: str, categories: list) -> str:
    category_str = ", ".join(categories)
    response = client.chat.completions.create(
        model="gpt-4",
        messages=[
            {"role": "user", "content": f"""
다음 텍스트를 아래 카테고리 중 가장 적합한 것으로 분류하세요.
카테고리: {category_str}

텍스트: {text}

선택한 카테고리 하나만 출력하세요:"""}
        ],
        max_tokens=20,
        temperature=0
    )
    return response.choices[0].message.content.strip()

# Hugging Face 모델을 활용한 Zero-Shot Classification
from transformers import pipeline

def zero_shot_with_huggingface(text: str, candidate_labels: list) -> dict:
    """
    Hugging Face의 zero-shot-classification 파이프라인 사용
    모델: facebook/bart-large-mnli (NLI 기반 분류)
    """
    classifier = pipeline(
        "zero-shot-classification",
        model="facebook/bart-large-mnli"
    )

    result = classifier(
        text,
        candidate_labels=candidate_labels,
        multi_label=False  # 단일 레이블 분류
    )

    return {
        "text": text,
        "predicted_label": result["labels"][0],
        "confidence": result["scores"][0],
        "all_scores": dict(zip(result["labels"], result["scores"]))
    }

# Zero-Shot vs Few-Shot 비교 함수
def compare_zero_few_shot(text: str, examples: list = None) -> dict:
    """
    Zero-Shot과 Few-Shot 결과를 비교합니다.
    examples: [{"text": "...", "label": "..."}] 형식의 예시 리스트
    """
    # Zero-Shot
    zero_shot_result = zero_shot_sentiment(text)

    # Few-Shot (예시가 있는 경우)
    if examples:
        example_str = "\n".join([
            f"텍스트: {e['text']}\n감정: {e['label']}"
            for e in examples
        ])

        response = client.chat.completions.create(
            model="gpt-4",
            messages=[
                {"role": "user", "content": f"""
텍스트의 감정을 분석하세요.

예시:
{example_str}

텍스트: {text}
감정:"""}
            ],
            max_tokens=10,
            temperature=0
        )
        few_shot_result = response.choices[0].message.content.strip()
    else:
        few_shot_result = None

    return {
        "text": text,
        "zero_shot": zero_shot_result,
        "few_shot": few_shot_result,
        "examples_count": len(examples) if examples else 0
    }

# 실행 예제
if __name__ == "__main__":
    # Zero-Shot 감정 분석
    result = zero_shot_sentiment("이 제품 정말 마음에 들어요! 배송도 빨랐어요.")
    print(f"감정: {result}")  # positive

    # Zero-Shot 커스텀 분류
    categories = ["기술", "스포츠", "정치", "연예", "경제"]
    text = "애플이 새로운 아이폰 발표회를 열었습니다."
    result = zero_shot_classification(text, categories)
    print(f"분류: {result}")  # 기술

    # Hugging Face Zero-Shot
    result = zero_shot_with_huggingface(
        "The stock market reached an all-time high today.",
        ["finance", "sports", "technology", "politics"]
    )
    print(f"HF 분류: {result['predicted_label']} ({result['confidence']:.2%})")

🗣️ 실무에서 이렇게 말하세요

💬 회의에서

"새로운 리뷰 카테고리 분류 모델을 만들어야 하는데, 라벨링된 데이터가 없어요." - "일단 Zero-Shot으로 시작해보죠. GPT-4나 Claude에 카테고리 목록을 주고 프롬프트만으로 분류해볼 수 있어요. 정확도가 85% 정도면 충분하다면 바로 프로덕션에 쓸 수도 있고, 부족하면 오분류된 케이스를 수집해서 Few-Shot이나 Fine-tuning으로 개선하면 됩니다."

💬 면접에서

"Zero-Shot과 Few-Shot Learning의 차이점을 설명해주세요." - "Zero-Shot은 작업별 예시 없이 프롬프트 지시만으로 수행하고, Few-Shot은 몇 개의 예시를 프롬프트에 포함해서 패턴을 보여주는 방식입니다. 일반적으로 Few-Shot이 정확도가 높지만, 프롬프트 토큰 수가 늘어나 비용이 증가해요. 작업 난이도와 예산을 고려해 선택합니다. 실제로 GPT-4 수준에서는 많은 기본 작업에서 Zero-Shot도 충분히 좋은 성능을 보여줍니다."

💬 기술 토론에서

"Hugging Face의 zero-shot-classification 파이프라인은 어떻게 동작하나요?" - "NLI(Natural Language Inference) 모델을 활용합니다. 입력 텍스트와 각 레이블을 전제-가설 쌍으로 변환해서, '이 텍스트는 스포츠에 관한 것이다'가 참인지 판단하는 식이에요. facebook/bart-large-mnli가 대표적인데, 영어에 최적화되어 있어서 한국어는 mDeBERTa 같은 다국어 모델을 쓰는 게 좋습니다."

⚠️ 흔한 실수 & 주의사항

복잡한 작업에 Zero-Shot 과신

도메인 특화 작업(법률 문서 분석, 의료 코드 분류 등)에서는 Zero-Shot 정확도가 50~60%에 그칠 수 있습니다. 높은 정확도가 필요하면 Few-Shot이나 Fine-tuning을 고려하세요.

프롬프트 설계 경시

Zero-Shot 성능은 프롬프트 품질에 크게 의존합니다. "분류하세요"보다 "다음 카테고리 중 가장 적합한 것을 선택하세요: A, B, C"처럼 구체적인 지시가 정확도를 높입니다.

올바른 접근 방법

Zero-Shot으로 빠르게 프로토타입을 만들고, 실제 오류 케이스를 분석하세요. 자주 틀리는 패턴이 있으면 그 예시들을 Few-Shot 프롬프트에 추가하거나, 충분한 데이터가 모이면 Fine-tuning으로 전환하는 점진적 접근이 효과적입니다.

🔗 관련 용어

📚 더 배우기