Accepted for 13-class training

ADR-0005: Training Config v2

작성일: 2026-05-14 · 범위: MobileCLIP2-S4 학습 하이퍼파라미터 4건 변경 · 선행: ADR-0004

Decision

fold0 4-class 학습(fingerprint c95c8a5e) 분석 결과, 13-class 확장 학습(fingerprint 3bd290fc)에 다음 4가지를 변경한다. 각 변경은 독립적이며, 문제 발생 시 개별 롤백 가능하다.

  1. Batch size 8 → 14 per GPU (effective 32 → 56)
  2. LR scheduler: constant → linear warmup 2 epochs + cosine decay (min ratio 0.01)
  3. Augmentation: crop scale 0.65 → 0.80, RandAugment magnitude 7 → 5
  4. Class imbalance: 미처리 → sqrt-weighted CrossEntropyLoss

추가로 evaluate()에 per-class precision/recall/f1과 confusion matrix 출력을 추가한다.

1. Batch Size 증가

항목v1v2
batch_size_per_gpu814
effective batch (4 GPU DDP)3256
클래스당 배치 내 평균 샘플2.54.3

ArcFace는 배치 내에서 클래스 간 angular margin을 계산한다. 배치가 작으면 일부 클래스가 배치에서 빠져 gradient가 noisy해진다. MobileNetV4 paper (Qin et al., 2024)에서 ArcFace 계열 학습 시 effective batch 64 이상을 권장한다. P100 16GB에서 MobileCLIP2-S4 + image_size 224 + FP16 AMP 기준 peak VRAM은 약 12-13GB로 batch 14가 안전 범위.

2. Cosine LR Scheduler + Warmup

항목v1v2
scheduler없음 (constant)cosine annealing
warmup없음2 epochs linear (0.01 → 1.0)
min LR ratio0.01
backbone 최종 LR1e-5 (고정)1e-7
head 최종 LR1e-4 (고정)1e-6

Loshchilov & Hutter (2017) "SGDR"에서 cosine annealing이 constant LR 대비 일관되게 더 좋은 generalization을 보여줬다. 이후 DINOv2, MAE, CLIP, MobileCLIP2 모두 cosine schedule을 기본으로 사용한다.

Warmup은 Goyal et al. (2017) "Accurate, Large Minibatch SGD"에서 제안됐다. Pretrained weight를 fine-tune할 때 초기 큰 gradient가 representation을 망가뜨리는 것을 방지한다. fold0 4-class 학습에서 epoch 1 val_top1이 0.64로 시작한 것이 warmup 부재의 증거. 2 epoch warmup이면 13-class trainval 3,788장 기준 약 540 steps (batch 56 × 4 GPU 기준 ~68 steps/epoch).

구현: step-level LambdaLR. warmup 구간은 linear 0.01→1.0, 이후 cosine으로 1.0→0.01.

3. Augmentation 완화

항목v1v2
RandomResizedCrop min_scale0.650.80
RandAugment magnitude75
RandAugment num_ops22 (유지)

랜드마크 인식은 건물의 global structure(전체 외형, 지붕선, 기둥 배치)가 핵심 단서다. scale 0.65는 이미지의 35%를 잘라내므로 건물 자체가 프레임에서 사라질 수 있다. He et al. (2022) "MAE"에서 fine-grained recognition task에서는 crop을 보수적으로 쓸 것을 권장한다.

RandAugment magnitude 7은 ImageNet 1000-class 대규모 학습에 맞춰진 값이다. 4,000장 13-class 소규모 데이터셋에서는 과도한 augmentation이 학습 불안정을 유발할 수 있다. Touvron et al. (2022) "DeiT III"에서 소규모 fine-tuning 시 magnitude 5-6을 권장한다.

4. Class Imbalance 보정

항목v1v2
class balance없음sqrt-weighted CrossEntropyLoss
최대 클래스changgyeonggung 505장
최소 클래스gwanghwamun 44장 (11.5배 차이)

Cui et al. (2019) "Class-Balanced Loss Based on Effective Number of Samples"에서 1/sqrt(n) weighting이 inverse weighting보다 안정적이고 majority class 성능을 크게 해치지 않으면서 minority class를 끌어올린다고 보고했다.

구현은 학습 환경에 따라 분기한다. 두 방식 모두 sqrt 비율을 적용하지만, 동시에 적용하면 minority class가 이중 보정되어 over-fit한다.

환경적용 방식이유
DDP (multi-GPU) DistributedSampler (uniform) + CrossEntropyLoss(weight=class_weights_tensor) WeightedRandomSampler는 DDP에서 직접 지원하지 않는다. loss weight로 동등 효과.
Single GPU (디버깅) WeightedRandomSampler(sqrt) + CrossEntropyLoss(weight=None) loss weight 미적용. 환경 간 결과 일관성 유지를 위해 sampler 한 종류만 사용.

gwanghwamun(44장)의 weight는 changgyeonggung(505장) 대비 약 3.4배. 이는 "gwanghwamun 1장 틀리면 changgyeonggung 3.4장 틀린 것과 같은 loss"를 의미한다.

yaml 키: class_balance_strategy: "sqrt_weighted" (또는 "inverse_weighted", "none").

5. Per-Class Metric 추가

evaluate() 함수가 sklearn classification_report와 confusion_matrix를 반환한다. metrics.json에 test_per_class, test_macro_f1, test_confusion_matrix가 기록된다.

Consequences

References