{"cells":[{"metadata":{"_uuid":"8b3d80ed7ad56834d70ed4d6e012f46257579e07","trusted":true},"cell_type":"code","source":"# 필요한 라이브러리 import\nimport os\nimport numpy as np\nimport pandas as pd\nimport cv2\nimport matplotlib.pyplot as plt\n%matplotlib inline\n\nfrom sklearn.model_selection import train_test_split\n\nimport torch \nimport torch.nn as nn\nimport torch.nn.functional as F\nimport torchvision\nimport torchvision.transforms as transforms\nfrom torch.utils.data import TensorDataset, DataLoader, Dataset","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"b0b625dddcf44cd8db7690bf380c6cb25f555cbd","trusted":true},"cell_type":"code","source":"# 하이퍼 파라미터 설정\nnum_epochs = 7\nnum_classes = 2\nbatch_size = 128\nlearning_rate = 0.0005\n\n# GPU 설정\ndevice = torch.device('cuda:0' if torch.cuda.is_available() else 'cpu')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# GPU 설정 확인\ntorch.cuda.is_available()","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"08fbba4de055ecb31736a3e5358252ca8180244b","trusted":true},"cell_type":"code","source":"# 데이터 불러오기\nlabels = pd.read_csv('../input/train_labels.csv')\nsub = pd.read_csv('../input/sample_submission.csv')\n\n# 파일 경로 설정\ntrain_path = '../input/train/'\ntest_path = '../input/test/'","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"16937da840e0d80e2604e0d362171796516886d3","trusted":true},"cell_type":"code","source":"# Validation 구간 20개로 나눔 train : val = 19 : 1\ntrain, val = train_test_split(labels, stratify=labels.label, test_size=0.05)\nlen(train), len(val)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"64e44031b4f051993af3648cdb99877563f37d6f"},"cell_type":"markdown","source":"**Simple custom generator**"},{"metadata":{"_uuid":"a5f0097544dc230bb794e75a163196f08de0c13c","trusted":true},"cell_type":"code","source":"# 데이터셋 오버라이딩. 이것을 해줘야 속도가 빨라진다고 한다.\n# len, getitem 오버라이딩\nclass MyDataset(Dataset):\n    def __init__(self, df_data, data_dir = './', transform=None):\n        super().__init__()\n        self.df = df_data.values\n        self.data_dir = data_dir\n        self.transform = transform\n\n    def __len__(self):\n        return len(self.df)\n    \n    def __getitem__(self, index):\n        img_name,label = self.df[index]\n        img_path = os.path.join(self.data_dir, img_name+'.tif')\n        image = cv2.imread(img_path)\n        if self.transform is not None:\n            image = self.transform(image)\n        return image, label","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"cbacdb7bcd20d414d115cde200f564934b69f308","trusted":true},"cell_type":"code","source":"# train 데이터 전처리\ntrans_train = transforms.Compose([transforms.ToPILImage(),\n                                  transforms.Pad(64, padding_mode='reflect'),\n                                  transforms.RandomHorizontalFlip(), \n                                  transforms.RandomVerticalFlip(),\n                                  transforms.RandomRotation(20), \n                                  transforms.ToTensor(),\n                                  transforms.Normalize(mean=[0.5, 0.5, 0.5],std=[0.5, 0.5, 0.5])])\n\n# validation 데이터 전처리\ntrans_valid = transforms.Compose([transforms.ToPILImage(),\n                                  transforms.Pad(64, padding_mode='reflect'),\n                                  transforms.ToTensor(),\n                                  transforms.Normalize(mean=[0.5, 0.5, 0.5],std=[0.5, 0.5, 0.5])])\n\n# 데이터 셋 설정\ndataset_train = MyDataset(df_data=train, data_dir=train_path, transform=trans_train)\ndataset_valid = MyDataset(df_data=val, data_dir=train_path, transform=trans_valid)\n\n# 데이터 셋에서 배치 단위로 불러옴\nloader_train = DataLoader(dataset = dataset_train, batch_size=batch_size, shuffle=True, num_workers=0)\nloader_valid = DataLoader(dataset = dataset_valid, batch_size=batch_size//2, shuffle=False, num_workers=0)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"ac596a6914e7455f1326c01eb532d7b36b972e7f"},"cell_type":"markdown","source":"**Model**"},{"metadata":{"_uuid":"f32c84715ab1c585a56b41fc71c05c42d55bfd4b","trusted":true},"cell_type":"code","source":"# 초기에 사용했던 CNN 신경망\n# 5개의 conv layer 와 1개의 fc layer 사용\n# conv layer 마다 batch norm과 활성함수 적용\n# 활성 함수 로는 leaky ReLU 사용\n# 활성 함수 적용 이후 pooling 적용\n# Max Pooling 을 사용함\n# 모든 과정을 거쳐서 하나의 벡터로 만든후 fc layer 통과\nclass SimpleCNN(nn.Module):\n    def __init__(self):\n        # ancestor constructor call\n        super(SimpleCNN, self).__init__()\n        self.conv1 = nn.Conv2d(in_channels=3, out_channels=32, kernel_size=3, padding=2)\n        self.conv2 = nn.Conv2d(in_channels=32, out_channels=64, kernel_size=3, padding=2)\n        self.conv3 = nn.Conv2d(in_channels=64, out_channels=128, kernel_size=3, padding=2)\n        self.conv4 = nn.Conv2d(in_channels=128, out_channels=256, kernel_size=3, padding=2)\n        self.conv5 = nn.Conv2d(in_channels=256, out_channels=512, kernel_size=3, padding=2)\n        self.bn1 = nn.BatchNorm2d(32)\n        self.bn2 = nn.BatchNorm2d(64)\n        self.bn3 = nn.BatchNorm2d(128)\n        self.bn4 = nn.BatchNorm2d(256)\n        self.bn5 = nn.BatchNorm2d(512)\n        self.pool = nn.MaxPool2d(kernel_size=2, stride=2)\n        self.avg = nn.AvgPool2d(8)\n        self.fc = nn.Linear(512 * 1 * 1, 2) # !!!\n    def forward(self, x):\n        x = self.pool(F.leaky_relu(self.bn1(self.conv1(x))))\n        x = self.pool(F.leaky_relu(self.bn2(self.conv2(x))))\n        x = self.pool(F.leaky_relu(self.bn3(self.conv3(x))))\n        x = self.pool(F.leaky_relu(self.bn4(self.conv4(x))))\n        x = self.pool(F.leaky_relu(self.bn5(self.conv5(x))))\n        x = self.avg(x)\n        x = x.view(-1, 512 * 1 * 1) # !!!\n        x = self.fc(x)\n        return x","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"67522fc88f034ddb684f9fba0e154c341760d1d1","trusted":true},"cell_type":"code","source":"# 우리가 사용한 신경망 모델\n# torchvision 에서 제공하는 resnet50을 사용함\n# resnet50의 구조는 보고서에 첨부\nmodel = torchvision.models.resnet50().to(device)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"a56a159ba70e958c82e518d718be99bd41c17299","trusted":true},"cell_type":"code","source":"# 손실 함수로 교차 엔트로피 사용\ncriterion = nn.CrossEntropyLoss()\n\n# 최적화 방법으로 RMSProp 사용\noptimizer = torch.optim.RMSprop(model.parameters(), lr=learning_rate, weight_decay = 0.0001)\n\n# 두 가지 방법의 자세한 내용은 보고서에 첨부","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"dca29061dd5d6a60ba95f16dbaea70e6dc822150","trusted":true},"cell_type":"code","source":"# 모델 학습 단계\ntotal_step = len(loader_train)\nfor epoch in range(num_epochs):\n    for i, (images, labels) in enumerate(loader_train):\n        images = images.to(device)\n        labels = labels.to(device)\n        \n        # 순전파\n        outputs = model(images)\n        loss = criterion(outputs, labels)\n        \n        # 역전파 및 최적화\n        optimizer.zero_grad()\n        loss.backward()\n        optimizer.step()\n        \n        if (i+1) % 10 == 0:\n            print ('Epoch [{}/{}], Step [{}/{}], Loss: {:.4f}' \n                   .format(epoch+1, num_epochs, i+1, total_step, loss.item()))","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"9de7463bf94c03149a7121ce2bb96dc05ecf2d7b"},"cell_type":"markdown","source":"**Accuracy Check**"},{"metadata":{"_uuid":"998c3c05a3c3fb6fc7f2523dddff50496490d051","trusted":true},"cell_type":"code","source":"# 모델 검증 단계\nmodel.eval()\nwith torch.no_grad():\n    correct = 0\n    total = 0\n    for images, labels in loader_valid:\n        images = images.to(device)\n        labels = labels.to(device)\n        outputs = model(images)\n        _, predicted = torch.max(outputs.data, 1)\n        total += labels.size(0)\n        correct += (predicted == labels).sum().item()\n          \n    print('Test Accuracy of the model on the 22003 test images: {} %'.format(100 * correct / total))\n\n# checkpoint 저장\ntorch.save(model.state_dict(), 'model.ckpt')","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"c1c0709b4a1e7edea538eda5168819a7b949eedf"},"cell_type":"markdown","source":"**CSV submission**"},{"metadata":{"_uuid":"4d03acf3711d8036703041276749bbaf2ef64e71","trusted":true},"cell_type":"code","source":"# validation 데이터 셋 설정 및 불러오기\ndataset_valid = MyDataset(df_data=sub, data_dir=test_path, transform=trans_valid)\nloader_test = DataLoader(dataset = dataset_valid, batch_size=32, shuffle=False, num_workers=0)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"b85e1661e660b45486ab1b46a4d925e18f541b75","trusted":true},"cell_type":"code","source":"# validation 단계\nmodel.eval()\n\npreds = []\nfor batch_i, (data, target) in enumerate(loader_test):\n    data, target = data.cuda(), target.cuda()\n    output = model(data)\n\n    pr = output[:,1].detach().cpu().numpy()\n    for i in pr:\n        preds.append(i)\n        \n# 제출 파일 생성\nsub.shape, len(preds)\nsub['label'] = preds\nsub.to_csv('submit_KMUAI_2.csv', index=False)","execution_count":null,"outputs":[]}],"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"codemirror_mode":{"name":"ipython","version":3},"file_extension":".py","mimetype":"text/x-python","name":"python","nbconvert_exporter":"python","pygments_lexer":"ipython3","version":"3.6.6"}},"nbformat":4,"nbformat_minor":1}