컴퓨터 비전을 위한 통합 벤치마킹 파이프라인 구축 — 모든 작업에 대해 코드를 다시 작성하지 않고

발행: (2025년 12월 8일 오전 05:25 GMT+9)
8 min read
원문: Dev.to

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
    ...

제공되는 어댑터

  • ClassificationFolderAdapter
  • CocoDetectionAdapter
  • YoloDetectionAdapter
  • MaskSegmentationAdapter

각 어댑터는 다음을 수행합니다:

  • 원본 데이터셋을 읽음.
  • 주석을 정규화된 구조로 변환.
  • 작업 전반에 걸쳐 일관된 출력을 제공.

이로써 수십 개의 조건문과 형식‑특정 파싱 로직이 사라집니다.

4. 작업 실행기: 벤치마크 전반에 걸친 모델 실행을 일관되게

데이터셋이 통합되면, 우리는 세 개의 모듈형 실행기(Runner)를 만들었습니다:

  • ClassifierRunner
  • DetectorRunner
  • SegmenterRunner

모든 실행기는 동일한 API를 공유합니다:

result = runner.run(dataset, model, config)

각 실행기가 담당하는 일:

  • 순전파 수행
  • 출력 정규화
  • 예측 로깅
  • 지표 계산
  • 아티팩트 생성
  • 실시간 UI 보고

이 설계 덕분에 구성만 맞추면 어떤 모델이든 어떤 벤치마크든 실행할 수 있습니다.

5. 스크립트에서 시스템으로: 클라이언트‑서버 아키텍처

다수 사용자와 병렬 평가를 지원하기 위해 프로젝트는 완전한 클라이언트‑서버 시스템으로 진화했습니다.

서버 역할

  • 작업 스케줄링 및 큐 관리
  • 워커 간 부하 분산
  • 아티팩트 저장소 (예: MinIO)
  • 모델/버전 추적
  • 실패 격리

클라이언트 (PyQt) 역할

  • 모델 업로드
  • 벤치마크 선택 및 실행 설정
  • 실시간 로그 보기
  • 실행 간 지표 비교
  • 예측 아티팩트 다운로드

이 아키텍처는 파이프라인을 실용적이고 확장 가능한 연구 도구로 바꾸었습니다.

6. 핵심 엔지니어링 교훈

  • 구성 파일이 실행을 주도해야 한다, 그 반대가 아니라.
  • 강력한 검증(Pydantic)은 디버깅 시간을 크게 절감한다.
  • 어댑터는 복잡성을 정규화하고 형식‑특정 로직 폭발을 방지한다.
  • 모듈형 실행기는 작업 로직을 교체하고 확장하기 쉽게 만든다.
  • 증분 평가는 실제 데이터셋에서 필수적이다.
  • 클라이언트‑서버 분리는 파이프라인을 프로덕션 급 시스템으로 전환한다.

결론

다음 요소들을 결합함으로써:

  • 선언형 YAML 설정
  • 강타입 AppConfig 레이어
  • 어댑터를 통한 데이터셋 정규화
  • 모듈형 실행기
  • 증분 연산
  • 클라이언트‑서버 아키텍처

우리는 어떤 컴퓨터 비전 모델이든, 어떤 벤치마크든 새로운 코드를 작성하지 않고도 실행할 수 있는 통합 벤치마킹 파이프라인을 구축했습니다. 이 접근법은 안정성, 확장성, 재현성을 제공하며, 실무 평가 시스템에 필수적인 특성들입니다.

Back to Blog

관련 글

더 보기 »