반응형

Custom 데이터로 YoloV5 모델 학습하기 1편에 이어 Test / 모델 성능평가 에 대해 알아보자.

yolov5 학습 튜토리얼 1편 -

[AI/Self-Study] - yolov5 학습 튜토리얼 1

 

yolov5 학습 튜토리얼 1

Custom 데이터로 YoloV5 모델 학습하기 2편 - [AI/Self-Study] - yolov5 학습 튜토리얼 2 (+ mAP, IoU 설명 / Test 와 Inference) 1. 환경 세팅 1) YoloV5 깃헙 레포지토리 clone $ git clone https://github.com/..

lynnshin.tistory.com

 

1. Test 코드 돌리기

1) yaml 파일 만들기 

 

data 폴더 안에 coco.yaml 이라는 파일이 있는데 이와 비슷하게 test.yaml 파일을 만들어 주면 된다. 

# train and val data as 1) directory: path/images/, 2) file: path/images.txt, or 3) list: [path1/images/, path2/images/]
val: /data/images/valid
test: /data/images/test

# number of classes
nc: 1

# class names
names: ['wheat']

 

2) run test.py 

$ python test.py --weights 'runs/train/exp20/weights/best.pt' --data '/data/test.yaml' --img 640 --task 'test'

인자값 설명

  • --weights: 내가 학습한 모델의 best weight를 넣어주면 된다.
    • 학습 정보가 runs/train/exp... 안에 들어 있음으로 학습한 exp 폴더에 들어가서 weights 폴더 안에 보면 last.pt (마지막 epoch 의 weight), best.pt (제일 성능 좋은 epoch의 weight (best mAP) 가 들어있다.
    • 내가 학습시킨 weight 말고 그냥 pretrain weight를 넣어줄수도 있음 ( 예) yolov5x.pt )
  • --data: 위에서 만들어준 yaml 파일 경로 넣어주기
  • --img: 이미지 사이즈 (보통 학습 할 때 쓴 이미지 사이즈와 통일)
  • --task: 설정 안해주면 default 로 'val'이 들어가있다. 위에 만든 yaml 파일에서 val 경로에 있는 데이터로 테스트 결과를 보고싶으면 default로 놔두고, test 경로에 있는 데이터로 테스트 결과를 보려면 --task 'test' 를 해줘야함
  • --batch-size: default는 32
  • --save-txt: 라벨 결과값을 txt 파일로 저장해준다 -> runs/test/exp4/labels/IMG_001.txt ... 이런식
  • --save-json: 라벨 결과값을 coco annotation json 파일 포맷으로 저장
  • --save-conf: txt 파일 저장할 때 confidence 값도 함께 저장
  • --project / --name : 결과값 저장하는 폴더는 default로 runs/test 인데, --project 그리고 --name 를 지정해주면 runs/test => project/name 로 저장하는 경로가 바뀐다.
  • --device : GPU/CPU 세팅 => 0 / 0,1,2,3 / cpu 이런식으로 바꿔주면 됨

 

 

3) 위에 코드를 돌리면 아래와 같이 결과값이 나온다. 이제 그 결과값을 해석해 모델의 성능을 평가하면 된다.

 

결과 예시

 

 

2. 모델 성능평가

Yolo에서는 모델의 성능(정확도)을 Mean average precision(mAP)를 통해 확인한다. mAP가 높을수록 정확하고, 작을수록 부정확하다.

 

Average precision(AP) 계산을 할 때 precision-recall 곡선을 사용하는데, 관련 내용들을 이해하기 위해서 IoU, precision, recall, precision-recall 의 개념을 먼저 살펴봐야 한다. 

 

 

1) Intersection over union (IoU)

IoU는 어떤 데이터셋에 대하여 객체 검출하는 모델의 정확도를 측정하는 평가지표이다. 이는 합성곱 신경망을 사용한 객체 검출 모델 Convolutional Neural Network detectors (R-CNN, Faster R-CNN, YOLO, etc.)을 평가할 때 사용된다.

 

