# 1st Solution

안녕하세요 캐글코리아!
먼저 좋은 대회 마련해 주신 KaKR 운영진분들께 감사의 인사를 드리고 싶습니다.
저는 학부생이어서 학기중에는 바빠 이전 대회들은 참여하지 못하고 있었습니다. 우연히 이번 competition과 방학이 겹쳐서 이렇게 참여하게 되었습니다. 이 글을 통하여 저의 solution과 score을 얻기 위해서 어떤 방식들을 시도했는지 공유하겠습니다! 다른 순위권 분들도 좋은 solution과 시행착오들을 공유해 주셔서 다같이 배울 수 있는 글들을 남겨주셨으면 좋겠습니다!
Baseline model : Efficientnet-B5
Preprocessing
Using Bounding Box : 
저는 처음에 bounding Box로 crop된 image를 사용했지만 아래의 두 github에서는 crop하지 않은 image를 input으로 주는 것이 성능이 더 좋다고 하였습니다.
[https://github.com/jianshen92/stanford-car-grab-challenge](https://github.com/jianshen92/stanford-car-grab-challenge)
[https://github.com/morganmcg1/Projects/tree/master/stanford-cars](https://github.com/morganmcg1/Projects/tree/master/stanford-cars)
하지만, Public score 0.93정도 이상에서는 그렇게 큰 효과가 없었습니다. 또한, cutout을 적용하면 crop된 image가 성능이 더 높은 모습을 보여주었습니다. 그래서 저는 Bounding box로 crop된 이미지를 input으로 사용했습니다.
저는 Image를 단순하게 resize하는 방식을 사용했는데 위의 github에서는 squeeze method를 사용하면 더 좋은 성능을 보여준다고 합니다. 하지만, 저는 이것을 구현하지 못해서 적용하지 못했습니다.
Augmentation
: 
(saewon님의 kernel을 참고하였습니다.)
Random Resized Crop, Random Horizontal Flip, Random Rotation, AutoAgumentation(CIFAR-10), Normalize, Random Erasing(cutout)을 적용하였습니다. 여기에 mixup을 적용시켰습니다.
Cutmix를 mixup대신 적용시켜 보았지만, 저는 mixup을 사용했을 때 성능이 더 좋게 나타났습니다. 
mixup의 alpha값은 0.2, 0.4, 1.0을 사용해보았는데 1.0에서 성능이 가장 좋게 나왔습니다.
rotation은 30도를 주었고 resized crop은 (0.8, 1.0) 다른 것들은 default 값으로 적용시켰습니다.
Sampler :
Class의 이미지 수들의 불균형이 존재했습니다. 균형을 맞추기 위해서 oversampling 방식을 통하여 한 epoch을 당 주어지는 class의 image 수를 같게 맞추었습니다.
Loss :
FocalLoss를 gamma를 0.5, 2, 3을 시도해 보았습니다. gamma가 0.5일 때 성능이 가장 좋았습니다. 하지만, 이것보다 그냥 cross entropy loss가 더 좋은 성능을 보여주었습니다. (제가 구현을 잘못한 것인가요…ㅠㅠ Focal loss가 더 좋을 것으로 예상을 했었는데…) 최종적으로 저는 loss로 cross entropy를 사용했습니다.
Label smoothing을 적용해서 실험해 보았지만 그럴듯한 성능 향상을 보여주지 않았습니다. 
(Triplet loss구현을 시도해 보았지만, 시간 부족을 구현을 완료하지 못했습니다. 혹시 해보신 분 있으면 결과를 남겨주시면 좋겠습니다.)
Model :
저는 Efficientnet-B7, B6, B5, PNASNet, NASNet을 사용했습니다. 각 model head에 dropout(p=0.4)을 추가해서 사용했습니다. (IIdoo kim님이 discussion에 올렸던 model은 너무 train하기에 무거워서 결국 사용하지 못했습니다.)
WS-DAN(Weakly Supervised Data Augmentation Network)이라는 아주 흥미로운 구조를 실험해 보았습니다. 이것을 Efficientnet-B7 model에 적용시켰습니다. Training 시간은 3배로 걸리지만 성능은 크게 개선되지 않아서 이 구조를 사용하지 않게 되었습니다.
Scheduler :
초반에는 CosineannealingLR, MultistepLR, StepLR을 사용해 보았습니다. 이중에서 적절한 값을 찾아본 결과 MultistepLR이 가장 좋은 성능을 보여주어서 이것을 사용했습니다. 후반기에 최종 model을 train할 때는 SuperConvergence라는 scheduler를 사용하여 train을 하였습니다.
Optimizer :
다양한 optimizer를 baseline에 실험해 보았는데 AdamW가 가장 성능이 좋았습니다. PNAS, NAS는SGD + momentum이 성능이 좋은 모습을 보여주어 이것을 사용하였습니다.
Train Process:
Efficientnet-B7, B6, B5는 lr=0.00028로 50 epoch train후 max_lr=0.00028로 SuperConvergence + AdamW로 60 epoch train했습니다.
PNAS, NAS는 lr=0.0042, max_lr=0.0042로 위와 같은 방식으로 optimizer만 바꿔준 후 train했습니다. weight저장은 valid set에서 f1-score가 가장 좋은 weight를 저장했습니다.
Test-Time-Augmentation :
tta를 5번 적용하였습니다. 적용한 augmentation은 Random Resized Crop, Random Horizontal Flip, Random Rotation입니다. Rotation은 5를 주었고 나머지는 train때와 같게 주었습니다.
Ensemble :
6 fold cross validation을 사용하였습니다. 또한 앞에서 언급한 Efficientnet-B7, B6, B5, PNAS, NAS model을 soft-voting을 하였습니다.
성능으로는 B7>B6>B5>PNAS>NAS 순이었습니다. (Public score 기준)
(결론적으로 총 30개의 weight를 사용했네요… 6.5G정도 되네요)
최종 score  “ Public : 0.96604,  Private : 0.96058 ”
Privat score가 가장 좋은 모델은 Efficientnet-B7 model이네요 0.96132나왔습니다.