본문으로 이동
메뉴 여닫기
환경 설정 메뉴 여닫기
개인 메뉴 여닫기
로그인하지 않음
지금 편집한다면 당신의 IP 주소가 공개될 수 있습니다.
Contrastive learning; 대조 학습
비슷해야 할 쌍의 표현은 가깝게, 달라야 할 쌍의 표현은 멀게 만드는 손실로 표현을 학습하는 방법

대조 학습(contrastive learning)은 "무엇이 무엇과 같은가"만 정해 주면 레이블 없이도 쓸모 있는 표현(임베딩)을 학습할 수 있게 해 주는 학습 방법이다. 같은 사진을 두 번 변형한 것, 질문과 그 답이 든 문단, 이미지와 그 설명문처럼 서로 짝이 맞는 양성 쌍(positive pair)을 정하고, 짝이 아닌 나머지를 음성 예제(negative)로 삼아 둘을 구별하도록 인코더를 훈련한다.

개념의 큰 그림과 다른 자기 지도 학습 방법(마스크 예측, 비대조 방법, JEPA)과의 관계는 자기 지도 학습 문서에 있다. 이 문서는 손실 함수의 수식, 온도와 음성 예제의 역할, 하드 네거티브, SimCLR·MoCo·CLIP의 손실 차이, 그리고 실제 구현을 다룬다. 대조 학습은 이미지 표현 학습뿐 아니라 문장 임베딩, 밀집 검색, CLIP 같은 멀티모달 모델의 표준 학습 방법이다.

연도 방법 핵심
2006 대조 손실(contrastive loss) 쌍마다 "같음/다름" 레이블을 두고, 같으면 거리를 줄이고 다르면 일정 여유(margin) 이상 벌린다. 차원 축소용으로 제안되었다[1]
2015 트리플렛 손실(triplet loss) 기준(anchor), 양성, 음성 세 개를 묶어 "기준-양성 거리 + 여유 < 기준-음성 거리"가 되게 한다. FaceNet이 온라인 트리플렛 채굴과 함께 썼다[2]
2018 InfoNCE (CPC) 양성 하나를 여러 음성 사이에서 골라내는 분류 문제로 바꾼 손실. 대조 예측 부호화(CPC)에서 제안[3]
2019 MoCo 음성 예제를 큐에 쌓고 키 인코더를 이동 평균으로 갱신[4]
2020 SimCLR 큰 배치 안의 다른 이미지를 모두 음성으로 쓰는 NT-Xent 손실[5]
2020 DPR, SupCon 질문-문단 쌍으로 검색기 학습(DPR), 같은 클래스를 모두 양성으로 쓰는 지도 대조 학습(SupCon)
2021 CLIP, SimCSE 이미지-텍스트 쌍(CLIP), 드롭아웃만 다른 같은 문장 쌍(SimCSE)

대부분의 현대 대조 학습은 InfoNCE 계열 손실을 쓴다. 질의(앵커) 표현 q, 그 양성 k+, 음성 k1−,…,kK−가 있을 때

ℒInfoNCE=−log⁡exp⁡(sim(q,k+)/τ)exp⁡(sim(q,k+)/τ)+∑j=1Kexp⁡(sim(q,kj−)/τ)

이다. sim은 보통 L2 정규화한 벡터의 내적, 곧 코사인 유사도이고 τ는 온도(temperature)다. 식의 모양은 K+1개 후보 가운데 양성의 번호를 맞히는 소프트맥스 분류의 교차 엔트로피와 같다. 그래서 구현에서는 유사도 행렬을 로짓으로 놓고 정답 번호를 레이블로 주어 cross_entropy를 그대로 호출한다.

CPC 논문은 이 손실을 최소화하는 것이 두 관점 사이의 상호 정보량의 하한 I(q;k+)≥log⁡(K+1)−ℒInfoNCE를 높이는 것과 같다고 보였다.[3] 이 하한은 log⁡(K+1)을 넘을 수 없으므로, 음성 예제가 많을수록 더 많은 정보를 담은 표현을 요구할 수 있다. 큰 배치와 큰 음성 사전이 유리한 이론적 이유다.

