Skip to main content

대조 학습 (Contrastive Learning)

학습 목표

  • 대조 학습의 핵심 아이디어와 양성/음성 쌍 개념을 이해한다
  • InfoNCE Loss의 수학적 구조를 설명할 수 있다
  • SimCLR의 자기 지도 학습 프레임워크를 이해한다
  • CLIP의 멀티모달 대조 학습 방식을 안다

왜 중요한가

대조 학습(Contrastive Learning)은 레이블 없이 의미적으로 유사한 데이터는 가깝게, 다른 데이터는 멀게 배치하는 표현을 학습합니다. 자기 지도 학습(Self-Supervised Learning)의 핵심 패러다임이며, CLIP, Sentence-BERT, E5 등 현대 임베딩 모델의 학습 기반입니다.

핵심 아이디어

용어설명예시
앵커(Anchor)기준 샘플고양이 이미지
양성 쌍(Positive)앵커와 유사한 샘플같은 고양이의 다른 뷰
음성 쌍(Negative)앵커와 다른 샘플자동차 이미지

InfoNCE Loss

대조 학습의 표준 손실 함수입니다. 양성 쌍의 유사도를 최대화하고, 음성 쌍의 유사도를 최소화합니다. LInfoNCE=logexp(sim(zi,zj)/τ)k=12N1[ki]exp(sim(zi,zk)/τ)\mathcal{L}_{\text{InfoNCE}} = -\log \frac{\exp(\text{sim}(z_i, z_j) / \tau)}{\sum_{k=1}^{2N} \mathbb{1}_{[k \neq i]} \exp(\text{sim}(z_i, z_k) / \tau)}
  • zi,zjz_i, z_j: 양성 쌍의 임베딩
  • τ\tau: 온도 파라미터(Temperature) — 분포의 날카로움 조절
  • sim\text{sim}: 코사인 유사도
import torch
import torch.nn.functional as F

def info_nce_loss(features, temperature=0.07):
    """InfoNCE Loss 구현

    Args:
        features: (2N, dim) — 양성 쌍이 연속으로 배치
                  [z_1, z_1', z_2, z_2', ..., z_N, z_N']
        temperature: 온도 파라미터
    """
    batch_size = features.shape[0] // 2

    # 정규화
    features = F.normalize(features, dim=1)

    # 유사도 행렬 (2N x 2N)
    similarity_matrix = torch.matmul(features, features.T) / temperature

    # 양성 쌍 마스크: (i, i+N) 과 (i+N, i) 가 양성 쌍
    labels = torch.cat([
        torch.arange(batch_size, 2 * batch_size),
        torch.arange(batch_size)
    ]).to(features.device)

    # 자기 자신과의 유사도 제거 (대각선)
    mask = torch.eye(2 * batch_size, dtype=torch.bool).to(features.device)
    similarity_matrix.masked_fill_(mask, float('-inf'))

    # CrossEntropy로 InfoNCE 계산
    loss = F.cross_entropy(similarity_matrix, labels)
    return loss

온도 파라미터의 역할

τ\tau효과결과
작음 (0.01)분포가 날카로움어려운 음성 쌍에 집중
보통 (0.07)균형 잡힌 학습일반적으로 사용
큼 (1.0)분포가 부드러움균등한 학습

SimCLR (2020)

Google의 Chen et al.이 제안한 자기 지도 대조 학습 프레임워크입니다. 하나의 이미지에서 두 가지 증강(Augmentation)을 적용하여 양성 쌍을 만듭니다.
import torch
import torch.nn as nn
import torchvision.transforms as T

class SimCLR(nn.Module):
    """SimCLR 프레임워크"""
    def __init__(self, base_encoder, projection_dim=128):
        super().__init__()
        self.encoder = base_encoder  # 예: ResNet-50 (fc 제거)
        encoder_dim = 2048  # ResNet-50 출력 차원

        # 프로젝션 헤드 (학습 시에만 사용)
        self.projector = nn.Sequential(
            nn.Linear(encoder_dim, encoder_dim),
            nn.ReLU(),
            nn.Linear(encoder_dim, projection_dim),
        )

    def forward(self, x):
        h = self.encoder(x)          # 표현 (다운스트림 사용)
        z = self.projector(h)         # 프로젝션 (학습 시에만 사용)
        return h, z


# SimCLR 데이터 증강 파이프라인
class SimCLRAugmentation:
    """하나의 이미지에서 두 개의 증강 뷰 생성"""
    def __init__(self, size=224):
        self.transform = T.Compose([
            T.RandomResizedCrop(size, scale=(0.2, 1.0)),
            T.RandomHorizontalFlip(),
            T.RandomApply([T.ColorJitter(0.4, 0.4, 0.4, 0.1)], p=0.8),
            T.RandomGrayscale(p=0.2),
            T.GaussianBlur(kernel_size=23, sigma=(0.1, 2.0)),
            T.ToTensor(),
            T.Normalize(mean=[0.485, 0.456, 0.406],
                        std=[0.229, 0.224, 0.225]),
        ])

    def __call__(self, x):
        return self.transform(x), self.transform(x)
