컴퓨터 비전을 위한 통합 벤치마킹 파이프라인 구축 — 모든 작업에 대해 코드를 다시 작성하지 않고
Source: Dev.to
문제 개요
| 작업 | 데이터 형식 | 출력 | 평가 지표 |
|---|---|---|---|
| 분류 | 폴더 구조 | 라벨 인덱스 | 정확도, F1 |
| 객체 탐지 | COCO / YOLO JSON / TXT | 경계 상자 | mAP |
| 세그멘테이션 | PNG 마스크 | 픽셀‑레벨 마스크 | IoU |
초기 상태는 다음과 같았습니다:
- 비정형 파이프라인
- 모델‑별 스크립트
- 벤치마크‑별 코드 경로
- 일관된 평가 흐름 부재
실제 벤치마킹 플랫폼을 구축하기 위해—단순 스크립트 모음이 아니라—통합 실행 모델이 필요했습니다.
1. 선언형 접근법: 하나의 YAML이 전체 벤치마크를 정의
첫 번째 설계 결정은 하드코딩된 로직을 선언형 설정 모델로 교체하는 것이었습니다. 각 벤치마크는 다음을 지정하는 단일 YAML 파일로 정의됩니다:
- 작업 유형
- 데이터셋 형식 및 경로
- 분할 (train/val/test)
- 평가 지표
- 실행 파라미터 (디바이스, 배치 크기 등)
YAML 예시
task: detection
dataset:
kind: coco
root: datasets/fruit
splits:
val: val
eval:
metrics: ["map50", "map"]
device: auto
왜 중요한가
- YAML이 시스템 전체의 단일 진실 원천이 됩니다.
- 새로운 벤치마크를 추가하려면 YAML 파일만 만들면 되며, 코드 변경, 새로운 스크립트 작성, 로직 중복이 필요 없습니다.
- 이 설계는 바로 확장성을 제공합니다.
2. YAML만으로는 부족 — Pydantic AppConfig 도입
YAML은 유연하지만 실수에 취약합니다. 오타나 누락된 필드가 평가를 중단시킬 수 있죠. 정확성을 보장하기 위해 우리는 강타입 AppConfig 레이어를 Pydantic 모델로 구축했습니다.
AppConfig의 특징
- 깊은 검증 – 타입, 허용 값, 필수 필드, 구조적 일관성.
- 정규화 – 경로 해석, 기본값 설정, 디바이스 처리, 지표 검증.
- 결정적 해석 – YAML → 안정적인 Python 객체 변환.
- 명확한 계약 – DatasetAdapters, Runners, Metrics, UI 모두 동일한 구조화된 설정을 사용합니다.
Pydantic 모델 예시
from pathlib import Path
from typing import Dict, List
from pydantic import BaseModel
class DatasetConfig(BaseModel):
kind: str
root: Path
splits: Dict[str, str]
class EvalConfig(BaseModel):
metrics: List[str]
device: str = "auto"
batch_size: int = 16
class AppConfig(BaseModel):
task: str
dataset: DatasetConfig
eval: EvalConfig
올바른 AppConfig는 파이프라인 동작을 예측 가능하게 보장하고, 잘못된 YAML은 실행기 시작 전에 즉시 잡아냅니다.
3. 일관되지 않은 형식 통합: DatasetAdapters
검증이 끝난 뒤 다음 과제는 호환되지 않는 데이터셋 형식을 다루는 것이었습니다. 우리는 모든 데이터셋을 통일된 반복 인터페이스로 변환하는 모듈형 DatasetAdapter 레이어를 도입했습니다:
for image, target in adapter:
# model inference
...
제공되는 어댑터
ClassificationFolderAdapterCocoDetectionAdapterYoloDetectionAdapterMaskSegmentationAdapter
각 어댑터는 다음을 수행합니다:
- 원본 데이터셋을 읽음.
- 주석을 정규화된 구조로 변환.
- 작업 전반에 걸쳐 일관된 출력을 제공.
이로써 수십 개의 조건문과 형식‑특정 파싱 로직이 사라집니다.
4. 작업 실행기: 벤치마크 전반에 걸친 모델 실행을 일관되게
데이터셋이 통합되면, 우리는 세 개의 모듈형 실행기(Runner)를 만들었습니다:
ClassifierRunnerDetectorRunnerSegmenterRunner
모든 실행기는 동일한 API를 공유합니다:
result = runner.run(dataset, model, config)
각 실행기가 담당하는 일:
- 순전파 수행
- 출력 정규화
- 예측 로깅
- 지표 계산
- 아티팩트 생성
- 실시간 UI 보고
이 설계 덕분에 구성만 맞추면 어떤 모델이든 어떤 벤치마크든 실행할 수 있습니다.
5. 스크립트에서 시스템으로: 클라이언트‑서버 아키텍처
다수 사용자와 병렬 평가를 지원하기 위해 프로젝트는 완전한 클라이언트‑서버 시스템으로 진화했습니다.
서버 역할
- 작업 스케줄링 및 큐 관리
- 워커 간 부하 분산
- 아티팩트 저장소 (예: MinIO)
- 모델/버전 추적
- 실패 격리
클라이언트 (PyQt) 역할
- 모델 업로드
- 벤치마크 선택 및 실행 설정
- 실시간 로그 보기
- 실행 간 지표 비교
- 예측 아티팩트 다운로드
이 아키텍처는 파이프라인을 실용적이고 확장 가능한 연구 도구로 바꾸었습니다.
6. 핵심 엔지니어링 교훈
- 구성 파일이 실행을 주도해야 한다, 그 반대가 아니라.
- 강력한 검증(Pydantic)은 디버깅 시간을 크게 절감한다.
- 어댑터는 복잡성을 정규화하고 형식‑특정 로직 폭발을 방지한다.
- 모듈형 실행기는 작업 로직을 교체하고 확장하기 쉽게 만든다.
- 증분 평가는 실제 데이터셋에서 필수적이다.
- 클라이언트‑서버 분리는 파이프라인을 프로덕션 급 시스템으로 전환한다.
결론
다음 요소들을 결합함으로써:
- 선언형 YAML 설정
- 강타입
AppConfig레이어 - 어댑터를 통한 데이터셋 정규화
- 모듈형 실행기
- 증분 연산
- 클라이언트‑서버 아키텍처
우리는 어떤 컴퓨터 비전 모델이든, 어떤 벤치마크든 새로운 코드를 작성하지 않고도 실행할 수 있는 통합 벤치마킹 파이프라인을 구축했습니다. 이 접근법은 안정성, 확장성, 재현성을 제공하며, 실무 평가 시스템에 필수적인 특성들입니다.