본 글은 제로샷 학습(Zero-Shot Learning)의 개념을 이해하고, 실제 예제 코드를 통해 이를 구현하는 방법을 설명합니다. 제로샷 학습이 무엇이고, 왜 중요한지를 Hugging Face를 이용해 얼마나 쉽게 활용할 수 있는지 다루도록 하겠습니다.
제로샷 학습이란 무엇인가?
전통적인 머신러닝 모델을 훈련시키는 방식으로 "암기 과목" 공부와 비슷합니다. 예를 들어 모델에게 "고양이"와 "개" 사진 1000장을 보여주며 "이건 고양이야, 이건 강아지야"라고 정답(Label)을 알려줍니다. 학습이 끝난 모델은 "고양이"와 "강아지"는 잘 구분하지만, 한 번도 본 적 없는 "코끼리" 사진을 주면 혼란에 빠집니다.
제로샷 학습은 이와는 정반대입니다. 이름 그대로, 0(Zero)개의 예시(Shot)만 보고도 문제를 푸는 방식입니다. 예를 들어 모델에게 "고양이"나 "강아지"라는 정답(Label) 자체를 가르친 적이 없습니다. 대신, 모델은 "언어"와 "이미지" 사이의 "관계"와 "개념"을 미리 학습합니다.
마치 우리가 "얼룩말"을 한 번도 본적이 없어도, "말이랑 비슷한데 몸에 검은 줄무늬가 있어"라는 설명만 듣고도 얼룩말을 알아볼 수 있는 것과 같습니다.
위에서 언급한 개념을 더 쉽게 이해하기 위해 "도서관 사서"로 비유해보겠습니다.
전통적인 사서 (훈련 필요)
이 사서는 "역사", "과학" 코너만 압니다.
새롭게 "경제" 책이 들어오면, 이 사서는 이 책을 어디에 둬야 할지 모릅니다. "경제" 코너를 새로 만들고, 어떤 책이 경제 책인지 수백 권의 예시를 보여주며 "다시 훈련(Fine-tuning)" 해야 합니다.
제로샷 사서 (훈련 불필요)
이 사서는 "역사", "과학" 코너를 암기한 것이 아니라, "책의 내용"과 "코너 이름(Label)"의 의미를 모두 이해하고 있습니다.
새로운 "경제" 책이 들어오면, 사서는 이 책을 읽어봅니다.
그리고 우리가 제시한 새로운 코너 이름(Lable)인 "경제"의 의미도 생각해봅니다.
사서는 이 책의 내용은 "경제"라는 단어의 의미와 매우 가깝다고 추론하고 책을 분류합니다.
이제 제로샷 학습에 대해서 이해가 되셨나요?
왜 이 학습법이 혁신적일까?
전통적인 AI 모델 구축의 가장 큰 병목은 "데이터 라벨링" 입니다. 수만, 수십만 개의 데이터에 일일이 정답을 매핑하는 작업은 시간과 비용이 엄청나게 듭니다.
제로샷은 이 문제를 해결합니다.
비용 절감: 데이터 라벨링 비용이 절감됩니다.
유연성: "정치", "사회"로 분류하던 모델을 "IT", "예술"로 분류하고 싶을 때, 모델을 재훈련할 필요 없이 Label 이름만 바꿔주면 됩니다.
신속성: 아이디어가 떠오른 즉시 프로토타입을 만들 수 있습니다.
제로샷 구현 예시
텍스트 분류
가장 기본적인 제로샷 텍스트 분류 예제를 살펴보겠습니다.
먼저 Hugging Face의 transformers 라이브러리를 설치합니다.
!pip install transformers
다음은 텍스트(sequence)와 후보 라벨(candidate_labels)만으로 분류를 수행하는 코드입니다.
from transformers import pipeline
classifier = pipeline("zero-shot-classification", model="MoritzLaurer/mDeBERTa-v3-base-mnli-xnli")
sequence_to_classify = "내일 중요한 축구 경기가 열린다고 한다."
candidate_labels = ["정치", "경제", "스포츠", "IT/기술"]
output = classifier(sequence_to_classify, candidate_labels, multi_label=False)
print(output)
위 코드를 실행하면 아래와 같은 결과가 나오게됩니다.
{'sequence': '내일 중요한 축구 경기가 열린다고 한다.',
'labels': ['스포츠', 'IT/기술', '정치', '경제'],
'scores': [0.9846686720848083, 0.008273092098534107,0.0036497144028544426, 0.003408558899536729]}
sequence: 원본 텍스트
labels: 점수가 높은 순서대로 정렬된 라벨 리스트
scores: 각 라벨 대한 신뢰도 점수(0~1)
"축구 경기"라는 텍스트가 "스포츠" 라벨과 가장 관련성(0.98)이 높다고 나옵니다. 위 모델은 정확하게 추론해냈습니다.
만약, 하나의 텍스트가 여러 개의 라벨에 속할 수 있다면, multi_label=True 옵션을 사용합니다.
from transformers import pipeline
classifier = pipeline("zero-shot-classification", model="MoritzLaurer/mDeBERTa-v3-base-mnli-xnli")
sequence_to_classify = "이 레스토랑은 음악은 훌륭하지만, 음식 맛은 평범했다."
candidate_labels = ["음식", "서비스", "음악", "가격"]
output = classifier(sequence_to_classify, candidate_labels, multi_label=True)
print(output)
위 코드를 실행하면 아래의 결과가 나오게됩니다.
{'sequence': '이 레스토랑은 음악은 훌륭하지만, 음식 맛은 평범했다.', 'labels': ['음악', '음식', '서비스', '가격'], 'scores': [0.9990034103393555, 0.9980430006980896, 0.9746165871620178, 0.48950350284576416]}
multi_label=True로 설정하면, 점수(scores)의 총합이 1이 되지 않습니다. 따라서 각 라벨이 독립적으로 "참일 확률"을 계산할 수 있습니다. 위 결과는 "음악"과 "음식" 모두에 관한 내용임을 추론한 것입니다.
이미지 분류
제로샷 개념은 텍스트에만 국한되지 않습니다. "개념"을 이해하는 모델이라면 이미지 분류나 객체 탐지에도 적용할 수 있습니다.
텍스트 분류가 NLI 모델을 기반으로 한다면, 이미지 분류는 CLIP(Contrastive Language Image Pre-training) 모델을 기반으로 합니다.
CLIP 모델은
인터넷에서 수집한(이미지, 이미지 설명 텍스트) 쌍 정보를 엄청나게 많이 학습한 모델입니다.
CLIP은 "고양이 사진"과 "고양이라는 텍스트"가 서로 "가까운" 개념임을 압니다.
from transformers import pipeline
from PIL import Image
import requests # URL에서 이미지를 불러오기 위해
# 1. 제로샷 '이미지' 분류 파이프라인 로드
# CLIP 모델을 명시적으로 지정해줍니다.
image_classifier = pipeline(
"zero-shot-image-classification",
model="openai/clip-vit-large-patch14"
)
# 2. 분류할 이미지 준비 (인터넷에서 고양이 사진 불러오기)
url = "https://images.unsplash.com/photo-1514888286974-6c03e2ca1dba"
image = Image.open(requests.get(url, stream=True).raw)
# 3. 후보 레이블 (텍스트로)
# 모델은 이 텍스트와 이미지의 '유사도'를 계산합니다.
labels = ["a photo of a cat", "a photo of a dog", "a photo of a car"]
# 4. 분류 실행
result = image_classifier(image, candidate_labels=labels)
pprint.pprint(result)
위 코드를 실행하면 아래의 결과가 나옵니다.
[{'score': 0.9979252815246582, 'label': 'a photo of a cat'}, {'score': 0.0012550547253340483, 'label': 'a photo of a dog'}, {'score': 0.0008196595590561628, 'label': 'a photo of a car'}]
모델은 이미지를 보고, 우리가 제시한 라벨 중 "a photo of a cat"이라는 설명과 이미지의 개념이 99.7% 일치한다고 판단했습니다.
객체 분류
이미지 전체를 분류하는 것을 넘어, 이미지 안의 특정 객체들을 텍스트로 찾아내는 것도 가능합니다.
from transformers import pipeline
from PIL import Image
import requests # URL에서 이미지를 불러오기 위해
# 1. 제로샷 '객체 탐지' 파이프라인 로드
object_detector = pipeline(
"zero-shot-object-detection",
model="google/owlvit-large-patch14"
)
# 2. (위와 동일한 고양이 이미지 사용)
url = "https://images.unsplash.com/photo-1514888286974-6c03e2ca1dba"
image = Image.open(requests.get(url, stream=True).raw)
# 3. 찾아내고 싶은 객체들의 이름 (텍스트)
labels_to_find = ["cat nose", "cat eyes", "remote control"]
# 4. 탐지 실행
result = object_detector(image, candidate_labels=labels_to_find)
print(result)
위 코드를 실행하면 아래의 결과나 나옵니다.
[{'score': 0.5476904511451721, 'label': 'cat nose', 'box': {'xmin': 2350, 'ymin': 1570, 'xmax': 2640, 'ymax': 1818}},
{'score': 0.3316132128238678, 'label': 'cat eyes', 'box': {'xmin': 2021, 'ymin': 1199, 'xmax': 2931, 'ymax': 1442}}, {'score': 0.31051504611968994, 'label': 'cat eyes', 'box': {'xmin': 2027, 'ymin': 1200, 'xmax': 2940, 'ymax': 1449}},
{'score': 0.29117435216903687, 'label': 'cat eyes', 'box': {'xmin': 2680, 'ymin': 1215, 'xmax': 2952, 'ymax': 1438}}, {'score': 0.24599002301692963, 'label': 'cat eyes', 'box': {'xmin': 2046, 'ymin': 1199, 'xmax': 2328, 'ymax': 1417}},
{'score': 0.17471081018447876, 'label': 'cat nose', 'box': {'xmin': 2336, 'ymin': 1601, 'xmax': 2644, 'ymax': 1821}}, {'score': 0.14712969958782196, 'label': 'cat eyes', 'box': {'xmin': 2679, 'ymin': 1215, 'xmax': 2953, 'ymax': 1450}},
{'score': 0.14246635138988495, 'label': 'cat eyes', 'box': {'xmin': 2018, 'ymin': 1200, 'xmax': 2332, 'ymax': 1435}}, {'score': 0.14067652821540833, 'label': 'cat eyes', 'box': {'xmin': 1985, 'ymin': 1186, 'xmax': 2983, 'ymax': 1478}},
{'score': 0.13866569101810455, 'label': 'cat eyes', 'box': {'xmin': 1765, 'ymin': 1098, 'xmax': 3168, 'ymax': 1572}}]
결론
이제까지 제로샷에 대해서 알아보았고, 장점과 한계에 대해서 다시 한번 살펴보겠습니다.
제로샷의 장점
데이터가 필요 없음
유연성: 비즈니스 요구사항이 변경되어 분류 카테고리를 늘려야 할 때, 재훈련없이 candidate_labels만 수정하면 됩니다.
프로토타이핑: "이런 분류가 어떨까?" 라는 아이디어를 검증하기 위해 간단히 테스트할 수 있습니다.
제로샷의 한계
정확도: 모든 것을 적당히 알지만, 한 분야의 "전문가" 보다는 못합니다. 만약 "고객 리뷰"에 대해 "긍정/부정"으로 분류하는 단 하나의 작업만 수행해야 한다면, 해당 작업에 특화된 데이터로 "파인 튜닝"한 모델이 제로샷 모델보다 좋습니다.
모호성: NLI 기반 모델은 라벨의 "단어 의미"에 크게 의존합니다. "IT, 기술" 처럼 의미가 비슷한 라벨이 함께 있으면 모델이 혼동합니다. 따라서 복잡한 분류는 어려울 수 있습니다.
속도 및 크기: 제로샷을 수행하는 NLI 모델이나 CLIP 모델은 크기가 매우 큽니다. 특화 모델보다 추론 속도가 느릴 수 있습니다.
제로샷 학습은 "모든 것을 대체하는" 만병 통치약은 아닙니다. 하지만 AI 개발의 패러다임을 바꾸는 강력한 도구이기에 아래의 상황에서 사용 하시기를 추천 드립니다.
초기 탐색 및 프로토타이핑: 어떤 종류의 데이터가 유입되는지, 어떤 분류가 의미 있을지 빠르게 탐색할 때 활용
데이터가 절대적으로 부족할 때: 라벨링된 데이터가 아예 없을 때 유일한 선택지
동적인 분류가 필요할 때: 분류 카테고리가 매일같이 바뀌는 환경일 때 (e.g. 실시간 뉴스 토픽 분류)
0 Comments:
댓글 쓰기