SimCLR에서 프로젝션 헤드는 학습 시에만 사용됩니다. 다운스트림 태스크에서는 프로젝션 헤드를 제거하고, 인코더의 표현 hh를 직접 사용합니다. 프로젝션 헤드가 증강에 의한 불변성 정보를 흡수하여, 인코더 표현이 더 풍부한 의미 정보를 유지합니다.

CLIP (2021)

OpenAI의 Radford et al.이 제안한 멀티모달 대조 학습 모델입니다. 이미지와 텍스트를 같은 임베딩 공간에 매핑합니다.

CLIP의 대조 학습

배치 내 NN개의 (이미지, 텍스트) 쌍에서:
  • 양성 쌍: 매칭되는 이미지-텍스트 (NN개)
  • 음성 쌍: 매칭되지 않는 이미지-텍스트 (N2NN^2 - N개)
import torch
import torch.nn.functional as F

def clip_loss(image_features, text_features, temperature=0.07):
    """CLIP 대조 손실 (간소화 버전)

    Args:
        image_features: (N, dim) 이미지 임베딩
        text_features: (N, dim) 텍스트 임베딩
        temperature: 학습 가능한 온도 파라미터
    """
    # 정규화
    image_features = F.normalize(image_features, dim=1)
    text_features = F.normalize(text_features, dim=1)

    # 유사도 행렬 (N x N)
    logits = torch.matmul(image_features, text_features.T) / temperature

    # 대각선이 양성 쌍 → labels = [0, 1, 2, ..., N-1]
    labels = torch.arange(logits.shape[0]).to(logits.device)

    # 이미지→텍스트 + 텍스트→이미지 양방향 손실
    loss_i2t = F.cross_entropy(logits, labels)
    loss_t2i = F.cross_entropy(logits.T, labels)

    return (loss_i2t + loss_t2i) / 2

CLIP의 제로샷 분류

CLIP은 학습하지 않은 클래스도 텍스트 프롬프트로 분류할 수 있습니다.
# CLIP 제로샷 분류 (OpenAI clip 라이브러리)
# import clip
# model, preprocess = clip.load("ViT-B/32", device="cuda")
#
# image = preprocess(image).unsqueeze(0).to("cuda")
# text = clip.tokenize(["고양이", "강아지", "자동차"]).to("cuda")
#
# with torch.no_grad():
#     image_features = model.encode_image(image)
#     text_features = model.encode_text(text)
#     similarity = (image_features @ text_features.T).softmax(dim=-1)
#     print(f"예측: {similarity}")  # 가장 높은 유사도 클래스 선택

대조 학습 변형 비교

방법양성 쌍 생성음성 쌍모달리티대표 모델
SimCLR데이터 증강배치 내 다른 샘플단일 (이미지)SimCLR, BYOL
CLIP이미지-텍스트 매칭배치 내 비매칭멀티모달CLIP, SigLIP
Sentence-BERT문장 쌍 라벨배치 내 다른 문장단일 (텍스트)SBERT, E5

실무 활용

학습 방식활용연결 탭
자기 지도 사전학습레이블 없이 범용 표현 학습Fine-Tuning
멀티모달 정렬이미지-텍스트 검색, 제로샷 분류Vision
임베딩 모델 학습시맨틱 검색, RAG 리트리버RAG
대조 학습(SimCLR, CLIP)은 판별적(Discriminative) 표현을 학습하고, 생성 모델(GPT, MAE)은 생성적(Generative) 사전학습을 합니다. 대조 학습은 유사도 기반 태스크(검색, 분류)에 강하고, 생성 모델은 텍스트/이미지 생성에 강합니다. 최근에는 두 방식을 결합하는 연구도 활발합니다.

참고 논문

논문학회/연도핵심 기여
A Simple Framework for Contrastive Learning - SimCLR (Chen et al.)ICML 2020자기 지도 대조 학습 프레임워크
Learning Transferable Visual Models From Natural Language Supervision - CLIP (Radford et al.)ICML 2021이미지-텍스트 멀티모달 대조 학습
Representation Learning with Contrastive Predictive Coding - CPC (van den Oord et al.)2018InfoNCE Loss 제안

체크리스트

  • 양성 쌍과 음성 쌍의 역할을 설명할 수 있다
  • InfoNCE Loss의 구조와 온도 파라미터의 역할을 안다
  • SimCLR의 데이터 증강 기반 자기 지도 학습을 이해한다
  • CLIP의 멀티모달 대조 학습과 제로샷 분류를 설명할 수 있다

다음 문서