정렬과 균일성

편집 원본 편집

왕(Tongzhou Wang)과 이솔라(Phillip Isola)는 대조 손실이 점근적으로 두 성질을 최적화한다는 것을 보였다.[6]

  • 정렬(alignment): 양성 쌍의 표현이 가깝다. 분자 항이 담당한다.
  • 균일성(uniformity): 정규화된 표현이 초구 표면에 고르게 퍼진다. 분모의 음성 항이 담당하며, 모든 입력이 한 점으로 모이는 표현 붕괴를 막는다.

두 지표를 직접 최적화해도 대조 학습과 비슷하거나 더 나은 하위 과제 성능이 나왔다. 문장 임베딩에서 SimCSE가 사전 학습 언어 모델의 한쪽으로 쏠린(비등방성) 임베딩 공간을 고르게 펴 준다고 설명한 것도 같은 관점이다.

온도 τ는 유사도 차이를 얼마나 날카롭게 볼지 정한다. τ가 작으면 소프트맥스가 뾰족해져 기준과 가장 비슷한 음성 몇 개가 손실과 기울기를 거의 독차지한다. 왕(Feng Wang)과 류(Huaping Liu)는 대조 손실이 어려운 음성에 더 큰 벌점을 주는 "난이도 인식(hardness-aware)" 손실이며 온도가 그 벌점의 세기를 조절한다는 것을 보였다. 온도가 너무 작으면 의미가 비슷한 샘플까지 무리하게 밀어내 의미 구조가 깨지고, 너무 크면 표현이 덜 분리되는 균일성-허용성 딜레마가 있다.[7]

실제로 쓰인 값은 방법마다 다르다.

방법 온도 비고
MoCo 0.07 InstDisc(Wu 외 2018)의 값을 따름[4]
SimCLR 0.1, 0.5 등 실험 배치 4096, 100에폭 선형 평가에서 L2 정규화와 τ=0.1 조합이 64.4%로 가장 좋았고, 정규화 없이 쓰면 크게 떨어졌다[5]
CLIP 학습 가능, 초깃값 0.07 로짓 배율이 100을 넘지 않도록 잘라 학습 불안정을 막음[8]
sentence-transformers MNRL 0.05 (scale=20) 라이브러리 기본값. 문서에 "scale = 1/temperature"로 적혀 있다[9]

음성 예제를 어디서 얻는가

편집 원본 편집

분모의 음성 예제 수와 질이 성능을 크게 좌우한다. 세 가지 공급 방식이 있다.

  • 배치 내 음성(in-batch negatives): 배치에 든 다른 샘플의 양성을 음성으로 재활용한다. 배치 크기가 N이면 추가 계산 없이 질의마다 N-1개의 음성이 생긴다. SimCLR, CLIP, DPR, sentence-transformers의 MultipleNegativesRankingLoss가 이 방식이다. 음성 수가 배치 크기에 묶이므로 SimCLR은 4096, CLIP은 32,768이라는 큰 배치를 썼다.[5][8]
  • 메모리 뱅크·큐: 과거 배치의 표현을 저장해 두고 음성으로 쓴다. MoCo는 크기 65,536의 큐를 쓰고, 큐의 표현이 너무 오래되어 어긋나지 않도록 키 인코더를 쿼리 인코더의 이동 평균(모멘텀 m=0.999)으로 천천히 갱신했다. 배치 크기와 음성 수를 떼어 놓은 것이 핵심이다.[4]
  • 캐시된 큰 배치: GPU 메모리에 다 올라가지 않는 큰 배치를, 임베딩만 먼저 계산하고 기울기를 나중에 조각별로 다시 계산하는 방식으로 흉내 낸다. sentence-transformers의 CachedMultipleNegativesRankingLoss가 이런 방식이다.

