토니의 연습장

BLIP / CLIP 본문

언어 AI (NLP)/Multimodal (MLLM, LMM)

BLIP / CLIP

bellmake 2025. 7. 17. 15:17

BLIP과 CLIP이 서로 다른 방식으로 유사도를 계산하는 주요 이유는 모델 구조학습 목표의 차이에서 비롯됩니다.

  1. BLIP(ITM) – Image–Text Matching Head
    • BLIP은 사전학습 단계에서 이미지–텍스트 매칭(Image–Text Matching, ITM) 태스크를 추가로 학습합니다.
    • use_itm_head=True일 때는, 이미지와 텍스트를 함께 입력해 매칭 여부(positive/negative) 를 분류하는 분류기 헤드(logits) 를 돌려줍니다.
    • 반면 use_itm_head=False로 설정하면, 내부에서 추출된 이미지·텍스트 임베딩을 꺼내와 (정규화된) 내적 또는 코사인 유사도 형태로 반환합니다.
    • 즉, ITM 헤드를 사용하면 “이 쌍이 매칭(올바른 캡션)”인지에 대한 분류 확신도를, 헤드를 쓰지 않으면 순수 임베딩 유사도를 얻을 수 있습니다.
  2. CLIP – Contrastive Embedding Alignment
    • CLIP은 이미지 인코더와 텍스트 인코더를 대조 학습(contrastive learning) 방식으로 함께 훈련하여, 두 임베딩을 동일한 잠재공간(shared latent space)에 정렬합니다.
    • 학습 시 양(positive) 쌍음(negative) 쌍을 구분하기 위해 코사인 유사도(cosine similarity) 를 손실 함수로 직접 사용합니다.
    • 따라서 추론 단계에서는, 이미지와 텍스트 임베딩을 L2 정규화(unit‑norm) 한 뒤 내적(dot product) 만으로 코사인 유사도를 구하면 됩니다.
  3. 요약 비교
BLIP (ITM)CLIP
학습 목표 매칭 분류(ITM 헤드) + 생성/대조 학습 순수 대조 학습(이미지↔텍스트 정렬)
유사도 계산 방식 - ITM 헤드: 분류 로짓  
 
  • 헤드 미사용: 임베딩 내적 또는 코사인 유사도 | L2 정규화된 임베딩 간 내적 = 코사인 유사도 |
    | 입력 처리 방식 | 이미지+텍스트를 동시에 모델에 입력 | 이미지 인코더·텍스트 인코더 분리 실행 |
    | 반환 형태 | (batch_size,) 매칭 점수 벡터 | (batch_size, dim) 임베딩 → (batch, batch) 유사도 행렬 |

  • BLIP은 “이 이미지와 이 텍스트가 얼마나 잘 맞는가”를 판별하도록 특화된 헤드가 있고, 필요시 헤드를 끄고 간단한 임베딩 유사도로도 사용할 수 있습니다.
  • CLIP은 처음부터 이미지와 텍스트 임베딩 간 코사인 유사도를 직접 최적화하도록 설계되어, 별도의 매칭 헤드 없이 내적 방식으로 유사도를 구합니다.

이처럼 모델의 설계 철학과 학습 방식이 달라서, 각각의 유사도 계산 방법도 자연스럽게 다르게 구현되는 것입니다.

 

 

 

 


  • 모델 학습 목표의 차이
    • BLIP은 이미지–텍스트 매칭(ITM) 태스크와 생성 학습을 함께 수행하도록 설계되었습니다. ITM 헤드를 사용하면 “이 이미지와 이 텍스트가 올바르게 매칭되는가”를 분류하는 로짓(logits)을 반환합니다.
    • 반면 CLIP은 이미지 인코더와 텍스트 인코더를 대조 학습(contrastive learning) 방식으로 훈련해, 양(positive) 쌍과 음(negative) 쌍을 구분하도록 코사인 유사도를 직접 최적화합니다.
  • 유사도 계산 방식의 차이
    • BLIP에서 use_itm_head=True일 때는 매칭 확신도를 나타내는 분류 점수를, use_itm_head=False일 때는 헤드 직전의 임베딩 벡터를 꺼내와 벡터 내적 또는 코사인 유사도(별도 정규화 시) 형태로 반환합니다.
    • CLIP은 기본적으로 L2 정규화된(unit‑norm) 임베딩을 반환하므로, 이들을 내적(dot product)하기만 해도 곧바로 코사인 유사도에 해당합니다.
  1. ITM 헤드를 끈 BLIP과 CLIP이 완전히 동일한가?
    • 두 모델 모두 “벡터 내적”을 통해 유사도 성분을 계산할 수 있지만, 자동 정규화 여부임베딩 공간의 분포가 다르기 때문에 동일하다고 보긴 어렵습니다.
      1. 정규화 여부
        • CLIP 임베딩은 ‖v‖₂ = 1이 보장되므로, 내적(dot) 연산이 곧바로 코사인 유사도입니다.
        • BLIP(use_itm_head=False) 임베딩은 정규화가 적용되지 않을 수 있어, 단순 내적은 “스케일된 유사도 점수”가 됩니다.
      2. 임베딩 공간의 차이
        • 두 모델은 서로 다른 데이터와 목적을 갖고 학습되었으므로, 같은 텍스트·이미지 쌍이라도 임베딩 벡터의 분포와 스케일이 다릅니다.
        • 따라서 숫자 자체를 비교하기보다는, 각 모델 내에서 순위(rank)나 Top‑K 성능으로 평가해야 합니다.
  2. BLIP 임베딩도 코사인 유사도로 사용하고 싶을 때
    • BLIP 임베딩에 대해서도 코사인 유사도를 정확히 계산하려면, 벡터를 수동으로 L2 정규화하신 후 내적을 적용하시면 됩니다.
     
