[OD] 객체 탐지(Object Detection) 성능 판단 지표 정리 | IOU, mAP, FPS, FLOPS
IoU
IoU (Intersection Over Union)은 모델이 얼마나 객체 탐지를 정확하게 했는지, 즉 모델이 찾은 객체의 위치가 실제 데이터셋의 ground truth와 겹치는지를 확인하는 지표 입니다. 영문 명칭에서 확인할 수 있는 것처럼 겹치는 부분(Intersection)을 전체 면적(Union)으로 나눈 값으로 계산할 수 있습니다.
IoU xx (예를 들어, IoU 50)와 같은 표현은 IoU 값을 xx(%)를 기준으로 하는 것이며, xx라는 임계값에 따라 제대로 예측했는지 결정됩니다. 이는 뒤에 다룰 mAP에서 까지 확장되는데, mAP 50은 IoU 임계값을 50으로 객체를 탐지하여 성능을 측정합니다.
mAP
mAP은 객체 탐지 문제에 흔히 사용되는 성능 지표로 mean average precision의 줄임말 입니다. mAP의 의미에 대해 결론부터 얘기하자면, 각 클래스의 AP(average precision)의 평균을 의미합니다. 한 클래스에 여러 데이터가 있으니 average를 계산하고, 여러 클래스가 존재하니 이에 대한 평균을 계산한다는 의미일텐데, mAP에 대해 이해하기 위해서는 정밀도(precision)을 알아야 합니다.
precision
정밀도는 True라고 예측한 것 중 실제 True인 것의 비율을 말합니다. 한글 명칭인 정밀도의 의미(동일한 조건에서 여러 번 반복 측정할 경우 측정값이 얼마나 가깝게 나오는지)를 생각해볼 때 예측한 것들 중 얼마나 맞추느냐로 이해할 수 있습니다. 함께 나오는 개념으로 재현율(recall)이 있는데, 이는 정답 중 얼마나 잘 맞추느냐로 이해할 수 있습니다.
PR Curve와 AP
precision과 recall은 서로 관련이 있다보니, 함께 그래프를 나타내는 경우가 많은데 이를 PR Curve라고 합니다. 아래의 좌측 그래프 처럼 PR Curve는 recall이 증가함에 따라 precision은 (정확히 반비례하지는 않지만) 떨어지는 것처럼 그림이 그려지게 되는데 이를 값이 일정한 함수로 바꿔서 아래 면적을 계산하면 AP(average precision)이라고 합니다.
이렇게 나온 AP는 하나의 클래스에 대한 값이고, 데이터셋마다 개별의 클래스가 있기 때문에 이를 평균해서 구한 값이 mAP입니다.
속도 지표
객체 탐지는 그 활용(자율주행, CCTV 등) 특성에 따라 속도가 중요한 경우가 많습니다. 따라서, 속도에 대한 지표도 측정이 필요한데, 대표적으로 FPS와 FLOPS가 있습니다.
FPS
FPS는 Frames Per Second의 약자로 초당 프레임수를 이야기합니다. 게임에서도 많이 언급되는 개념인데, 1초라는 단위 시간 동안 얼마나 많은 이미지들이 있는지를 의미합니다. FPS가 높을수록 1초 안에 더 많은 이미지가 있고, 이는 더욱 자연스러운 모션을 구현할 수 있게 됩니다. 객체 탐지에서 FPS는 초당 처리할 수 있는 이미지 수를 의미하게 됩니다. 객체 탐지에서 FPS 측정하는 방법은 다음과 같이 정의할 수 있습니다. [3]
FPS = 처리한 프레임(이미지) 수 / 처리 시간
위 정의를 바탕으로 아래와 같이 코드를 만드는 것이 가능합니다.
import time
num_frames = len(input_images)
start_time = time.time()
# 객체 탐지 수행 코드 (예시)
for i in range(num_frames):
model.detect_objects(input_images[i])
end_time = time.time()
processing_time = end_time - start_time
fps = num_frames / processing_time
FLOPS
FLOPS는 Floating Point Operations의 약자로 모델이 얼마나 빠르게 동작하는지 측정하는 지표입니다. 곱하기, 더하기, 빼기와 같은 연산량의 횟수로 계산이 가능합니다. 주요 연산들의 FLOPS를 대략적으 계산하는 방법은 다음과 같습니다.[4]
- Convolution layer : 입력 채널 x 출력 채널 x 커널 높이 x 커널 너비 x 출력 특징맵 높이 x 출력 특징맵 너비
- Fully Connected layer : 2 x 입력 수 x 출력 수
이러한 연산들이 여러 개가 중첩되는 경우 전체의 합을 통해 해당 모델의 FLOPS를 계산할 수 있습니다. 하지만, torch 계열의 fvcore의 FlopCountAnalysis를 통해 간편하게 볼 수 있습니다.
import torch
from fvcore.nn import FlopCountAnalysis
# 모델 정의
model = MyObjectDetectionModel()
# 입력 텐서 정의
input = torch.randn(1, 3, 256, 256)
# FLOPS 계산
flops = FlopCountAnalysis(model, input)
print(f"Total FLOPS: {flops.total()}")
참고자료
[1] https://pyimagesearch.com/2016/11/07/intersection-over-union-iou-for-object-detection/
[2] 송원호. "Object Detection Overview". 부스트캠프
[3] https://blog.roboflow.com/what-is-fps/
[4] https://medium.com/@pashashaik/a-guide-to-hand-calculating-flops-and-macs-fa5221ce5ccc