본 콘텐츠의 이미지 및 내용은 AI로 생성되었습니다.
본 콘텐츠의 이미지 및 내용을 무단으로 복제, 배포, 수정하여 사용할 경우 저작권법에 의해 법적 제재를 받을 수 있습니다.
이미지 로딩 중...
AI Generated
2025. 12. 9. · 14 Views
실전 CV 프로젝트 완벽 가이드
Computer Vision 프로젝트를 처음부터 끝까지 완성하는 방법을 배웁니다. 데이터 수집부터 모델 최적화, 데모 배포까지 실무에서 바로 쓸 수 있는 핵심 과정을 다룹니다.
목차
1. 프로젝트 주제 선정
김개발 씨는 CV 과정을 모두 수강하고 나서 문득 고민에 빠졌습니다. "이제 뭘 만들어야 하지?" 선배 박시니어 씨가 다가와 물었습니다.
"프로젝트 주제는 정했어요?"
프로젝트 주제 선정은 성공적인 CV 프로젝트의 첫 번째 단계입니다. 마치 여행을 떠나기 전에 목적지를 정하는 것과 같습니다.
좋은 주제는 구현 가능성과 실용성, 그리고 데이터 확보 가능성을 모두 고려해야 합니다.
다음 코드를 살펴봅시다.
# CV 프로젝트 주제 평가 체크리스트
project_criteria = {
"name": "마스크 착용 감지 시스템",
"feasibility": 8, # 구현 가능성 (1-10)
"data_availability": 9, # 데이터 확보 용이성
"practicality": 9, # 실용성
"complexity": 6 # 복잡도 (낮을수록 좋음)
}
# 프로젝트 점수 계산
def evaluate_project(criteria):
# 복잡도는 역산 (10에서 빼기)
score = (criteria["feasibility"] + criteria["data_availability"] +
criteria["practicality"] + (10 - criteria["complexity"])) / 4
return score
project_score = evaluate_project(project_criteria)
print(f"프로젝트 점수: {project_score:.2f}/10")
김개발 씨는 입사 6개월 차 주니어 개발자입니다. Computer Vision 온라인 강의를 모두 수강하고 나니 이제 직접 프로젝트를 만들고 싶었습니다.
하지만 막상 시작하려니 어떤 주제를 선택해야 할지 막막했습니다. 선배 박시니어 씨가 커피를 한 잔 건네며 말했습니다.
"첫 프로젝트는 욕심내지 말고 확실하게 완성할 수 있는 걸 고르는 게 중요해요." 그렇다면 좋은 CV 프로젝트 주제란 무엇일까요? 쉽게 비유하자면, 프로젝트 주제 선정은 마치 등산 코스를 고르는 것과 같습니다.
초보자가 처음부터 에베레스트에 도전하면 중간에 포기하기 쉽습니다. 하지만 적당한 난이도의 산을 선택하면 성취감을 느끼며 완주할 수 있습니다.
CV 프로젝트도 마찬가지입니다. 프로젝트 주제가 없던 시절에는 어땠을까요?
많은 초보 개발자들이 "무작정 멋있어 보이는" 프로젝트에 뛰어들었습니다. 자율주행 자동차, 의료 진단 시스템 같은 거창한 주제를 선택했습니다.
하지만 데이터를 구하지 못해 막히거나, 너무 복잡해서 중간에 포기하는 경우가 많았습니다. 바로 이런 문제를 해결하기 위해 체계적인 주제 선정 프레임워크가 필요합니다.
좋은 주제를 선택하면 프로젝트 완성 가능성이 크게 높아집니다. 또한 포트폴리오 가치도 올라갑니다.
무엇보다 학습 효과가 극대화됩니다. 위의 코드를 한 줄씩 살펴보겠습니다.
먼저 딕셔너리로 프로젝트를 정의합니다. 구현 가능성, 데이터 확보 용이성, 실용성, 복잡도 네 가지 기준으로 평가합니다.
각 항목을 1부터 10까지 점수로 매깁니다. evaluate_project 함수는 이 점수들을 종합하여 최종 점수를 계산합니다.
복잡도는 낮을수록 좋으므로 10에서 빼서 계산합니다. 실제 현업에서는 어떻게 활용할까요?
예를 들어 스타트업에서 신규 서비스를 기획한다고 가정해봅시다. 마스크 착용 감지 시스템은 데이터 확보가 쉽고(공개 데이터셋 존재), 구현도 가능하며(객체 탐지 모델 활용), 실용성도 높습니다(코로나 이후 수요 증가).
많은 기업에서 이런 기준으로 프로젝트를 선정합니다. 하지만 주의할 점도 있습니다.
초보 개발자들이 흔히 하는 실수 중 하나는 너무 참신한 주제를 선택하는 것입니다. 아무도 시도하지 않은 완전히 새로운 주제는 데이터를 구하기 어렵고 레퍼런스도 없습니다.
따라서 검증된 유형의 프로젝트에서 시작하는 것이 좋습니다. 다시 김개발 씨의 이야기로 돌아가봅시다.
박시니어 씨의 조언을 들은 김개발 씨는 고개를 끄덕였습니다. "그럼 먼저 간단한 분류 프로젝트부터 시작해볼게요!" 좋은 주제를 선택하면 프로젝트를 끝까지 완성할 확률이 높아집니다.
여러분도 오늘 배운 체크리스트를 활용해 주제를 평가해 보세요.
실전 팁
💡 - 첫 프로젝트는 객체 분류나 간단한 탐지 문제로 시작하세요
- Kaggle에서 유사한 프로젝트를 검색해 데이터셋 확보 가능성을 먼저 확인하세요
- 3개월 안에 완성 가능한 범위로 설정하세요
2. 데이터 수집 및 라벨링
주제를 정한 김개발 씨는 이제 데이터를 모아야 합니다. "데이터가 없으면 아무것도 할 수 없다"는 말이 실감났습니다.
박시니어 씨가 말했습니다. "데이터가 모델의 70%를 결정한다고 보면 돼요."
데이터 수집과 라벨링은 CV 프로젝트의 생명선입니다. 마치 요리사가 좋은 재료를 준비하는 것과 같습니다.
양질의 데이터를 충분히 확보하고 정확하게 라벨링해야 좋은 모델을 만들 수 있습니다.
다음 코드를 살펴봅시다.
import os
from PIL import Image
import json
# 데이터셋 구조 생성
def create_dataset_structure(base_path):
folders = ['train', 'val', 'test']
classes = ['with_mask', 'without_mask']
for folder in folders:
for cls in classes:
# 데이터셋 폴더 구조 생성
path = os.path.join(base_path, folder, cls)
os.makedirs(path, exist_ok=True)
print("데이터셋 폴더 구조 생성 완료")
# 라벨링 정보 저장 (COCO 형식)
def save_annotation(image_path, bbox, category):
annotation = {
"image": image_path,
"bbox": bbox, # [x, y, width, height]
"category": category,
"verified": True
}
return annotation
# 사용 예시
create_dataset_structure("./mask_dataset")
sample_annotation = save_annotation("img001.jpg", [100, 150, 200, 200], "with_mask")
print(f"라벨링 완료: {sample_annotation}")
김개발 씨는 마스크 착용 감지 프로젝트를 시작했습니다. 가장 먼저 해야 할 일은 데이터를 모으는 것이었습니다.
구글에 "mask dataset"을 검색하니 다행히 공개 데이터셋이 몇 개 보였습니다. 하지만 막상 데이터를 받아보니 문제가 생겼습니다.
이미지 품질이 제각각이고, 라벨도 일관성이 없었습니다. 박시니어 씨에게 물어봤더니 이렇게 대답했습니다.
"그래서 데이터 전처리가 중요한 거예요." 그렇다면 데이터 수집과 라벨링은 정확히 어떻게 해야 할까요? 쉽게 비유하자면, 데이터 수집은 마치 도서관에서 책을 모으는 것과 같습니다.
무작정 많이 모으는 것보다 주제에 맞는 양질의 책을 선별하는 게 중요합니다. 라벨링은 그 책들을 정확한 카테고리에 배치하는 것입니다.
잘못 분류된 책은 나중에 찾을 수 없게 됩니다. 체계적인 데이터 관리가 없던 시절에는 어땠을까요?
개발자들은 이미지를 하나의 폴더에 마구 저장했습니다. 파일명도 규칙 없이 image1, image2 같은 식으로 지었습니다.
나중에 학습 데이터와 검증 데이터를 분리하려면 수작업으로 옮겨야 했습니다. 더 큰 문제는 라벨링 정보가 흩어져 있다는 점이었습니다.
바로 이런 문제를 해결하기 위해 표준화된 데이터셋 구조가 등장했습니다. 구조화된 폴더 시스템을 사용하면 데이터 관리가 쉬워집니다.
또한 train/val/test 분리가 명확해집니다. 무엇보다 라벨링 정보를 체계적으로 저장할 수 있습니다.
위의 코드를 한 줄씩 살펴보겠습니다. create_dataset_structure 함수는 base_path 아래에 train, val, test 폴더를 만듭니다.
각 폴더 안에는 다시 클래스별 폴더(with_mask, without_mask)를 생성합니다. os.makedirs의 exist_ok=True 옵션은 폴더가 이미 있어도 에러를 발생시키지 않습니다.
save_annotation 함수는 COCO 형식으로 라벨링 정보를 저장합니다. 실제 현업에서는 어떻게 활용할까요?
예를 들어 제조업체에서 불량품 감지 시스템을 개발한다고 가정해봅시다. 정상 제품 1000장, 불량 제품 1000장을 수집합니다.
이를 train 70%, val 15%, test 15%로 나눕니다. 각 이미지에는 불량 부위를 표시한 bounding box 정보를 JSON으로 저장합니다.
많은 제조 기업에서 이런 방식으로 데이터를 관리합니다. 하지만 주의할 점도 있습니다.
초보 개발자들이 흔히 하는 실수 중 하나는 데이터 불균형을 무시하는 것입니다. 정상 데이터 900장, 불량 데이터 100장처럼 비율이 맞지 않으면 모델이 제대로 학습되지 않습니다.
따라서 클래스 간 균형을 맞추거나 augmentation으로 보완해야 합니다. 다시 김개발 씨의 이야기로 돌아가봅시다.
박시니어 씨의 조언대로 데이터를 체계적으로 정리한 김개발 씨는 뿌듯해했습니다. "이제야 제대로 시작하는 느낌이에요!" 양질의 데이터를 체계적으로 관리하면 모델 성능이 크게 향상됩니다.
여러분도 오늘 배운 구조를 따라 데이터셋을 구축해 보세요.
실전 팁
💡 - Roboflow, Labelbox 같은 무료 라벨링 도구를 활용하세요
- 데이터 수는 클래스당 최소 500장 이상 확보하세요
- 라벨링 검증을 위해 일부 데이터는 이중으로 라벨링하세요
3. 모델 선택 및 학습
데이터 준비가 끝나자 김개발 씨는 드디어 모델을 선택할 차례였습니다. "YOLO, ResNet, EfficientNet...
뭘 써야 하지?" 박시니어 씨가 웃으며 말했습니다. "문제 유형에 맞는 모델을 골라야죠."
모델 선택과 학습은 CV 프로젝트의 핵심입니다. 마치 도구 상자에서 적합한 공구를 고르는 것과 같습니다.
분류, 탐지, 세그멘테이션 등 문제 유형에 따라 적절한 아키텍처를 선택하고 효과적으로 학습시켜야 합니다.
다음 코드를 살펴봅시다.
import torch
import torchvision.models as models
from torch import nn, optim
from torch.utils.data import DataLoader
# 사전 학습된 모델 로드 (Transfer Learning)
model = models.resnet18(pretrained=True)
# 마지막 레이어를 우리 문제에 맞게 수정
num_classes = 2 # with_mask, without_mask
model.fc = nn.Linear(model.fc.in_features, num_classes)
# 모델을 GPU로 이동
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model = model.to(device)
# 손실 함수와 옵티마이저 정의
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)
# 학습 루프 (간단한 예시)
def train_one_epoch(model, dataloader, criterion, optimizer):
model.train()
running_loss = 0.0
for images, labels in dataloader:
images, labels = images.to(device), labels.to(device)
optimizer.zero_grad() # 기울기 초기화
outputs = model(images) # 순전파
loss = criterion(outputs, labels) # 손실 계산
loss.backward() # 역전파
optimizer.step() # 가중치 업데이트
running_loss += loss.item()
return running_loss / len(dataloader)
김개발 씨는 모델을 처음부터 학습시키려고 했습니다. 하지만 박시니어 씨가 말렸습니다.
"처음부터 학습시키면 시간도 오래 걸리고 데이터도 훨씬 많이 필요해요. Transfer Learning을 쓰세요." "Transfer Learning이요?" 김개발 씨는 고개를 갸우뚱했습니다.
그렇다면 Transfer Learning이란 정확히 무엇일까요? 쉽게 비유하자면, Transfer Learning은 마치 이미 요리를 배운 사람이 새로운 레시피를 배우는 것과 같습니다.
요리 기초가 전혀 없는 사람이 처음부터 배우는 것보다 훨씬 빠르게 익힐 수 있습니다. CV 모델도 마찬가지입니다.
ImageNet 같은 거대한 데이터셋으로 이미 학습된 모델은 일반적인 시각적 특징을 이미 알고 있습니다. Transfer Learning이 없던 시절에는 어땠을까요?
개발자들은 모든 모델을 처음부터 학습시켜야 했습니다. 수백만 장의 데이터와 수천 시간의 GPU 시간이 필요했습니다.
작은 데이터셋으로는 제대로 된 모델을 만들 수 없었습니다. 더 큰 문제는 과적합이 쉽게 발생한다는 점이었습니다.
바로 이런 문제를 해결하기 위해 **사전 학습 모델(Pre-trained Model)**이 등장했습니다. 사전 학습 모델을 사용하면 학습 시간이 크게 단축됩니다.
또한 적은 데이터로도 높은 정확도를 얻을 수 있습니다. 무엇보다 과적합 위험이 감소합니다.
위의 코드를 한 줄씩 살펴보겠습니다. 먼저 pretrained=True로 ImageNet에서 학습된 ResNet18을 불러옵니다.
이 모델은 이미 1000개 클래스를 분류할 수 있습니다. 하지만 우리는 2개 클래스만 필요하므로 마지막 fully connected 레이어를 교체합니다.
model.fc.in_features는 이전 레이어의 출력 크기를 자동으로 가져옵니다. 모델을 GPU로 이동시켜 학습 속도를 높입니다.
train_one_epoch 함수는 한 에폭 동안 데이터를 반복하며 학습합니다. 실제 현업에서는 어떻게 활용할까요?
예를 들어 의류 쇼핑몰에서 상품 카테고리 자동 분류 시스템을 개발한다고 가정해봅시다. ResNet50을 사전 학습 모델로 사용하고, 마지막 레이어만 "티셔츠, 바지, 드레스, 신발" 4개 클래스로 교체합니다.
불과 클래스당 500장의 이미지만으로도 95% 이상의 정확도를 달성할 수 있습니다. 많은 e-커머스 기업이 이런 방식을 활용합니다.
하지만 주의할 점도 있습니다. 초보 개발자들이 흔히 하는 실수 중 하나는 학습률을 너무 크게 설정하는 것입니다.
사전 학습된 가중치는 이미 최적화되어 있으므로 큰 학습률로 학습하면 오히려 성능이 떨어집니다. 따라서 0.001 이하의 작은 학습률로 시작하는 것이 좋습니다.
다시 김개발 씨의 이야기로 돌아가봅시다. Transfer Learning으로 학습을 시작한 김개발 씨는 놀랐습니다.
"와, 불과 10분 만에 90% 정확도가 나왔어요!" 사전 학습 모델을 활용하면 적은 리소스로도 좋은 결과를 얻을 수 있습니다. 여러분도 오늘 배운 방법으로 모델을 학습시켜 보세요.
실전 팁
💡 - 처음에는 ResNet18이나 MobileNetV2 같은 가벼운 모델로 시작하세요
- 학습 초기에는 사전 학습된 레이어를 freeze하고 마지막 레이어만 학습시키세요
- TensorBoard로 loss와 accuracy를 실시간으로 모니터링하세요
4. 하이퍼파라미터 튜닝
모델이 90% 정확도를 보이자 김개발 씨는 만족했습니다. 하지만 박시니어 씨가 물었습니다.
"학습률은 어떻게 정했어요? 배치 사이즈는요?" 김개발 씨는 당황했습니다.
"그냥... 기본값으로..."
하이퍼파라미터 튜닝은 모델 성능을 끌어올리는 핵심 과정입니다. 마치 악기를 조율하는 것과 같습니다.
학습률, 배치 사이즈, 에폭 수 등을 최적화하면 같은 모델로도 훨씬 좋은 성능을 얻을 수 있습니다.
다음 코드를 살펴봅시다.
import optuna
# Optuna를 활용한 하이퍼파라미터 최적화
def objective(trial):
# 튜닝할 하이퍼파라미터 정의
lr = trial.suggest_loguniform('lr', 1e-5, 1e-2)
batch_size = trial.suggest_categorical('batch_size', [16, 32, 64])
optimizer_name = trial.suggest_categorical('optimizer', ['Adam', 'SGD'])
# 모델 생성 및 학습
model = models.resnet18(pretrained=True)
model.fc = nn.Linear(model.fc.in_features, 2)
if optimizer_name == 'Adam':
optimizer = optim.Adam(model.parameters(), lr=lr)
else:
optimizer = optim.SGD(model.parameters(), lr=lr, momentum=0.9)
# 간단한 학습 및 검증 (실제로는 전체 학습 루프)
# val_accuracy = train_and_validate(model, optimizer, batch_size)
val_accuracy = 0.92 # 예시 값
return val_accuracy
# 최적화 실행
study = optuna.create_study(direction='maximize')
study.optimize(objective, n_trials=20)
print(f"최적 하이퍼파라미터: {study.best_params}")
print(f"최고 정확도: {study.best_value:.4f}")
김개발 씨는 그동안 하이퍼파라미터를 대충 설정했다는 사실을 깨달았습니다. 박시니어 씨가 설명했습니다.
"하이퍼파라미터를 잘 튜닝하면 성능이 5%에서 10%까지도 올라갈 수 있어요." "그럼 일일이 다 바꿔가면서 실험해야 하나요?" 김개발 씨가 물었습니다. 그렇다면 효율적인 하이퍼파라미터 튜닝 방법은 무엇일까요?
쉽게 비유하자면, 하이퍼파라미터 튜닝은 마치 라디오 주파수를 맞추는 것과 같습니다. 무작정 다이얼을 돌리는 것보다 체계적으로 범위를 좁혀가며 최적의 지점을 찾는 게 효율적입니다.
Optuna 같은 도구는 이 과정을 자동화해줍니다. 체계적인 튜닝이 없던 시절에는 어땠을까요?
개발자들은 수작업으로 값을 바꿔가며 수십 번 실험했습니다. 학습률을 0.1, 0.01, 0.001로 각각 테스트하고, 배치 사이즈도 16, 32, 64로 모두 돌려봤습니다.
하나의 조합을 테스트하는 데 몇 시간씩 걸렸습니다. 더 큰 문제는 최적 조합을 찾지 못할 수도 있다는 점이었습니다.
바로 이런 문제를 해결하기 위해 **자동 하이퍼파라미터 최적화(HPO)**가 등장했습니다. 자동 HPO를 사용하면 탐색 시간이 크게 단축됩니다.
또한 최적 조합을 놓칠 확률이 줄어듭니다. 무엇보다 여러 하이퍼파라미터를 동시에 최적화할 수 있습니다.
위의 코드를 한 줄씩 살펴보겠습니다. objective 함수는 Optuna가 최적화할 목표 함수입니다.
trial.suggest_loguniform은 로그 스케일로 학습률 범위를 탐색합니다. 1e-5부터 1e-2까지 광범위하게 시도합니다.
suggest_categorical은 정해진 선택지 중에서 고릅니다. 각 조합으로 모델을 학습하고 검증 정확도를 반환합니다.
create_study로 최적화 작업을 생성하고, direction='maximize'로 정확도를 최대화합니다. n_trials=20으로 20번의 조합을 시도합니다.
실제 현업에서는 어떻게 활용할까요? 예를 들어 자율주행 스타트업에서 차선 인식 모델을 개발한다고 가정해봅시다.
학습률, 배치 사이즈, 데이터 augmentation 강도 등 10개 이상의 하이퍼파라미터를 최적화해야 합니다. Optuna를 밤새 돌려두면 아침에 최적 조합을 얻을 수 있습니다.
많은 AI 기업이 이런 방식으로 모델을 개선합니다. 하지만 주의할 점도 있습니다.
초보 개발자들이 흔히 하는 실수 중 하나는 너무 많은 trial을 돌리는 것입니다. 100번 이상 시도하면 시간만 오래 걸리고 성능 향상은 미미합니다.
따라서 20~50번 정도가 적절합니다. 또한 검증 데이터로 평가해야지 학습 데이터로 평가하면 과적합이 발생합니다.
다시 김개발 씨의 이야기로 돌아가봅시다. Optuna로 최적화를 돌린 김개발 씨는 놀라운 결과를 봤습니다.
"정확도가 90%에서 94%로 올랐어요!" 하이퍼파라미터를 체계적으로 튜닝하면 모델 성능이 크게 향상됩니다. 여러분도 오늘 배운 Optuna를 활용해 최적화해 보세요.
실전 팁
💡 - 먼저 학습률과 배치 사이즈 같은 중요한 하이퍼파라미터부터 튜닝하세요
- Early Stopping을 설정해 시간을 절약하세요
- Optuna 대시보드로 실시간 최적화 과정을 확인하세요
5. 모델 최적화 ONNX TensorRT
모델 성능이 만족스러워지자 김개발 씨는 이제 배포를 생각했습니다. 하지만 추론 속도를 측정해보니 이미지 1장당 0.5초나 걸렸습니다.
박시니어 씨가 말했습니다. "실시간으로 쓰려면 최적화가 필수예요."
모델 최적화는 배포를 위한 필수 과정입니다. 마치 짐을 꾸릴 때 압축하는 것과 같습니다.
ONNX로 모델을 변환하고 TensorRT로 가속화하면 추론 속도가 수십 배 빨라집니다.
다음 코드를 살펴봅시다.
import torch
import torch.onnx
# PyTorch 모델을 ONNX로 변환
def export_to_onnx(model, onnx_path, input_shape=(1, 3, 224, 224)):
model.eval() # 평가 모드로 전환
dummy_input = torch.randn(input_shape) # 더미 입력 생성
torch.onnx.export(
model,
dummy_input,
onnx_path,
export_params=True, # 학습된 파라미터 포함
opset_version=11, # ONNX opset 버전
do_constant_folding=True, # 상수 folding 최적화
input_names=['input'], # 입력 이름
output_names=['output'], # 출력 이름
dynamic_axes={ # 동적 배치 크기 지원
'input': {0: 'batch_size'},
'output': {0: 'batch_size'}
}
)
print(f"ONNX 모델 저장 완료: {onnx_path}")
# ONNX 모델로 추론
import onnxruntime as ort
def infer_with_onnx(onnx_path, input_data):
session = ort.InferenceSession(onnx_path)
input_name = session.get_inputs()[0].name
output = session.run(None, {input_name: input_data})
return output[0]
# 사용 예시
export_to_onnx(model, "mask_detector.onnx")
김개발 씨는 모델을 그대로 배포하려 했습니다. 하지만 박시니어 씨가 고개를 저었습니다.
"PyTorch 모델을 그대로 쓰면 속도도 느리고 배포도 어려워요. ONNX로 변환하세요." "ONNX가 뭔가요?" 김개발 씨가 물었습니다.
그렇다면 ONNX란 정확히 무엇일까요? 쉽게 비유하자면, ONNX는 마치 범용 파일 포맷과 같습니다.
워드 문서를 PDF로 변환하면 어떤 기기에서든 볼 수 있듯이, PyTorch 모델을 ONNX로 변환하면 어떤 플랫폼에서든 실행할 수 있습니다. TensorFlow, PyTorch, MXNet 같은 프레임워크에 구애받지 않습니다.
표준 포맷이 없던 시절에는 어땠을까요? 개발자들은 각 프레임워크마다 별도로 배포해야 했습니다.
PyTorch로 학습한 모델을 TensorFlow Serving에서 쓸 수 없었습니다. 모바일이나 엣지 디바이스에 배포하기도 어려웠습니다.
더 큰 문제는 추론 속도 최적화가 제한적이었다는 점입니다. 바로 이런 문제를 해결하기 위해 **ONNX(Open Neural Network Exchange)**가 등장했습니다.
ONNX를 사용하면 플랫폼 독립성을 얻을 수 있습니다. 또한 ONNX Runtime으로 빠른 추론이 가능합니다.
무엇보다 TensorRT, OpenVINO 같은 최적화 엔진과 연계할 수 있습니다. 위의 코드를 한 줄씩 살펴보겠습니다.
먼저 model.eval()로 모델을 평가 모드로 전환합니다. Dropout이나 BatchNorm이 올바르게 동작하도록 합니다.
torch.randn으로 더미 입력을 생성합니다. ONNX 변환 시 입력 shape를 파악하는 데 필요합니다.
export_params=True로 학습된 가중치를 ONNX 파일에 포함시킵니다. dynamic_axes로 배치 크기를 동적으로 처리할 수 있게 합니다.
ort.InferenceSession으로 ONNX 모델을 로드하고 추론합니다. 실제 현업에서는 어떻게 활용할까요?
예를 들어 스마트폰 앱에서 실시간 객체 인식 기능을 개발한다고 가정해봅시다. PyTorch로 학습한 모델을 ONNX로 변환하고, 다시 ONNX Mobile로 변환합니다.
이렇게 하면 iOS와 Android 모두에서 추론 속도가 10배 이상 빨라집니다. 많은 모바일 AI 앱이 이런 방식을 사용합니다.
하지만 주의할 점도 있습니다. 초보 개발자들이 흔히 하는 실수 중 하나는 모든 연산자가 ONNX를 지원한다고 생각하는 것입니다.
일부 커스텀 연산자는 ONNX로 변환되지 않을 수 있습니다. 따라서 변환 후 정확도를 검증해야 합니다.
또한 TensorRT를 쓰려면 NVIDIA GPU가 필수입니다. 다시 김개발 씨의 이야기로 돌아가봅시다.
ONNX로 변환한 모델을 테스트한 김개발 씨는 놀랐습니다. "추론 시간이 0.5초에서 0.05초로 줄었어요!" 모델을 ONNX로 최적화하면 배포 시 큰 이점을 얻습니다.
여러분도 오늘 배운 방법으로 모델을 변환해 보세요.
실전 팁
💡 - 변환 후 원본 모델과 출력을 비교해 정확도를 검증하세요
- TensorRT를 쓰면 GPU에서 추론이 더욱 빨라집니다
- 모바일 배포는 ONNX Mobile이나 TFLite를 고려하세요
6. Gradio로 데모 만들기
모든 준비가 끝나자 김개발 씨는 데모를 만들고 싶었습니다. "하지만 웹 개발은 잘 몰라서..." 박시니어 씨가 웃으며 말했습니다.
"Gradio 쓰면 5분이면 돼요."
Gradio 데모는 모델을 빠르게 시연할 수 있는 최고의 도구입니다. 마치 프레젠테이션 슬라이드를 만드는 것과 같습니다.
웹 개발 지식 없이도 멋진 인터페이스로 모델을 공유할 수 있습니다.
다음 코드를 살펴봅시다.
import gradio as gr
import cv2
import numpy as np
from PIL import Image
# 모델 로드 (ONNX)
import onnxruntime as ort
session = ort.InferenceSession("mask_detector.onnx")
def predict_mask(image):
# 이미지 전처리
img = cv2.resize(image, (224, 224))
img = img.astype(np.float32) / 255.0
img = np.transpose(img, (2, 0, 1)) # HWC -> CHW
img = np.expand_dims(img, axis=0) # 배치 차원 추가
# 추론
input_name = session.get_inputs()[0].name
output = session.run(None, {input_name: img})[0]
# 결과 해석
classes = ["마스크 미착용", "마스크 착용"]
confidence = np.max(output)
prediction = classes[np.argmax(output)]
return f"{prediction} (신뢰도: {confidence:.2%})"
# Gradio 인터페이스 생성
demo = gr.Interface(
fn=predict_mask,
inputs=gr.Image(),
outputs=gr.Text(label="예측 결과"),
title="마스크 착용 감지 시스템",
description="얼굴 이미지를 업로드하면 마스크 착용 여부를 판단합니다.",
examples=["example1.jpg", "example2.jpg"]
)
# 실행
if __name__ == "__main__":
demo.launch(share=True) # 공개 URL 생성
김개발 씨는 모델을 완성했지만 고민이 생겼습니다. 팀원들에게 어떻게 시연하면 좋을까요?
웹 페이지를 만들려면 HTML, CSS, JavaScript를 배워야 할까요? 박시니어 씨가 Gradio를 소개했습니다.
"Gradio면 코드 몇 줄로 웹 데모를 만들 수 있어요." 그렇다면 Gradio란 정확히 무엇일까요? 쉽게 비유하자면, Gradio는 마치 무료 홈페이지 빌더와 같습니다.
워드프레스처럼 복잡한 설정 없이도 드래그 앤 드롭처럼 쉽게 웹 인터페이스를 만들 수 있습니다. 머신러닝 모델을 위해 특별히 설계되었습니다.
데모 도구가 없던 시절에는 어땠을까요? 개발자들은 Flask나 Django로 웹 서버를 직접 구축해야 했습니다.
HTML 폼을 만들고, 이미지 업로드 처리를 구현하고, CSS로 스타일을 꾸미는 데 며칠이 걸렸습니다. 비개발자에게 시연하기도 어려웠습니다.
더 큰 문제는 배포가 복잡했다는 점입니다. 바로 이런 문제를 해결하기 위해 Gradio가 등장했습니다.
Gradio를 사용하면 개발 시간이 크게 단축됩니다. 또한 즉시 공유 가능한 URL을 얻을 수 있습니다.
무엇보다 Hugging Face Spaces에 무료 배포도 가능합니다. 위의 코드를 한 줄씩 살펴보겠습니다.
먼저 ONNX 모델을 로드합니다. predict_mask 함수는 입력 이미지를 받아 예측 결과를 반환합니다.
이미지를 224x224로 리사이즈하고 정규화합니다. numpy 배열을 모델 입력 형태로 변환합니다.
gr.Interface로 UI를 정의합니다. inputs는 이미지 업로드 위젯, outputs는 텍스트 결과입니다.
examples 파라미터로 샘플 이미지를 제공합니다. share=True로 공개 URL을 생성합니다.
실제 현업에서는 어떻게 활용할까요? 예를 들어 AI 스타트업에서 투자자에게 제품을 시연한다고 가정해봅시다.
Gradio로 5분 만에 데모를 만들고, 공개 URL을 공유합니다. 투자자는 브라우저에서 바로 테스트할 수 있습니다.
실제로 많은 스타트업이 Hugging Face Spaces에 Gradio 데모를 올려 제품을 홍보합니다. 하지만 주의할 점도 있습니다.
초보 개발자들이 흔히 하는 실수 중 하나는 공개 URL을 영구적이라고 생각하는 것입니다. share=True로 생성된 URL은 72시간 후 만료됩니다.
장기적으로 사용하려면 Hugging Face Spaces나 클라우드에 배포해야 합니다. 또한 보안에 신경 써야 합니다.
다시 김개발 씨의 이야기로 돌아가봅시다. Gradio 데모를 완성한 김개발 씨는 뿌듯해했습니다.
"드디어 처음부터 끝까지 완성했어요!" Gradio로 쉽게 데모를 만들면 모델을 효과적으로 공유할 수 있습니다. 여러분도 오늘 배운 방법으로 데모를 만들어 보세요.
실전 팁
💡 - gr.Blocks로 더 복잡한 레이아웃을 구성할 수 있습니다
- Hugging Face Spaces에 배포하면 영구 URL을 얻을 수 있습니다
- 입력 예시를 여러 개 제공하면 사용자가 이해하기 쉽습니다
이상으로 학습을 마칩니다. 위 내용을 직접 코드로 작성해보면서 익혀보세요!
댓글 (0)
함께 보면 좋은 카드 뉴스
Helm 마이크로서비스 패키징 완벽 가이드
Kubernetes 환경에서 마이크로서비스를 효율적으로 패키징하고 배포하는 Helm의 핵심 기능을 실무 중심으로 학습합니다. Chart 생성부터 릴리스 관리까지 체계적으로 다룹니다.
보안 아키텍처 구성 완벽 가이드
프로젝트의 보안을 처음부터 설계하는 방법을 배웁니다. AWS 환경에서 VPC부터 WAF, 암호화, 접근 제어까지 실무에서 바로 적용할 수 있는 보안 아키텍처를 단계별로 구성해봅니다.
AWS Organizations 완벽 가이드
여러 AWS 계정을 체계적으로 관리하고 통합 결제와 보안 정책을 적용하는 방법을 실무 스토리로 쉽게 배워봅니다. 초보 개발자도 바로 이해할 수 있는 친절한 설명과 실전 예제를 제공합니다.
AWS KMS 암호화 완벽 가이드
AWS KMS(Key Management Service)를 활용한 클라우드 데이터 암호화 방법을 초급 개발자를 위해 쉽게 설명합니다. CMK 생성부터 S3, EBS 암호화, 봉투 암호화까지 실무에 필요한 모든 내용을 담았습니다.
AWS Secrets Manager 완벽 가이드
AWS에서 데이터베이스 비밀번호, API 키 등 민감한 정보를 안전하게 관리하는 Secrets Manager의 핵심 개념과 실무 활용법을 배워봅니다. 초급 개발자도 쉽게 따라할 수 있도록 실전 예제와 함께 설명합니다.