← 모델 목록
수업 실습 2026-10-07 · image-text-matching
CLIP 계열 (이미지-텍스트 대조학습)

openai/clip-vit-base-patch32

CLIP ViT-B/32 이미지-텍스트 매칭 (수업 실습)
모델
이미지와 텍스트를 같은 임베딩 공간에 매핑해 유사도를 계산하는 OpenAI의 이미지-텍스트 모델 (ViT-B/32)
사용 목적
학습 없이 텍스트 라벨로 이미지를 분류(zero-shot)하고, 텍스트로 이미지 폴더를 검색하는 방법을 익히려고 사용
코드
mnmms/data-analysis
가중치
clip-vit-base-patch32 HF Hub
학습 시간없음
추론 CPU / GPU측정 안 함

데이터

  • 추론만 · 분류 이미지 1장 (sit.jpg)
  • 검색 대상 옷 이미지 5장 (images/clothes)

학습

  • 학습 없음 · 사전학습 가중치
  • 분류는 CPU, 검색은 GPU (RTX 4070 Laptop)

결과

  • 분류: sitting 0.523 · standing 0.451 · running 0.025
  • 검색 "a black shirt" Top-3 = image3 · image5 · image4
  • 정량 지표 없음

배운 점

  • softmax라 확률 합 = 1 (SigLIP2는 sigmoid)
  • torch.no_grad()로 추론 시 그래디언트 계산 생략
  • 이미지·텍스트 벡터를 미리 만들어 두고 코사인 유사도로 검색
개요용도 의도한 용도: 클래스 학습 없이 텍스트 라벨( "a person sitting" 등)로 이미지를 분류하고, 텍스트 질의로…

용도

  • 의도한 용도: 클래스 학습 없이 텍스트 라벨("a person sitting" 등)로 이미지를 분류하고, 텍스트 질의로 이미지 폴더에서 비슷한 이미지를 찾는 흐름 익히기
  • 대상 사용자: 해당 없음 (학습용)
  • 의도하지 않은 용도: 정확도 근거로서의 모델 선정. 정답 라벨로 평가하지 않았고 이미지가 1장(분류), 5장(검색)뿐임

모델 정보

항목 값
베이스 모델 Hugging Face openai/clip-vit-base-patch32 (CLIPModel, CLIPProcessor)
크기 · 변형 base, patch 32. 가중치 텐서 398개(노트북 출력 Loading weights 0/398). 파라미터 수 · 파일 크기 [미확인] (노트북에 출력 없음)
리비전 revision은 지정하지 않음 ([미확인]). transformers 5.19.0
아키텍처 이미지 인코더(ViT) + 텍스트 인코더(Transformer)를 각각 projection해 같은 차원의 벡터로 만들고 내적으로 유사도 계산. 세부 차원은 [미확인]
학습 방식 학습하지 않음. 사전학습 가중치로 추론만
프롬프트 · 에이전트 구성 분류 라벨 3개: "a person standing", "a person sitting", "a person running". 검색 질의: "a black shirt" (top_k=3)
데이터학습·평가 데이터셋은 없고, 추론에 쓴 입력만 있습니다. 확보 방식 해당 없음 (수업 자료 이미지로 추론만) 출처 분류: 로컬…

학습·평가 데이터셋은 없고, 추론에 쓴 입력만 있습니다.

