수달이네 기술 블로그

5. CLIP모델과 UMAP을 이용한 차원축소 시각화 본문

AI공부/멀티모달

5. CLIP모델과 UMAP을 이용한 차원축소 시각화

슬픈 수달이 2026. 3. 17. 14:13

복습(CLIP구조)

CLIP은 인코더 두 개(텍스트-transformer, 비전ViT)가 대비학습을 하며 학습하는 구조

import torch
import umap
import matplotlib.pyplot as plt
from matplotlib.offsetbox import OffsetImage, AnnotationBbox

import numpy as np
from PIL import Image
from transformers import CLIPProcessor, CLIPModel
from datasets import load_dataset

모델, 프로세서

model = CLIPModel.from_pretrained('openai/clip-vit-base-patch32')
processor = CLIPProcessor.from_pretrained('openai/clip-vit-base-patch32')

model: 클립 모델을 hugging face에서 불러온다

processor: 마찬가지로 CLIP모델에 맞는 processor를 넣어준다.

  • 모델에 데이터를 넣을 때 형식이 맞춰져야한다(전처리 필요)
  • 그 전처리를 모델에 맞게 해주는 객체가 processor안에 들어있다.

임베딩 함수

def get_clip_embeddings(images, texts):
    inputs = processor(text = texts, images = images, return_tensors= 'pt', padding=True, truncation=True)
    with torch.no_grad():
        print(inputs)
        #pixel_values [B, 3, 224, 224]
        vision_out = model.vision_model(pixel_values = inputs['pixel_values'])
        print(vision_out)
        #image_out [B, 512]
        image_embeds = model.visual_projection(vision_out.pooler_output)
        text_out = model.text_model(input_ids = inputs['input_ids'], attention_mask = inputs['attention_mask'])
        text_embeds = model.text_projection(text_out.pooler_ooutput)
    return image_embeds.cpu().numpy(), text_embeds.cpu().numpy()

processor속성

  • text: 텍스트 넣어줌
  • image: 이미지를 넣어줌
  • return_tensors: 텐서 형식(pt = pytorch형 / tf = tensorflow / np = numpy)
  • padding: 합성곱 연산 시 길이 맞추기
  • truncation: 사전 설정한 모델 최대 길이(77토큰)을 초과하면 잘라줌.

→inputs = 전처리 이후 나온 값.

with torch.no_grad(): 추론 모델 즉, 미분 계산을 하지 않음.(테스트)

  • model.vision_model: 결과 중에 이미지 입력(pixel_values)만 받아, 이미지 특징 벡터를 뽑아낸다. 입력 → [배치크기, 3, 224, 224]
    • 키가 pixel_values로 되어있음.
  • vision_out.pooler_output: 해당 특징 벡터로 이미지 전체를 임베딩 한다.
  • vision_projection: 모델에 잘 넣을 수 있게 크기를 맞춰준다(텍스트 임베딩과 크기를 맞춤) 출력 → [배치크기, 512]
  • text out: vision과 마찬가지로 텍스트 출력을 뽑아낸후,
    • attention_mask를 이용해 불필요한 패딩 토큰을 없앤다.(padding mask)
  • text_embeds: 이미지와 같은 크기가 된다.

데이터셋

https://huggingface.co/datasets/clip-benchmark/wds_flickr8k

  • flickr8k 데이터셋을 가져오는데 clipbenchmark한 걸 가져온다.
  • 위처럼 이미지-텍스트(이미지를 설명하는 문장)데이터셋이다.
    • CLIP학습처럼 웹에서 추출함.
dataset = load_dataset('clip-benchmark/wds_flickr8k')
train_dataset = dataset['test'] # 학습용이 아니라 일반화가 잘 되는지 확인만
train_dataset

# Dataset({
#     features: ['__key__', '__url__', 'jpg', 'txt'],
#     num_rows: 1000
# })
  • 데이터셋을 위처럼 가져와 준다.
sample_size = 100
subset = train_dataset.select(range(sample_size))

images = list(subset['jpg'])
captions = list(subset['txt'])
image_embeds, text_embeds = get_clip_embeddings(images, captions)
  • 전체 이미지, 텍스트가 임베딩되어 저장된다.
all_embeds = np.concatenate([image_embeds,text_embeds], axis=0)

이미지 임베딩과 텍스트 임베딩을 행으로 연결해 준다.

UMAP적용, 시각화

umap_model = umap.UMAP(n_neighbors=15, min_dist=0.1, metric = 'cosine')
reduce_embeds = umap_model.fit_transform(all_embeds)
  • 임베딩 한 결과에 UMAP을 적용, 결과를 시각화 할 수 있도록 해준다.
image_coords = reduce_embeds[:sample_size]
text_coords = reduce_embeds[sample_size:]
fig, ax = plt.subplots(figsize=(30,30))
ax.scatter(text_coords[:,0], text_coords[:, 1], color = 'red', label='Captions',alpha=0.5)

def plot_with_images(ax, coords, images, captions, is_text=False):
    for i, (x,y)in enumerate(coords):
        if is_text:
            ax.text(x,y, str(captions[i])[:30], fontsize = 8, color='red', ha='right')
        else:
            img = images[i].resize((64,64))
            imagebox = OffsetImage(img, zoom=1.0)
            ab = AnnotationBbox(imagebox, (x,y), frameon=False)
            ax.add_artist(ab)

plot_with_images(ax, image_coords, images, captions, is_text=False)

all_coords=np.vstack([image_coords, text_coords])
x_min, y_min = all_coords.min(axis = 0)
x_max, y_max = all_coords.max(axis = 0)
pad_x = (x_max - x_min) * 0.05
pad_y = (y_max - y_min) * 0.05
ax.set_xlim(x_min - pad_x, x_max + pad_x)
ax.set_ylim(y_min - pad_y, y_max + pad_y)

ax.legend()
plt.tight_layout()
plt.savefig('test.png', dpi=200)
plt.show(

  • 이미지, 텍스트의 임베딩을 출력한다.
  • 비슷한 문장끼리 임베딩 공간에 있고,
  • 비슷한 이미지끼리 임베딩 공간에 있다.
    • 이미지 그룹에서도 가까운게 가까운 의미를 가진다.