하드 네거티브

편집 원본 편집

하드 네거티브(hard negative)는 양성과 헷갈릴 만큼 기준과 비슷하지만 실제로는 정답이 아닌 음성이다. 무작위 음성은 대부분 너무 쉬워서 손실에 거의 기여하지 않으므로, 어려운 음성을 일부러 넣으면 결정 경계를 더 세밀하게 배운다.

  • 검색 모델: DPR은 배치 내 음성에 더해, 정답 문단은 아니지만 BM25 점수가 높은 문단을 질문마다 하나씩 하드 네거티브로 넣었다.[10] 이후 이미 학습한 검색기나 리랭커로 상위 후보를 뽑아 하드 네거티브를 채굴하는 방식이 표준이 되었다. 고려대 KURE-v1은 질의-문서-하드 네거티브 5개 형식의 한국어 데이터로 BGE-M3를 미세 조정했다.[11]
  • 문장 임베딩: 지도 SimCSE는 자연어 추론(NLI) 데이터에서 함의(entailment) 문장을 양성으로, 모순(contradiction) 문장을 하드 네거티브로 썼다.[12]
  • 레이블 없는 경우: 로빈슨(Robinson) 등은 기준과의 유사도에 따라 음성의 가중치를 높이는 방식으로, 레이블 없이도 난이도를 조절할 수 있는 하드 네거티브 표집법을 제안했다.[13]

하드 네거티브의 위험은 거짓 음성(false negative)이다. 채굴한 "어려운 음성"이 사실은 정답인 경우(레이블이 빠진 관련 문서, 같은 뜻의 다른 문장)가 많아, 그대로 밀어내면 모델이 오히려 나빠진다. 그래서 상위 몇 개는 건너뛰고 그 아래에서 고르거나, 리랭커 점수가 양성에 너무 가까운 후보는 빼는 식의 걸러내기를 한다.

대표 방법의 손실 비교

편집 원본 편집
방법 양성 쌍 음성 손실 형태 특징
SimCLR (NT-Xent) 같은 이미지를 두 번 증강 배치 안 다른 2(N-1)개 표현 2N개 표현 전체에서 자기 자신만 뺀 소프트맥스, 양쪽 방향 모두 계산 증강 조합과 투영 헤드가 중요, 큰 배치 필요[5]
MoCo 같은 이미지의 두 증강(쿼리, 키) 큐에 쌓인 과거 키 K개 쿼리 하나 대 (양성 1 + 큐 K개) InfoNCE 키 인코더는 기울기를 받지 않고 이동 평균으로만 갱신[4]
CLIP 이미지와 그 설명문 배치 안 다른 이미지·텍스트 N×N 유사도 행렬에서 행 방향(이미지→텍스트)과 열 방향(텍스트→이미지) 교차 엔트로피의 평균 온도도 학습, 서로 다른 두 인코더[8]
SupCon 같은 클래스의 모든 샘플 다른 클래스 샘플 기준마다 양성이 여러 개인 InfoNCE 레이블이 있을 때 교차 엔트로피 대신 쓸 수 있음[14]
DPR, MNRL 질문과 정답 문단 배치 안 다른 문단 + 하드 네거티브 질문 하나 대 (양성 + 배치 음성 + 하드 네거티브) InfoNCE 검색기·문장 임베딩 학습의 기본형[10]

SimCLR은 이 손실을 NT-Xent(normalized temperature-scaled cross entropy)라고 불렀다. 배치에 N개 이미지가 있으면 증강으로 2N개 표현이 생기고, 각 표현에 대해 짝 하나가 양성, 나머지 2(N-1)개가 음성이다.[5] CLIP 논문은 넘파이 비슷한 의사코드로 손실을 제시했는데, 두 인코더 출력을 정규화해 내적한 뒤 et를 곱해 로짓을 만들고, 정답을 np.arange(n)으로 두어 두 축 방향의 교차 엔트로피를 평균한다.[8]