항목 값
확보 방식 해당 없음 (수업 자료 이미지로 추론만)
출처 분류: 로컬 images/sit.jpg. 검색: 로컬 images/clothes/image1~5.jpg. 두 이미지 묶음의 원출처·저작권은 [미확인]
직접 수집 내용 해당 없음
이용 조건 확인 [미확인] (수업 자료로 받은 이미지, 원본 사이트 약관 확인 안 함)
규모 분류 이미지 1장 + 라벨 3개 / 검색 대상 이미지 5장 + 질의 1개
분할 해당 없음
레이블·클래스 분포 해당 없음 (라벨은 텍스트 3개를 직접 지정)
전처리 CLIPProcessor가 리사이즈·정규화 (pixel_values), 텍스트는 토큰화 (input_ids, attention_mask)
개인정보·민감정보 처리 sit.jpg에 사람이 있음. 레포에는 이 사진의 그림을 넣지 않음. 검색 결과 그림(옷 이미지)만 둠
학습학습을 하지 않았으므로 하이퍼파라미터·에폭·학습 시간은 해당 없음 입니다. 하이퍼파라미터 해당 없음 (추론 설정: 텍스트 pa…

학습을 하지 않았으므로 하이퍼파라미터·에폭·학습 시간은 해당 없음입니다.

항목 값
하이퍼파라미터 해당 없음 (추론 설정: 텍스트 padding=True, 검색은 torch.no_grad())
에폭 / 스텝 해당 없음
학습 시간 해당 없음
하드웨어 분류 실습: 모델을 .to(device)로 옮기지 않아 CPU. 검색 실습: device = cuda (이 컴퓨터의 NVIDIA GeForce RTX 4070 Laptop 8188MiB)
프레임워크 transformers 5.19.0, huggingface-hub 1.33.0, PyTorch 2.14.1+cu126 (uv.lock 기준)
시드 · 재현 방법 노트북을 위에서부터 실행. 모델 첫 로드 시 다운로드됨
결과Top-1: image3 Top-2: image5 Top-3: image4 정량 지표 없음. 정답 라벨로 정확도를 재지 않고 …
Top-1: image3
Top-1: image3
Top-2: image5
Top-2: image5
Top-3: image4
Top-3: image4

정량 지표 없음. 정답 라벨로 정확도를 재지 않고 점수와 순위를 눈으로만 확인했습니다.

실습 입력 결과 비교 대상
분류 (softmax) sit.jpg standing 0.4514 · sitting 0.5233 · running 0.0253 → a person sitting 해당 없음
분류 (logits) sit.jpg 25.2555 / 25.4033 / 22.3729 해당 없음
검색 (코사인 유사도) "a black shirt", 이미지 5장 image1 0.2236 · image2 0.2327 · image3 0.2827 · image4 0.2399 · image5 0.2430 → Top-3 = image3, image5, image4 해당 없음

검색 결과 (Top-1 → Top-3 순서, 질의 "a black shirt"):

추론 성능 (CPU / GPU)

측정 안 함. 지연 시간·처리량·메모리를 재는 코드가 노트북에 없습니다. infer_ms는 넣지 않았습니다.

장비 장비 이름 배치 크기 지연 시간 (샘플당, p50 / p95) 처리량 (샘플/초) 메모리 사용
CPU [미확인] - 측정 안 함 측정 안 함 측정 안 함
GPU NVIDIA GeForce RTX 4070 Laptop 8GB 1 측정 안 함 측정 안 함 측정 안 함
한계 · 배운 점한계 알려진 실패 유형: 분류에서 standing(25.26)과 sitting(25.40)의 logit 차이가 작아 확률이 0…

한계

  • 알려진 실패 유형: 분류에서 standing(25.26)과 sitting(25.40)의 logit 차이가 작아 확률이 0.45 / 0.52로 붙어 있음. 프롬프트를 바꿔 비교하지 않음 ([미확인]). [🚩AI 설명] 라벨 문구에 민감할 수 있음
  • 코드 주의: 검색 셀의 model.text_model(..., attension_mask=...)는 인자 이름 오타임. [🚩AI 설명] 마스크가 적용되지 않았을 수 있고, 질의가 1개라 패딩이 없어 결과에는 영향이 없을 것으로 보지만 확인하지 않음 [미확인]
  • 환경 문제: safetensors 버전 비교 오류(found=None)와 huggingface-hub 의존성 충돌이 있어 uv pip install --reinstall safetensors, uv remove huggingface-hub 등으로 정리했다고 노트북에 메모
  • 편향 / 공정성 이슈: [미확인]
  • 성능이 떨어지는 입력 조건: [미확인] (이미지 1장, 5장만 확인)

배운 점

  • CLIP은 텍스트 축에 softmax를 걸어 확률의 합이 1이 된다. [🚩AI 설명] 라벨이 하나만 맞아도 다른 라벨에 확률이 나눠지고, "어느 것도 아님"을 표현하기 어렵다
  • 추론에서는 torch.no_grad()로 그래디언트 계산을 막아 리소스를 줄인다
  • 검색은 이미지 폴더를 한 번만 벡터화해 두고 질의 텍스트 벡터와의 코사인 유사도로 순위를 매기면 된다. [🚩AI 설명] 벡터를 L2 정규화해야 내적 = 코사인 유사도
  • 같은 실습을 SigLIP2로도 했다: 점수 방식(sigmoid)과 벡터화 함수가 달라진다 (20261007-image-text-matching-siglip2). [🚩AI 설명] 질의와 이미지가 서로 달라 점수를 직접 비교할 수는 없다
  • [🚩AI 설명] 다음에 해 볼 것: 정답 라벨이 있는 이미지 묶음에서 CLIP과 SigLIP2의 정확도·속도를 같은 조건으로 비교
사용 방법코드 셀 5개
In [1]모델 불러오기
from transformers import CLIPProcessor, CLIPModel

model = CLIPModel.from_pretrained("openai/clip-vit-base-patch32")
processor = CLIPProcessor.from_pretrained("openai/clip-vit-base-patch32")
Out[1] 출력 보기
Loading weights:   0%|          | 0/398 [00:00<?, ?it/s]
In [2]이미지-텍스트 입력 만들기
from PIL import Image

image = Image.open("images/sit.jpg")
classes = ["a person standing", "a person sitting", "a person running"]

inputs = processor(text=classes, images=image, return_tensors="pt", padding=True)
print(inputs.keys())
Out[2] 출력 보기
KeysView({'input_ids': tensor([[49406,   320,  2533,  2862, 49407],
        [49406,   320,  2533,  4919, 49407],
        [49406,   320,  2533,  2761, 49407]]), 'attention_mask': ..., 'pixel_values': ...})
In [3]zero-shot 분류
import torch

with torch.no_grad():
    outputs = model(**inputs)
    logits_per_image = outputs.logits_per_image
    probs = logits_per_image.softmax(dim=1)
    print(probs)
    print(classes[probs[0].argmax()])
Out[3] 출력 보기
tensor([[0.4514, 0.5233, 0.0253]])
a person sitting
In [4]이미지 폴더 벡터화
device = "cuda" if torch.cuda.is_available() else "cpu"
model = CLIPModel.from_pretrained("openai/clip-vit-base-patch32").to(device)

image_features = []
for file_path in file_path_list:  # images/clothes 안의 jpg·png 5장
    image = Image.open(file_path)
    inputs = processor(images=image, return_tensors="pt").to(device)
    with torch.no_grad():
        feature = model.vision_model(pixel_values=inputs["pixel_values"]).pooler_output
        feature = model.visual_projection(feature)
        feature /= feature.norm(dim=1, keepdim=True)
    image_features.append(feature.to("cpu"))

image_features = torch.cat(image_features, dim=0)
In [5]텍스트 질의로 검색
query = "a black shirt"
top_k = 3

inputs = processor(text=[query], return_tensors="pt").to(device)
with torch.no_grad():
    text_feature = model.text_model(input_ids=inputs["input_ids"], attension_mask=inputs["attention_mask"]).pooler_output
    text_feature = model.text_projection(text_feature)
    text_feature /= text_feature.norm(dim=1, keepdim=True)

similarity = (image_features @ text_feature.to("cpu").T).squeeze(1)
top_indices = similarity.argsort(descending=True)[:top_k]
print(similarity)
print(top_indices)
Out[5] 출력 보기
tensor([0.2236, 0.2327, 0.2827, 0.2399, 0.2430])
tensor([2, 4, 3])

같은 과제·데이터셋 비교

같은 과제·데이터셋으로 학습한 모델이 생기면 여기에서 비교됩니다.