Field Log · Entry

Embedding 학습의 핵심: Contrastive Learning과 InfoNCE (3/14)

Anchor와 positive vector는 가까워지고 여러 negative vector는 멀어지며 temperature가 softmax 경계를 조절하는 contrastive embedding 학습

이번 글의 결론

  • Contrastive learning은 positive를 가깝게 하는 것만이 아니라, 같은 비교 집합의 negative보다 상대적으로 높은 score를 만들도록 학습합니다.
  • InfoNCE의 temperature와 batch composition은 model architecture만큼 중요합니다. 같은 loss 이름이어도 effective difficulty가 다르면 다른 공간이 만들어집니다.
  • In-batch negative는 싸고 강력하지만 다른 query의 positive가 내 query에도 negative라는 가정을 합니다. False negative가 있으면 큰 batch가 독이 될 수 있습니다.
  • Symmetric loss, multi-positive loss, hard-negative weight는 data의 관계 구조에 맞춰 선택합니다.
  • Loss 감소는 목적이 아닙니다. Held-out exact retrieval, geometry, slice metric을 함께 보고 학습을 멈춥니다.

앞 글에서는 vector space를 관찰했습니다. 이제 그 공간을 만드는 가장 널리 쓰이는 학습 원리를 살펴봅니다.


1. 분류가 아니라 상대 비교로 본다

Anchor query (q_i)와 positive document (d_i^+)가 있습니다. 같은 batch의 다른 document를 negative로 쓰면 model의 과제는 다음입니다.

q_i와 가장 잘 맞는 document는 d_i인가?

Score matrix:

          d1   d2   d3   d4
q1        +    -    -    -
q2        -    +    -    -
q3        -    -    +    -
q4        -    -    -    +

Diagonal score를 같은 행의 나머지보다 높이는 cross-entropy가 multiple-negatives ranking loss 또는 in-batch InfoNCE의 기본 형태입니다.

2. InfoNCE 수식

Normalized embedding과 cosine score를 쓴다고 합시다.

s_ij = cosine(fq(q_i), fd(d_j))

Query (i)가 자신의 positive (i)를 고를 확률:

p(i | q_i)
  = exp(s_ii / τ) / Σ_j exp(s_ij / τ)

Loss:

L_q→d = - (1/B) Σ_i log p(i | q_i)

(B)는 batch의 pair 수, (τ)는 temperature입니다.

3. Temperature는 난이도 증폭기다

예를 들어 positive score가 0.70, hard negative가 0.65라고 합시다.

τ = 1.0  → logits gap 0.05
τ = 0.05 → logits gap 1.00

작은 temperature는 작은 similarity 차이를 크게 증폭해 hard examples에 강한 gradient를 줍니다. 너무 작으면 mislabeled negative와 outlier가 학습을 지배하고 logit이 불안정해질 수 있습니다.

Temperature 선택은 다음과 얽힙니다.

  • normalized 여부
  • batch size와 negative 수
  • hard-negative 비율
  • label noise
  • model size
  • symmetric loss 여부

논문의 temperature 숫자만 복사하지 말고 dev retrieval로 조절합니다.

4. Batch Size가 중요한 이유

Batch가 (B)이면 각 query는 대략 (B-1)개의 in-batch negative를 봅니다.

B=32   → 31 negatives/query
B=1024 → 1023 negatives/query

큰 batch는 다양한 비교 대상을 주고 uniformity를 개선할 수 있습니다. 하지만:

  • GPU memory 증가
  • false-negative 확률 증가
  • easy negative만 늘어 실질 정보가 적을 수 있음
  • distributed all-gather 통신 증가
  • batch dataset mixture가 task prior를 바꿈

“큰 batch일수록 무조건 좋다”가 아니라 유효하고 정확한 negative가 얼마나 늘었는가를 봅니다.

5. Symmetric Loss

Document도 query를 고르게 만들 수 있습니다.

L = 0.5 × (L_q→d + L_d→q)

Paraphrase·image-text처럼 관계가 대칭이면 자연스럽습니다. 검색처럼 여러 query가 같은 document를 positive로 가질 수 있는 비대칭 task에서는 reverse direction의 one-to-one 가정이 부적절할 수 있습니다.

6. Multi-positive InfoNCE

한 query에 positive가 여러 개라면 diagonal 하나만 정답으로 두지 않습니다.

P_i = set of positive document indices for q_i

L_i = -log (
  Σ_{j∈P_i} exp(s_ij/τ)
  / Σ_k exp(s_ik/τ)
)

문서의 여러 chunk, paraphrase, 번역문이 positive라면 다른 positive를 서로 밀어내지 않게 합니다.

Graded Relevance

Grade를 soft target으로 바꿀 수 있습니다.

target_ij = softmax(gain(label_ij) / τ_label)
prediction_ij = softmax(score_ij / τ_model)
L = cross_entropy(target, prediction)

Binary pair보다 partial relevance를 보존합니다.

7. Explicit Hard Negative를 추가한다

Batch의 positive document 외에 query별 hard negative (h_{i1}…h_{im})을 넣습니다.

candidates(q_i)
  = batch positives
  + BM25 hard negatives
  + dense-mined hard negatives

Hard negative가 너무 많으면 query별 candidate 수가 달라지고 memory가 커집니다. 유형별 quota와 weight를 둡니다.

negative_mix:
  in_batch: all_valid
  random: 1
  bm25_hard: 2
  dense_hard: 3
  adversarial: 1

8. Margin-based Loss와 차이

Triplet margin loss:

L = max(0, m - s(q,d+) + s(q,d-))

