Training Runbook

작성일: 2026-05-13 · 최신 표시: 2026-06-13 · 대상: Ubuntu GPU 서버

현재 문서 상태

이 문서는 Sprint 1 초기에 작성한 학습 운영 초안이다. 당시에는 학습 코드가 아직 고정되지 않았고, 학생 모델 후보와 ONNX 변환 절차를 정리하는 목적이 컸다. 현재 최신 실험 실행 기준은 Sprint 2 논문식 실험 매트릭스landmark-assistant-model-ver2 repo의 config/스크립트를 따른다. 이 문서는 이전 운영 의사결정과 체크리스트를 보존하는 legacy runbook으로 관리한다.

Runbook 목적

이 문서는 초기 학습 착수 전 운영 절차를 보존한다. 현재는 학습 코드가 landmark-assistant-model-ver2로 분리되었고, 앱 전달 기준은 Model Serving Contract의 MobileCLIP2-S3 FP16 mixed image/text encoder bundle이다. 앱 팀이 UI와 상세정보 DB를 담당하므로, 모델 팀은 앱 팀이 바로 붙일 수 있는 ONNX artifact와 JSON output contract를 고정한다. 학습 서버는 8 × NVIDIA Tesla P100 PCIe 16GB 기준으로 운용한다. 모델 후보와 설정값 탐색은 2026.05 기준 MobileNetV4, MobileCLIP2, EfficientNet, ConvNeXt 계열을 포함한다.

0. Server 확인

nvidia-smi
python --version
python -c "import torch; print(torch.__version__, torch.cuda.is_available(), torch.cuda.device_count())"
df -h
free -h

확인해야 할 값은 GPU 모델명, 장당 VRAM, CUDA/driver 버전, 사용 가능한 디스크 용량이다. P100은 BF16을 기대하지 않고, FP32 smoke 후 FP16 AMP를 사용한다.

1. Dataset Snapshot

학습은 Google Drive를 mount해서 직접 읽지 않는다. 오늘 학습 착수 기준의 권장 경로는 버전명을 붙인 압축본을 서버 로컬 디스크로 직접 다운로드한 뒤 압축을 풀고, 그 snapshot을 학습 입력으로 고정하는 것이다.

방식 사용 시점 주의점
versioned archive 직접 다운로드 오늘 학습 착수 기본값. landmark_dataset_20260513_v1.tar.zst 같은 단일 파일로 고정한다. 압축 전후 file count, labels.json hash, archive checksum을 반드시 저장한다.
rclone 반복 동기화, 부분 갱신, 대용량 재시도 자동화가 필요할 때 사용한다. 초기 OAuth 또는 service account 설정이 필요하다.
Google Drive shared zip 도구 설치 없이 빠르게 한 번 받을 때 사용한다. Drive의 자동 zip은 큰 폴더에서 분할/실패/파일명 문제를 만들 수 있어 직접 만든 archive보다 약하다.
Drive mount 학습 입력으로는 사용하지 않는다. I/O가 느리고 연결 실패가 학습 실패로 이어질 수 있다. 데이터 확인용으로만 제한한다.

스냅샷 후 반드시 저장할 것: dataset version name, archive checksum, class count, image count, labels.json hash, split manifest. 학습은 /data/landmark-assistant/Datasets/landmark-vYYYYMMDD 같은 로컬 SSD/NVMe 경로에서만 실행한다. 현재 프로젝트 표준 폴더명은 Dataset이다.

/data/landmark-assistant/Dataset/
  cheongwadae/
    labels.json
    images/
  naksan_park/
    labels.json
    images/
  mmca_seoul/
    labels.json
    images/

1.5 Model Search Plan 생성

학습 전 experiments/model_search_space.json을 기준으로 phase별 실행 config를 생성한다. 이 단계는 후보와 설정값을 문서가 아니라 실행 가능한 JSON으로 고정하기 위한 gate다.

python scripts/generate_model_search_plan.py
find experiments/generated_model_search -name "*.json" | sort

서버 학습 후에는 W&B에서 내려받은 metrics 또는 각 run directory의 metrics JSON을 모아 scripts/rank_model_runs.py로 best candidate를 정렬한다. ranking은 val_top3_accuracy를 최우선으로 보고, ONNX export 성공, latency, model size를 함께 확인한다.

python scripts/rank_model_runs.py --runs runs --out runs/model_ranking.json

2. Baseline Evaluation

학습 전 dataset layout을 검사하고 master manifest를 생성한다.

python scripts/audit_dataset_layout.py --root /data/landmark-assistant/Dataset
python scripts/build_master_labels.py \
  --root /data/landmark-assistant/Dataset \
  --out /data/landmark-assistant/Dataset/labels_master.json