IoU로 평가하기 위해서는 ground-truth bounding box (정답 바운딩 박스) 와 모델로부터 예측된 predicted bounding box 가 필요하다. 

 

예를 들어 아래 사진에서 초록색 박스는 (사람이 사물의 위치에 라벨링한) 정답 바운딩 박스이고, 빨간 박스는 모델이 예측한 바운딩 박스다. 

 

bounding box 예시

 

IoU 계산 방법은 두 바운딩 박스를 가지고 IoU = 교집합 영역 넓이 / 합집합 영역 넓이 를 계산해 나온 값이 IoU이다.

 

IoU 계산 방법

 

Classification (분류) 문제같은 경우에는 모델이 예측한 클래스 라벨 값이 실제 클래스 라벨값과 같냐 다르냐만 따지면 된다. 하지만 객체 검출에서는 모델이 예측한 바운딩 박스의 x,y 좌표들이 정답 바운딩 박스의 x,y 좌표들과 정확히 일치하는 경우는 거의 없다. 그래서 IoU를 사용하는 것이다. 

 

IoU 는 모델이 예측한 바운딩 박스가 정답 바운딩 박스와 겹치는 부분이 많으면 많을 수록 rewards 를 준다.

아래 사진과 같이 빨간색 (예측된) 바운딩 박스과 초록색 (정답) 바운딩 박스와 겹치는 부분이 많을 수록 점수가 높다. 

이렇게 IoU를 사용함으로써 x,y 좌표가 정확히 일치하느냐를 보는게 아니라 예측한 바운딩 박스가 정답과 최대한 가까워지도록 학습하는 것이다.

 

IoU 값 비교

 

두 box의 크기가 동일할 경우 두 box의 2/3는 겹쳐줘야 0.5의 값이 나오기 때문에 R-CNN에서는 보통 IoU의 threshold 값으로 0.5를 잡아서 (= IoU 값을 계산해 0.5 이상인 경우) 해당 region을 객체로 바라보고 ground truth와 같은 class로 labelling을 한다고 한다.

 

⭐⭐⭐

IoU가 mAP를 이해하는데 필요한 이유가 뭘까? 바로 다음에 나올 precision 과 recall을 계산 할 때 물체를 검출했을 때 옳게 검출되었다와 옳게 검출되지 않았다를 구분 해주는 기준이 필요한데 그 기준으로 IoU가 쓰인다. 

 

예를 들어 논문을 보면 데이터 셋마다 mAP 평가를 했을 때 차이가 난다.

 

예시) MS COCO mAP 기준으로 YOLOv3 모델은 33.0 < RetinaNet 모델은 40.8
         Pascal VOC mAP (AP50) 기준으로 YOLOv3는 57.0 ≒ RetinaNet 61.1 (속도는 YOLOv3가 4배 빠름)

 

Pascal VOC는 IoU(Intersection over Union) > 0.5 인 detection은 true, 그 이하는 false로 평가하는 방식을 사용하고, COCO는 IoU>0.5, IoU>0.55, IoU>0.6, …, IoU>0.95 각각을 기준으로 AP를 계산한 후 이들의 평균을 취하는 방식을 사용한다.

 

yoloV5의 test.py 코드를 돌리면 아래와 같은 결과가 나온다.

그 중 오른쪽 두 컬럼을 보면 mAP@.5,  mAP@.5 : .95 가 있다. 이 것이 위에서 말한 Pascal VOC의 mAP 평가 방식과 COCO의 mAP 평가 방식이다.

We evaluate the mAP averaged for IoU ∈ [0.5 : 0.05 : 0.95] (COCO’s standard metric, simply denoted as mAP@[.5, .95]) and mAP@0.5 (PASCAL VOC’s metric). mAP@[.5,.95]) means average mAP over different IoU thresholds, from 0.5 to 0.95, step 0.05 (0.5, 0.55, 0.6, 0.65, 0.7, 0.75, 0.8, 0.85, 0.9, 0.95).

 