Positive가 negative보다 margin (m)만큼 높아지면 gradient가 0이 됩니다.

장점:

  • 한 pair의 상대 순서를 명확히 학습
  • score scale 해석이 단순
  • hard pair 중심 curriculum에 편함

단점:

  • negative 하나만 보면 batch 정보 활용이 낮음
  • margin tuning 필요
  • 많은 easy triplet은 학습 signal이 없음

InfoNCE와 margin loss 중 이름으로 고르기보다 candidate structure와 label 형태로 고릅니다.

9. Regression·Classification Objective

STS처럼 human similarity score (y)가 있으면 cosine regression을 쓸 수 있습니다.

L = (cos(f(x1), f(x2)) - y)²

Pair classification은 두 vector의 concat·difference·product를 classifier에 넣을 수 있습니다. 하지만 downstream에서 cosine만 쓸 예정이라면 classifier head만 좋아지고 metric space는 약할 수 있습니다.

train-time head와 serving-time similarity가 같은가?

항상 확인합니다.

10. Self-supervised SimCSE

Unsupervised SimCSE는 같은 문장을 dropout mask만 다르게 두 번 encoding해 positive를 만듭니다.

x --dropout mask A--> z
x --dropout mask B--> z+
other sentences       --> negatives

별도 text augmentation 없이 dropout이 최소 perturbation 역할을 합니다. 논문은 dropout을 제거하면 collapse가 발생했다고 보고했습니다.

Supervised SimCSE는 NLI의 entailment pair를 positive, contradiction을 hard negative로 사용했습니다. 여기서 배울 점은 label ontology가 geometry를 만든다는 것입니다.

11. Distributed In-batch Negatives

GPU마다 local batch가 64이고 GPU 8개라면 all-gather로 512 document를 negative pool로 쓸 수 있습니다.

# concept only: autograd-aware gather가 필요할 수 있다.
all_docs = distributed_gather(local_doc_embeddings)
logits = query_embeddings @ all_docs.T / temperature
loss = cross_entropy(logits, global_positive_indices)

주의:

  • gather가 gradient를 전달하는지
  • positive index offset이 정확한지
  • duplicate document를 negative로 두지 않는지
  • 서로 다른 task batch가 충돌하지 않는지
  • 마지막 uneven batch 처리

World size를 바꾸면 effective negative 수가 바뀌므로 같은 실험이 아닙니다.

12. Batch Composition은 암묵적인 Label이다

한 batch에 같은 topic의 문서가 많으면 fine-grained distinction을 배웁니다. 서로 무관한 task만 섞으면 easy separation을 배울 수 있습니다.

homogeneous batch:
  hard, but false-negative risk high

heterogeneous batch:
  diverse, but many easy negatives

Multi-task model은 dataset별 batch, mixed batch, temperature sampling을 비교합니다. 큰 dataset이 작은 고품질 task를 압도하지 않도록 sampling probability를 기록합니다.

13. Loss 구현의 수치 안정성

Softmax를 직접 exponentiate하지 않고 library cross entropy를 씁니다.

import torch
import torch.nn.functional as F

def in_batch_loss(query_embeddings, document_embeddings, temperature=0.05):
    q = F.normalize(query_embeddings, dim=-1)
    d = F.normalize(document_embeddings, dim=-1)
    logits = q @ d.T / temperature
    labels = torch.arange(logits.size(0), device=logits.device)
    return F.cross_entropy(logits, labels)

Mixed precision에서는 너무 작은 temperature로 logit magnitude가 커지는지 확인합니다.

14. 무엇을 Logging할까

training_step:
  loss: 1.84
  positive_similarity_mean: 0.71
  hardest_negative_similarity_mean: 0.64
  positive_rank_mean: 2.3
  top1_batch_accuracy: 0.62
  temperature: 0.05
  effective_negatives_per_query: 511
  false_negative_filtered: 27
  embedding_norm_p50: 1.0

Loss만 보면 positive와 negative가 함께 커지는 이상을 놓칠 수 있습니다.

15. 최소 Ablation Grid

temperature ∈ {0.02, 0.05, 0.1}
batch size   ∈ {64, 256, 1024 effective}
loss         ∈ {q→d, symmetric}
negatives    ∈ {in-batch, +BM25, +dense-mined}
normalize    ∈ {official, opposite for diagnosis}

한 번에 한 축만 바꾸고 같은 candidate corpus에서 exact retrieval을 평가합니다.

16. 학습 중단 기준

Training loss가 계속 내려가도 OOD retrieval은 나빠질 수 있습니다.

checkpoint selection:
  primary: in-domain nDCG@10
  guardrail: OOD BEIR/MMTEB slice
  guardrail: false-negative-sensitive set
  geometry: hubness / norm drift

가장 낮은 train loss가 아니라 목적에 맞는 held-out metric으로 고릅니다.

스스로 확인하기

  1. Temperature를 작게 하면 hard negative와 label noise에 대한 gradient가 어떻게 바뀌는가?
  2. Batch size를 늘렸는데 성능이 떨어질 수 있는 이유는 무엇인가?
  3. Asymmetric retrieval에서 symmetric loss가 항상 적절하지 않은 이유는 무엇인가?
  4. Multi-positive loss가 필요한 data 구조는 무엇인가?
  5. Training loss 외에 positive rank와 hubness를 관찰하면 어떤 실패를 찾을 수 있는가?

다음 글에서는 실제 성능을 좌우하는 positive definition, hard-negative mining, false-negative 정제와 data split을 설계합니다.

참고자료