{"cells":[{"metadata":{},"cell_type":"markdown","source":"\n안녕하세요 CONTEXT 라는 팀 이름으로 참가해서 private 16등한 커널 공개하겠습니다.\n\n저희 팀원은 4명으로 대학원생, 대학생, 기획자, 개발자로 구성되어있고 인공지능, 딥러닝 관련 연구소, 학교, 직장에서 일하며 스터디하는 모임입니다.\n\n각자 전문 분야가 다르지만 구글 우산이 탐나서 Kaggle kr 3rd competition에 참가하게 되었고 이번 대회를 통해 각자 실력도 쌓으며 정말 좋은 경험이 된 것 같습니다.\n\n이번 기회를 계기로 다른 국제 kaggle competition도 준비중에 있고 kaggle kr 4번째 대회가 나오면 참가할 예정입니다.\n\nInference 커널 작성은 처음이라 부족한 부분이 많이 있겠지만 잘봐주시면 감사하겠고 테스트를 할 때마다 수치 기록 정리를 소흘히 해서 빠진 부분도 있지만 잘 읽고 도움이 된다면 감사하겠습니다.\n\n\n\n"},{"metadata":{},"cell_type":"markdown","source":"**1. Dataset & Data augmentation**\n\n1) 데이터셋은 본 대회에서 제공한 것만 사용했으며 허태명님이 제공해주신 crop 방법을 이용을 했으며 off line augmentation으로 gray scale(gray scale 변환후 3채널로 stack) 이미지를 포함하여 학습을 진행했습니다.\n\nvalidation은 초기에만 각 클래스별 5개씩 빼서 validation dataset을 구성한 뒤 실험을 진행하고 이후에는 마지막에는 validation data를 다시 train data로 합쳐서 epoch를 크게 준 뒤 train acc가 saturation될 때까지 학습을 진행시켰습니다.\n\n2) Data augmentation은 차량 데이터셋에 어떤 augmentation이 좋은지 모르기 때문에 pytorch에서 쉽게 이용할 수 있는 rotate, scale, crop, color jittering 등을 기본 resnet18모델을 바탕으로 실험을 진행해서\n\nrotate(15), resizedcrop, horizontalflip 3가지를 기본으로 사용했었습니다.\n\n이후 autoaugmentation (https://github.com/DeepVoltaire/AutoAugment) 의 ImageNetPolicy를 이용하여 동일 조건을 바탕으로 실험을 해보니 성능이 약 0.5%증가하여 이후로는 autoaugmentation만 사용했습니다.\n![](http://)\n사용방법은 위의 github url을 참고하여 아래와 같은 방법으로 transforms에 넣어주시면 됩니다.\n"},{"metadata":{},"cell_type":"markdown","source":"**2. Network & Implementation details**\n\n기본적인 실험 검증(optimizer, initial learning rate, augmentation 등)은 앞에서 말씀드렸듯이 resnet18을 통해 검증을 해서 최적화를 맞추었습니다.\n\nOptimizer도 pytorch에서 가능한 sgd, adam, adgrad 등 여러가지 등을 시도해 보았고 최종적으로는 sgd + momentum(0.9)을 사용했습니다.\nInitial learning rate와 learning rate는 0.005, loss  감소가 5epoch 이상 없을시 *0.1로 설정했습니다.\n\n이런식으로 최적화를 맞춘 뒤 https://paperswithcode.com/sota/image-classification-on-imagenet, pytorch-hub(https://pytorch.org/hub)를 참고하여 가능한한 많은 네트워크를 실험하였습니다.\n\n실험에 사용한 네트워크 목록은 다음과 같습니다.\n\n* VGG16\n* Inception-v3\n* DenseNet-161\n* DenseNet-201\n* ResNet-18\n* ResNet-101\n* ResNext\n* resnext50_32x4d\t\n* resnext101_32x8d\t\n* resnext101_32x16d\n* resnext101_32x32d\n* resnext101_32x48d\t\n* FixResNeXt-101 32x48d\n* EfficientNet-b5\n* EfficientNet-b7\n\n실험 결과 resnet101계열(fix, next 포함)을 주로 사용했습니다.\n\n"},{"metadata":{},"cell_type":"markdown","source":"**3. Ensemble**\n\nEnsemble은 각 클래스별 영상의 predicted score을 기본으로 하며 weight를 바꿔서 주며 submission 하였습니다.\n\nPublic 0.96126, private 0.95343을 한 것은 resnext101_32x8d+DANN, resnext101_32x8d, resnext101_32x8d, resnext101_32x32d+autoaug, resnext101_32x8d+autoaug, fixresnext101_32x48d 5가지 모델을 앙상블 한 결과이고,\n\n(en_6_10.csv)\n\npublic 0.95839, private 0.96181을 한 것은 resnext101_32x8d+DANN, resnext101_32x8d+autoaug,  fixresnext101_32x48d, resnext101_32x32d+autoaug 의 4가지 모델을 앙상블 한 결과 입니다.\n\n(en_4_10.csv)\n\n아래 코드를 통해서 앙상블을 진행했지만 4개 모델을 한꺼번에 앙상블했더니 캐글노트북에서는 메모리문제 때문에 1개의 모델만 돌려보겠습니다.\n검증이 필요하다면 주석처리된 부분을 풀어서 같이 돌리면 됩니다."},{"metadata":{"trusted":true},"cell_type":"code","source":"import os\npath = '../input/kaggle_csv'\nprint(os.listdir(path))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import os\nimport numpy as np\nimport glob\nfrom PIL import Image, ImageEnhance, ImageOps\nimport torch\nfrom torch import nn, cuda\nfrom torch.autograd import Variable \nimport torch.nn.functional as F\nimport torchvision.models as models\nfrom torchvision import datasets, models, transforms\nfrom torch.utils.data import Dataset, DataLoader\n\n\ndevice = torch.device(\"cuda:0\")\n\n\ndef test_model():\n\n    data_transforms = transforms.Compose([\n        transforms.Resize([224, 224]),\n        transforms.ToTensor(),\n        transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])\n    ])\n    cuda0 = torch.device('cuda:0')\n    cuda1 = torch.device('cuda:1')\n\n    model_ft = torch.load('../input/kaggle_csv/renext8d_DANN.pth', map_location='cuda:0')\n    #model_4 = torch.load('../input/kaggle_csv/renext8d_aug_no_gray_100_real.pth',map_location='cuda:0')\n    #model_5 = torch.load('../input/kaggle_csv/save_Fixrenext101.pth', map_location='cuda:0')\n    #model_6 = torch.load('../input/kaggle_csv/renext32d_aug_gray_40.pth', map_location='cuda:0')\n\n    path_test = '../input/kaggle_csv/test/test'\n    image_list = os.listdir(path_test)\n    \n    predictions = []\n    outputs = []\n    for i, image in enumerate(image_list):\n        path_image = os.path.join(path_test, image)\n        image = Image.open(path_image)\n        imgblob = data_transforms(image)\n        imgblob.unsqueeze_(dim=0)\n        imgblob = Variable(imgblob)\n        imgblob = imgblob.cuda(cuda0)\n        #print(imgblob.shape)\n        torch.no_grad()\n\n        output = model_ft(imgblob)\n        #output4 = model_4(imgblob)\n        #output5 = model_5(imgblob)\n        #output6 = model_6(imgblob)\n\n\n        #sum =output+output4*1.5+output5+output6*1.5\n        sum = output\n\n\n        prediction = int(torch.max(sum.data, 1)[1].cpu().numpy())\n\n        prediction = prediction +1\n        predictions.append(prediction)\n\n        if i%100 ==0:\n            print(i)\n    return predictions\n        \n\npredictions = test_model()\n\n\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import pandas as pd\nsubmission = pd.read_csv(os.path.join(os.getcwd(), '../input/kaggle_csv/en_4_10.csv'))\nsubmission[\"class\"] = predictions\n#submission.to_csv(\"../input/kaggle_csv/en_4_10.csv\", index=False)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]}],"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat":4,"nbformat_minor":1}