출처 : darkpgmr.tistory.com/179

 

yolov5 test.py 결과값

 

2) Precision , Recall

Precision (정밀도) 는 모델이 예측한 결과의 Positive 결과가 얼마나 정확한지를 나타내는 값이다.

Recall (재현율) 은 모델의 예측한 결과기 얼마나 Positive 값들을 잘 찾는지를 측정하는 것이다.

 

예를 들어, 암 진단의 경우에 대해 Precision과 Recall은 다음과 같이 정의 된다.
Precision (정밀도) : 양성으로 예측된 것 중 진짜 양성의 비율 (신약의 효과 측정) / 모델이 정답이라고 한 것 중에 진짜 정답의 비율

Recall (재현율) : 진짜 양성 중 양성으로 예측된 비율 (암 진단) / 진짜 정답 중에 모델이 정답이라고 한 것의 비율

 

https://m.blog.naver.com/taewwon/221593257274

 

⭐⭐⭐

Object detection의 관점에서 보자면, recall과 precision의 관계는 아래와 같이 정의 가능하다.

Precision (정밀도) : 검출 결과들 중 옳게 검출한 비율을 의미한다.

예를 들어 알고리즘이 사람 10명을 검출했는데 그 중 4명을 옳게 검출해낸 것이라면 Precision은 4/10 = 0.4이다.

Recall (재현율) : 실제 옳게 검출된 결과물 중에서 옳다고 예측한 것의 비율을 의미한다.
예를 들어 10개의 옳게 검출된 결과물 중에서 옳다고 예측한 것이 5개라고 예측했다면 recall은 5/10 = 0.5가 된다.

 

 

https://seongkyun.github.io/study/2019/01/15/map/

 

Precison만으로 물체 검출 알고리즘의 성능을 평가하는 것은 적절하지 않다. 또한 Recall만으로 성능을 평가하는 것도 적절하지 않다. Precision과 Recall은 항상 0과 1사이의 값으로 나오게 되는데, Precision이 높으면 Recall은 낮은 경향이 있고, Precision이 낮으면 Recall이 높은 경향이 있다. 따라서 두 값을 종합해서 알고리즘의 성능을 평가해야 하고, 그래서 나온 것이 precision-recall 곡선 및 AP 다. (bskyvision.com/465)

 

물체를 검출했을 때 옳게 검출되었다와 옳게 검출되지 않았다를 구분해주는 기준, 즉 TP와 FP를 결정해주는 기준이 바로 intersection over union(IoU)이다.

 

출처 : seongkyun.github.io/study/2019/01/15/map/

 

 

3)  Precision-recall 곡선(PR 곡선)

PR 곡선은 confidence threshold 값에 따른 precision과 recall의 값의 변화를 그래프로 표현한 것이다.

 

confidence는 알고리즘이 검출한 것 (detect 한 것)에 대해 얼마나 정확하다고 생각하는지 알려주는 값인데, 만약 어떤 물체를 검출했을 때 confidence 레벨이 0.99라면 알고리즘은 그 물체가 검출해야 하는 물체와 거의 똑같다고 생각하는 것과 같다.

 

검출된 모든 바운딩 박스들을 confidence 내림차순으로 정렬을 한다. 그리고 각각 precision과 recall 값을 계산한다.

 

***

|  precision 은 "of all bounding box predicitions, what fraction was actually correct?" 모든 예측된 바운딩 박스들 중에서 맞은

|  것의 비율은? 이고,

|  recall 은 "of all target bounding boxes, what fraction did we correctly detect?" 전체 타켓 바운딩 박스 (정답 바운딩 박스) 들

|  중에서 우리가 검출한 것의 비율은 (맞춘 것은)? 이다.

 