아래는 PyTorch로 세 손실을 구현한 예다. 모두 "유사도 행렬을 로짓으로, 대각선 번호를 정답으로" 놓는 같은 틀을 쓴다(PyTorch 2.5에서 확인).

import torch
import torch.nn.functional as F

def info_nce(q, k, temperature=0.05, hard_neg=None):
    """q, k: (N, D). i번째 q의 양성은 i번째 k, 나머지 k는 배치 내 음성.
    hard_neg: (N, D) 질의마다 하나씩 붙인 하드 네거티브(선택)."""
    q = F.normalize(q, dim=-1)
    k = F.normalize(k, dim=-1)
    if hard_neg is not None:
        k = torch.cat([k, F.normalize(hard_neg, dim=-1)], dim=0)  # (2N, D)
    logits = q @ k.T / temperature                                 # (N, N) 또는 (N, 2N)
    labels = torch.arange(q.size(0), device=q.device)              # 정답은 대각선
    return F.cross_entropy(logits, labels)

def nt_xent(z1, z2, temperature=0.5):
    """SimCLR: 2N개 표현에서 자기 자신만 빼고 모두 후보로 쓴다."""
    z = F.normalize(torch.cat([z1, z2]), dim=-1)                   # (2N, D)
    sim = z @ z.T / temperature
    sim.fill_diagonal_(float("-inf"))                              # 자기 자신 제외
    n = z1.size(0)
    labels = torch.cat([torch.arange(n, 2 * n), torch.arange(0, n)])
    return F.cross_entropy(sim, labels)

def clip_loss(img, txt, logit_scale):
    """CLIP: 이미지→텍스트, 텍스트→이미지 교차 엔트로피의 평균.
    logit_scale은 log(1/τ)를 담은 학습 가능한 스칼라."""
    img, txt = F.normalize(img, dim=-1), F.normalize(txt, dim=-1)
    logits = logit_scale.exp().clamp(max=100) * img @ txt.T
    labels = torch.arange(img.size(0), device=img.device)
    return (F.cross_entropy(logits, labels) + F.cross_entropy(logits.T, labels)) / 2

구현할 때 자주 틀리는 점은 다음과 같다.

  • 정규화 누락: 정규화하지 않은 내적을 작은 온도로 나누면 로짓이 폭주한다. SimCLR 실험에서도 정규화 없이 쓴 경우 선형 평가 성능이 크게 낮았다.[5]
  • 분산 학습: 여러 GPU에서 배치 내 음성을 쓰려면 다른 GPU의 임베딩을 모아(all-gather) 분모에 넣어야 한다. 모으지 않으면 GPU당 배치만큼만 음성이 생긴다.
  • 배치 안 중복: 같은 문서가 한 배치에 두 번 들어가면 정답이 음성으로도 등장한다. 중복 제거나 마스킹이 필요하다.
  • 혼합 정밀도: 지수 함수 때문에 fp16에서 넘침이 나기 쉽다. 로짓 계산과 손실은 fp32로 하는 경우가 많다.

라이브러리를 쓰면 sentence-transformers의 losses.MultipleNegativesRankingLoss(model, scale=20.0)가 질문-정답 쌍(과 선택적 하드 네거티브 열)을 받아 위 info_nce와 같은 계산을 한다. 기본 유사도 함수는 코사인이며, 내적을 쓰려면 scale을 1로 두라고 안내한다.[9]

실무 선택 기준