python scripts/create_dataset_splits.py \
  --labels /data/landmark-assistant/Dataset/labels_master.json \
  --out /data/landmark-assistant/Dataset/splits/split_seed20260513.json
  1. confirmed 이미지만 train/val/test split 생성.
  2. DINOv3 frozen visual encoder와 SigLIP2 frozen image-text encoder를 각각 평가.
  3. train split으로 class prototype 생성.
  4. val/test image를 prototype과 cosine similarity로 검색.
  5. Top-1, Top-3 Accuracy, Recall@K, confusion matrix 저장.
  6. negative set이 있으면 reject AUROC, coverage@accuracy, Top1/Top2 margin threshold 저장.

이 단계는 학습이 아니라 baseline이다. baseline 숫자 없이 fine-tuning 결과를 성공으로 주장하지 않는다.

2.5 Canary Gates

  1. 1 batch overfit: 작은 batch 하나에서 loss가 확실히 내려가는지 확인한다.
  2. single-GPU smoke: 1개 GPU에서 dataloader, forward, backward, checkpoint 저장을 확인한다.
  3. small epoch baseline: 전체 데이터의 작은 subset 또는 1 epoch로 metrics.json 생성까지 확인한다.
  4. 위 3개가 통과한 뒤에만 6 GPU DDP를 표준 학습 경로로 사용한다.

3. Fine-tuning Start

아래 명령은 초기 계획 예시다. 현재 실험은 MobileCLIP2-S3/S4 backbone과 full/partial/ArcFace/LoRA 조건을 실험 매트릭스 기준으로 실행한다.

# 예시 형태. 실제 entrypoint는 학습 코드 생성 후 확정한다.
# Canary gates 통과 후 실행한다.
export WANDB_PROJECT=landmark-assistant-sprint1
export WANDB_ENTITY=<team-or-user>
export WANDB_MODE=online

torchrun --nproc_per_node=8 train.py \
  --data-root /data/landmark-assistant/Dataset \
  --model efficientnet_lite0 \
  --teacher dinov3_or_siglip2 \
  --loss ce+supcon+kd \
  --image-size 224 \
  --epochs 30 \
  --amp fp16 \
  --tracker wandb \
  --output runs/sprint1_student_001

실험 config, random seed, git commit 또는 파일 스냅샷, checkpoint, metrics.json을 함께 보관한다. W&B에는 run config, metrics, dataset/split manifest artifact, checkpoint artifact, ONNX artifact를 기록한다.

3.5 W&B Tracking and Drive Backup

  1. W&B run을 학습 시작 시 생성하고, dataset snapshot과 split hash를 config에 기록한다.
  2. best checkpoint와 ONNX export는 W&B artifact로 남긴다.
  3. 학습 종료 또는 실패 직후 scripts/backup_run_to_gdrive.sh로 run directory를 Google Drive에 업로드한다.
  4. Google Drive backup은 복구용이며, 실험 비교와 lineage 판단은 W&B를 기준으로 한다.

4. ONNX Smoke Test

  1. 선택된 MobileCLIP2 checkpoint를 image/text encoder ONNX로 export.
  2. ONNX Runtime으로 dummy input 추론.
  3. 실제 validation image 3장 이상으로 PyTorch output과 cosine similarity 비교.
  4. target device와 ONNX Runtime execution provider를 정하고 operator fallback 여부를 확인.
  5. 학습 preprocessing과 Flutter/Dart preprocessing parity를 확인.
  6. FP16 mixed bundle을 우선 검증하고, INT8/accelerator 경로는 accuracy parity, rejection metric, latency, file size를 별도 비교한다.

4.5 App Surface

  1. 현재 표면 1순위는 Flutter 앱의 ONNX Runtime Mobile이다.
  2. Sprint 1 Streamlit demo는 이전 재현 경로로만 둔다.
  3. 외부 inference API 없이 local runtime에서 모델 파일을 로드한다.
  4. 사용자 이미지를 입력받아 Top-3 landmark 후보와 confidence percentage를 출력한다.
  5. 후보 선택 또는 링크로 landmark 상세정보를 확인할 수 있게 한다. 상세정보 DB는 앱/콘텐츠 팀 책임이다.
  6. confidence가 낮거나 범위 외로 판단되면 목적 범위에 맞는 안내 문구를 보여주고, 후보는 debug log에만 남긴다.

5. Metrics Log Format

{
  "run_id": "sprint1_student_001",
  "dataset_snapshot": "landmark-snapshot-20260513",
  "model": "efficientnet_lite0",
  "teacher": "dinov3_or_siglip2",
  "teacher_checkpoint": null,
  "model_license": null,
  "preprocessing_config_hash": null,
  "torch_version": null,
  "transformers_version": null,
  "onnxruntime_version": null,
  "wandb_project": "landmark-assistant-sprint1",
  "wandb_run_id": null,
  "gdrive_backup_uri": null,
  "top1_accuracy": null,
  "top3_accuracy": null,
  "recall_at_5": null,
  "reject_auroc": null,
  "coverage_at_target_accuracy": null,
  "top1_top2_margin_threshold": null,
  "onnx_file_mb": null,
  "mobile_latency_ms": null,
  "demo_surface": null,
  "target_device": null,
  "onnx_execution_provider": null,
  "quantization": null,
  "notes": "Numbers are null until measured."
}

6. Stop Conditions