https://hyeonnii.tistory.com/284

 

그리고 위의 표를 x축은 recall 값, y축은 precision 값으로 곡선을 그리면 그 곡선이 PR 곡선이다.

 

https://hyeonnii.tistory.com/284

 

 

4) Average Precision (AP)

precision-recall 그래프는 어떤 알고리즘의 성능을 전반적으로 파악하기에는 좋으나 서로 다른 두 알고리즘의 성능을 정량적으로(quantitatively) 비교하기에는 불편한 점이 있다.

 

Average precision은 인식 알고리즘의 성능을 하나의 값으로 표현한 것으로서 precision-recall 그래프에서 그래프 선 아래쪽의 면적으로 계산된다.

 

average precision이 높으면 높을수록 그 알고리즘의 성능이 전체적으로 우수하다는 의미이고, 컴퓨터 비전 분야에서 물체인식 알고리즘의 성능은 대부분 average precision으로 평가한다.

 

 

 

 

5) Mean Average Precision (mAP)

이제 위에서 배운 개념들을 적용해서 mAP를 구해보자.

 

강아지를 검출하는 문제에서 아래와 같은 test set 이 있다고 가정하자. mAP를 구하기 위해서는

 

1. 모델이 예측한 모든 바운딩 박스 를 가져올 것이다. 빨간 바운딩 박스는 예측 값들이고 초록색 바운딩 박스는 타켓 값 (정답 값) 들이다. 빨간 바운딩 박스를 보면 박스마다 점수가 적혀있는 것을 볼 수 있다. 이 점수는 바운딩박스가 자신이 예측한 바운딩 박스안에 객체가 있다고 믿는 확률 값 (= confidence score) 이다.

 

* YoloV5 에서 conf_thres를 인자값을 따로 지정해주지 않으면 default 0.001로 설정되어있다. 모든 바운딩 박스를 가지고 와야함으로 원래는 0으로 해야하지만, 그러면 너무 느리기 때문에 0.001로 설정했다고 한다. 이 conf_thres 값은 mAP 계산만을 위한 값이다. 그러므로 inference code (detect.py) 를 돌릴 때는 conf_thres 값이 기본 0.25로 설정되어 있다 (mAP 계산 용이 아닌 예측 용). 이 경우에는 더 높은 값으로 변경해도 상관없다 (0 ~ 1 사이).

 

 

Image 1 을 먼저 보면, confidence score 가 각각 0.3, 0.6, 0.7인 3개의 바운딩 박스가 있다. 이 바운딩 박스들이 True Positive (TP) / False Positive (FP) 인지 평가한다고 한다면, confidence score 가 0.3인 첫번째 바운딩 박스는 어떤 타겟 바운딩 박스와도 겹치는 부분이 없다. 그러므로 첫번째 바운딩 박스는 FP 이다.

Confidence score 가 0.6인 두번째 바운딩 박스는 강아지의 한 부분을 검출하긴 했지만 0.5보다 작은 IoU를 가지고 있음으로 FP 이다.

Confidence score 가 0.7인 세번째 바운딩 박스를 보면 타켓 바운딩 박스와 겹치는 부분이 많고, 0.5보다 큰 IoU를 가지고 있음으로 TF 이다. 

 

 

Image 2 는 하나의 예측된 바운딩 박스를 가지고 있고, TP이다.

 

 

Image 3 는 세개의 예측된 바운딩 박스를 가지고 있고, 이미지의 위쪽에 위치한 2개의 바운딩 박스는 FP 이고 , confidence 가 0.9인 바운딩 박스는 0.5보다 큰 높은 IoU를 가지고 있음으로 TP이다.

 

 

2. 이제 테스트 셋의 모든 바운딩 박스를 하나의 표로 정리해보면 아래와 같다.

그리고 우리는 이 바운딩 박스들을 내림차순으로 정렬할 거다.

 

 