편집 원본 편집
상황 권장
질문-문서 쌍이 있는 검색·임베딩 미세 조정 배치 내 음성 + 하드 네거티브 1~5개의 InfoNCE. 배치는 메모리가 허락하는 한 크게, 부족하면 캐시 방식
레이블이 전혀 없는 문장 비지도 SimCSE식(같은 문장을 드롭아웃만 바꿔 두 번 인코딩)
분류 레이블이 있는 데이터 SupCon 또는 그냥 교차 엔트로피. 레이블이 많고 깨끗하면 이득이 크지 않을 수 있다
이미지 자기 지도 학습 큰 배치가 가능하면 SimCLR류, 아니면 MoCo류, 음성 예제 관리가 부담이면 BYOL·DINO 같은 비대조 방법(자기 지도 학습 참고)
이미지-텍스트 CLIP식 대칭 손실. 배치 크기가 성능에 직접 영향
  • 음성 예제 의존: 좋은 성능에 큰 배치나 큰 큐가 필요해 계산 비용이 크다. 이 부담 때문에 음성 예제 없이 붕괴를 막는 비대조 방법이 나왔다.
  • 거짓 음성: 인스턴스 구별 목표는 같은 클래스의 다른 샘플까지 밀어낸다. 온도가 작을수록 심하다.[7]
  • 증강 설계 의존: 비전에서는 어떤 변형을 "같은 것"으로 볼지가 곧 학습되는 불변성을 정한다. 색을 바꾼 이미지를 양성으로 쓰면 색 정보에 둔감한 표현이 된다.
  • 지름길: 양성 쌍을 구별할 수 있는 쉬운 단서(같은 길이, 같은 출처의 서식)가 있으면 의미 대신 그 단서를 배운다.
  1. ↑ Raia Hadsell, Sumit Chopra, Yann LeCun, 〈Dimensionality Reduction by Learning an Invariant Mapping〉, CVPR 2006. DOI
  2. ↑ Florian Schroff, Dmitry Kalenichenko, James Philbin, 〈FaceNet: A Unified Embedding for Face Recognition and Clustering〉, CVPR 2015. arXiv:1503.03832
  3. ↑ 3.0 3.1 Aaron van den Oord, Yazhe Li, Oriol Vinyals, 〈Representation Learning with Contrastive Predictive Coding〉, 2018. arXiv:1807.03748
  4. ↑ 4.0 4.1 4.2 4.3 Kaiming He 외, 〈Momentum Contrast for Unsupervised Visual Representation Learning〉, CVPR 2020. arXiv:1911.05722
  5. ↑ 5.0 5.1 5.2 5.3 5.4 5.5 Ting Chen 외, 〈A Simple Framework for Contrastive Learning of Visual Representations〉, ICML 2020. arXiv:2002.05709
  6. ↑ Tongzhou Wang, Phillip Isola, 〈Understanding Contrastive Representation Learning through Alignment and Uniformity on the Hypersphere〉, ICML 2020. arXiv:2005.10242
  7. ↑ 7.0 7.1 Feng Wang, Huaping Liu, 〈Understanding the Behaviour of Contrastive Loss〉, CVPR 2021. arXiv:2012.09740
  8. ↑ 8.0 8.1 8.2 8.3 Alec Radford 외, 〈Learning Transferable Visual Models From Natural Language Supervision〉, ICML 2021. arXiv:2103.00020
  9. ↑ 9.0 9.1 sentence-transformers, MultipleNegativesRankingLoss 소스 코드
  10. ↑ 10.0 10.1 Vladimir Karpukhin 외, 〈Dense Passage Retrieval for Open-Domain Question Answering〉, EMNLP 2020. arXiv:2004.04906
  11. ↑ nlpai-lab/KURE-v1 모델 카드
  12. ↑ Tianyu Gao, Xingcheng Yao, Danqi Chen, 〈SimCSE: Simple Contrastive Learning of Sentence Embeddings〉, EMNLP 2021. arXiv:2104.08821
  13. ↑ Joshua Robinson 외, 〈Contrastive Learning with Hard Negative Samples〉, ICLR 2021. arXiv:2010.04592
  14. ↑ Prannay Khosla 외, 〈Supervised Contrastive Learning〉, NeurIPS 2020. arXiv:2004.11362