# 예시 코드
img_norm = blip_image_embeds / np.linalg.norm(blip_image_embeds, axis=1, keepdims=True)
txt_norm = blip_text_embeds  / np.linalg.norm(blip_text_embeds,  axis=1, keepdims=True)
cosine_sim = np.dot(img_norm, txt_norm.T)

이렇게 하면 “정규화된 벡터 간 코사인 유사도”라는 의미론적 계산 방식은 CLIP과 동일해집니다.


정리하자면,

  • ITM 헤드를 끈 BLIP과 CLIP 모두 벡터 내적 기반의 유사도를 반환할 수 있지만,
  • CLIP은 기본적으로 단위 정규화된 임베딩을 사용해 진짜 코사인 유사도를,
  • BLIP은 별도 정규화가 필요할 수 있는 스케일된 점수를 제공합니다.
  • 필요에 따라 BLIP 임베딩도 수동 L2 정규화를 거치면, CLIP과 동일한 방식의 코사인 유사도로 활용할 수 있습니다.
 

 

import torch
import torch.nn.functional as F
from transformers import BlipProcessor, BlipForImageTextRetrieval
from transformers import CLIPProcessor, CLIPModel

from PIL import Image
from tqdm import tqdm
import os
import numpy as np
from sklearn.metrics.pairwise import cosine_similarity
from datasets import load_dataset


device = 'cuda' if torch.cuda.is_available() else 'cpu'

# BLIP-ITM 모델 로드
blip_processor = BlipProcessor.from_pretrained("Salesforce/blip-itm-base-coco")
blip_model = BlipForImageTextRetrieval.from_pretrained("Salesforce/blip-itm-base-coco").to("cuda")


# CLIP 모델 및 프로세서 로드
clip_model = CLIPModel.from_pretrained("openai/clip-vit-base-patch32")
clip_processor = CLIPProcessor.from_pretrained("openai/clip-vit-base-patch32")


def evaluate_retrieval(similarity_matrix, top_k=[1, 5, 10]):
    """Top-K 검색 정확도를 계산하는 함수"""
    num_samples = similarity_matrix.shape[0]
    correct_ranks = []

    for i in range(num_samples):
        sorted_indices = np.argsort(similarity_matrix[i])[::-1]
        rank = (sorted_indices == i).nonzero()[0]  # 정답 이미지의 랭킹
        correct_ranks.append(rank)

    results = {f"Top-{k}": sum(r < k for r in correct_ranks) / num_samples for k in top_k}
    return results


def get_blip_itm_scores(images, texts):
    inputs = blip_processor(images, texts, padding=True, return_tensors="pt").to("cuda")
    with torch.no_grad():
        # itm_scores = blip_model(**inputs)[0]
        cosine_score = blip_model(**inputs, use_itm_head=False)[0]
    # return itm_scores, cosine_score
    return cosine_score


def get_clip_embeddings(images, texts):
    inputs = clip_processor(text=texts, images=images, return_tensors="pt", padding=True, truncation=True)
    with torch.no_grad():
        image_embeds = clip_model.get_image_features(pixel_values=inputs["pixel_values"]).cpu().numpy()
        text_embeds = clip_model.get_text_features(input_ids=inputs["input_ids"], attention_mask=inputs["attention_mask"]).cpu().numpy()
    return image_embeds, text_embeds


dataset = load_dataset("clip-benchmark/wds_flickr8k")['test']

sample_size = 100  # 사용할 샘플 개수
subset = dataset.shuffle().select(range(sample_size))

# 이미지와 캡션 추출
images = subset['jpg']
captions = subset["txt"]

blip_similarity_matrix = get_blip_itm_scores(images, captions)
blip_similarity_matrix = blip_similarity_matrix.cpu().numpy()

# OpenCLIP 유사도 계산 (배치 연산 적용)
clip_image_embeddings, clip_text_embeddings = get_clip_embeddings(images, captions)
clip_similarity_matrix = np.dot(clip_image_embeddings, clip_text_embeddings.T)  # Cosine similarity


# 검색 성능 평가
print("\nBLIP Retrieval Performance:")
blip_results = evaluate_retrieval(blip_similarity_matrix)
for k, v in blip_results.items():
    print(f"{k}: {v.item():.4f}")

print("\nCLIP Retrieval Performance:")
clip_results = evaluate_retrieval(clip_similarity_matrix)
for k, v in clip_results.items():
    print(f"{k}: {v.item():.4f}")
print('----------')

 

'언어 AI (NLP) > Multimodal (MLLM, LMM)' 카테고리의 다른 글

Text-to-Image  (0) 2025.08.08
Multimodal 분기 처리  (0) 2025.07.23
Multimodal LoRA  (0) 2025.07.23
MLLM 구현  (0) 2025.05.26
MLLM / LMM  (0) 2025.04.07