여기서 중요한 metrics 인 precision 과 recall를 다시 요약해보면

true positives (TP) 는 예측된 바운딩 박스들 중에서 타켓 (정답) 바운딩 박스와의 IoU가 0.5 이상으로 겹치는 박스들이다. false positives 는 그렇지 않은 바운딩 박스들로 옳지않은 = 틀린 바운딩 박스들이다. 

false negatives (FN) 는 타켓 바운딩 박스에 대해 예측된 바운딩 박스가 없는 것을 의미하고, true negatives 는 타켓 바운딩 박스가 없는 곳에 예측된 바운딩 박스도 없는 것을 의미한다.

 

precision 은 "of all bounding box predicitions, what fraction was actually correct?" 모든 예측된 바운딩 박스들 중에서 맞은 것의 비율은? 이고,

recall 은 "of all target bounding boxes, what fraction did we correctly detect?" 전체 타켓 바운딩 박스 (정답 바운딩 박스) 들 중에서 우리가 검출한 것의 비율은 (맞춘 것은)? 이다.

 

이렇게 매우 다른 두 metrics는 둘이 반대인 경우가 많다 (Precision이 높으면 Recall은 낮은 경향이 있고, Precision이 낮으면 Recall이 높은 경향)

 

 

3. 이제 모든 결과값에 대해 precision 과 recall 를 계산한다.

지금 우리가 가지고 있는 테스트 셋은 총 4개의 타겟 바운딩 박스를 가지고 있다. 

아래 사진에서 첫 행부터 보면, 첫 번째 결과값은 TP 임으로 precision 은 1/1 (현재까지 예측된 바운딩 박스 = 1, 맞춘 개수 = 1) 이고, recall 은 1/4 (총 타겟 바운딩 박스 = 4, 맞춘 개수 = 1) 이다.

두번째 결과값은 FP 임으로 precision 은 1/2 (현재까지 예측된 바운딩 박스 = 2, 맞춘 개수 = 1) 이고, recall 은 그대로 1/4 (총 타겟 바운딩 박스 = 4, 맞춘 개수 = 1) 이다.

이런식으로 표를 채우면 된다.

 

4. 위에서 계산한 값들로 Precision-Recall graph (PR 곡선)을 그린다.

 

recall 값이 x 이고, precision 값이 y 일 때, 아래와 같은 곡선이 나온다.

 

 

5. PR 곡선의 아래 영역을 계산한다. ( = AP )

 

 

6. 지금까지 한 내용은 강아지 라는 하나의 클래스에 대해서만 PR 곡선 아래 영역을 계산한 것이다. 하지만 실제 케이스에서는 이렇게 하나의 클래스가 아니라 모든 클래스를 계산해야한다.

클래스가 하나가 아니라 강아지, 고양이 이렇게 두개가 있다고 생각해보자.

 

고양이 클래스의 AP 가 0.74 이고,

강아지 클래스의 AP 가 0.533 이면

mAP 는 모든 클래스의 (강아지 + 고양지) 평균인 0.6365가 된다.

 

 

7. 지금까지의 내용은 IoU threshold 를 0.5 로 특정했을 때 이야기이다. 하지만 실제 케이스에서는 이런 계산을 많은 IoU 값에 대해 반복해야된다. 예를 들어, IoU threshold 값이 0.5, 0.55, 0.6, ..., 0.95 일 때 mAP 값을 각각 계산하고, 그 값들을 평균 낸 값이 우리가 구하고 싶은 최종 값이 되는것이다. 이걸 mAP@0.5:0.05:0.95 라고 쓴다 (논문에서 자주 보임).

 

 

출처 : youtu.be/FppOzcDvaDI

 

 

참고 : 

en.wikipedia.org/wiki/Jaccard_index

ballentain.tistory.com/12

www.pyimagesearch.com/2016/11/07/intersection-over-union-iou-for-object-detection/

darkpgmr.tistory.com/162

반응형