Yolov5를 이용해서 Transfer Learning에서 Early Overfitting을 방지하는 방법
Yolov5를 사용할 때, 보통 Pretrained model을 사용합니다. (small, medium, large, Xlarge.. 이번에 nano도 추가)
Pretrained Model의 경우 80개의 Coco dataset을 detect합니다.
이 80개의 모델에 내가 원하는 class가 없는 경우, transfer learning(전이 학습)을 통해서
내가 원하는 class를 학습해야 합니다.
Pretrained model이 아닌 scratch model에서 학습을 하는 경우 너무 학습이 오래 걸린다는 단점이 있고,
(체감상 pretrained model보다 적어도 두배, 많으면 세네배 이상 시간이 걸립니다. 정확한 레퍼런스는 없네요)
freeze layer를 하고 학습을 하는 경우 더 빠르게 할 수 있는 방법은 있지만,
그런 경우에는 mAP(정확도)를 희생하는 방법이기 때문에, 고려하지 않도록 하겠습니다.
연구를 하던 와중에, 다음과 같은 현상이 나타나는 것을 발견하였습니다.
보시는 바와 같이, CoCo dataset이 아닌 다른 클래스를 학습시키는 상황이기 때문에
시작과 초기 상태에서는 mAP가 낮게 나와야 하는데도 불구하고 초기 0~10개의 Epoch 구간에서 mAP가 속칭 튀는(?)
현상이 발생하였습니다.
이로 문제가 되는 부분이, yolov5에서 어느정도 시간이 흐르면서 mAP가 발전하지 않으면 EarlyStopping이라는
기능이 작용하는데, 이 때 가장 좋았던 mAP를 기준으로 작용하기 때문에, (0.5의 비중 1, 0.5:0.95의 비중 9)
앞의 튀는 학습을 잡는다는 점이었습니다.
이를 해결하기 위해, 여러 가지 방법들이 있겠지만, 가장 쉬운 방법은 patience(mAP의 개선이 없을 때 EarlyStopping을 강제하는 Epoch 수)를 늘리는 방법이었습니다.
그래서 patience를 늘려서 학습을 해보았습니다.
위 이미지에서 보시다싶이, 아마 가장 높은 것은 앞 10번째 Epoch이지만 의미가 많이 떨어지고,
앞 부분을 무시하고 생각해 볼 때 오히려 100번째 Epoch에서 가장 높은 Epoch라고 생각할 수 있습니다.
물론 Validation Loss를 봐야지 좀 더 좋은 판단을 할 수 있겠지만요.
하지만 EarlyStopping이 앞 10번째 Epoch를 잡기 때문에 100번째 Epoch를 잡지 않습니다.
게다가, last.pt는 마지막을 잡죠.
결국 우리가 원하는 100번째 Epoch을 잡으려면, 모든 Epoch마다 체크포인트를 잡는 수밖에 없습니다.
이를 해결하기 위해서, 저는 ignore-epoch라는 parameter를 대입해서,
앞의 epoch들을 best.pt로 잡지 않도록 하는 코드를 수정하였지만,
Earlystopping이 되지 않는 등 에러가 발생하였습니다.
이런 에러를 잡기 위해서는, train.py를 직접 작성한 Glen Jocher에게도 물어봤지만,
Glen은 자기는 딥러닝 best practice에 나오지 않은 parameter는 넣고 싶지 않다고 거부했습니다.
그래서 이를 고치기 위해서, warmup epoch를 사용하는 방법을 사용하고자 합니다.
warmup epoch란, 처음 learning rate이 엄청 큰 값부터 떨어지는 방법을 사용하는데,
warmup epoch동안 learning rate을 아주 작은 값으로 서서히 올라가는 방법을 정함으로서
early overfitting을 방지합니다.
레퍼런스 : https://stackoverflow.com/questions/55933867/what-does-learning-rate-warm-up-mean