{"cells":[{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"# This Python 3 environment comes with many helpful analytics libraries installed\n# It is defined by the kaggle/python Docker image: https://github.com/kaggle/docker-python\n# For example, here's several helpful packages to load\n\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n\n# Input data files are available in the read-only \"../input/\" directory\n# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory\n\nimport os\nfor dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n        print(os.path.join(dirname, filename))\n\n# You can write up to 20GB to the current directory (/kaggle/working/) that gets preserved as output when you create a version using \"Save & Run All\" \n# You can also write temporary files to /kaggle/temp/, but they won't be saved outside of the current session","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"%matplotlib inline\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\nimport os, glob, time, copy, random, zipfile\nimport matplotlib.pyplot as plt\nfrom PIL import Image\nfrom sklearn.model_selection import train_test_split\nfrom tqdm import tqdm_notebook as tqdm\n\n\nimport torch\nimport torch.nn as nn\nimport torch.optim as optim\nimport torch.utils.data as data\nimport torch.nn.functional as F\nimport torchvision\nfrom torchvision import models, transforms","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Check Current Directory\nos.listdir('../input/dogs-vs-cats-redux-kernels-edition')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Make Directory for extracting from Zip\nos.makedirs('../data', exist_ok=True)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Train_dir, Test_dir\nbase_dir = '../input/dogs-vs-cats-redux-kernels-edition'\ntrain_dir = '../data/train'\ntest_dir = '../data/test'","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Extract All Data From Zip to \"../data\" Directory\nwith zipfile.ZipFile(os.path.join(base_dir, 'train.zip')) as train_zip:\n    train_zip.extractall('../data')\n    \nwith zipfile.ZipFile(os.path.join(base_dir, 'test.zip')) as test_zip:\n    test_zip.extractall('../data')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Check Current Directory\nos.listdir('../input/dogs-vs-cats-redux-kernels-edition')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Check File Name\nos.listdir(train_dir)[:5]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_dir","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# FilePath List\ntrain_list = glob.glob(os.path.join(train_dir, '*.jpg'))\ntest_list = glob.glob(os.path.join(test_dir, '*.jpg'))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_list","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"img = Image.open(train_list[3])\nplt.imshow(img)\nplt.axis('off')\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"img = Image.open(test_list[0])\nplt.imshow(img)\nplt.axis('off')\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_list[0].split('/')[-1].split('.')[0]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_list","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"int(test_list[0].split('/')[-1].split('.')[0])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"len(test_list)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"os.listdir(test_dir)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_list,val_list = train_test_split(train_list,test_size=0.1)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_list","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"len(train_list)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"len(val_list)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Data Augumentation\nclass ImageTransform():\n    \n    def __init__(self, resize, mean, std):\n        self.data_transform = {\n            'train': transforms.Compose([\n                transforms.RandomResizedCrop(resize, scale=(0.5, 1.0)),\n                transforms.RandomHorizontalFlip(),\n                transforms.ToTensor(),\n                transforms.Normalize(mean, std)\n            ]),\n            'val': transforms.Compose([\n                transforms.Resize(256),\n                transforms.CenterCrop(resize),\n                transforms.ToTensor(),\n                transforms.Normalize(mean, std)\n            ])\n        }\n        \n    def __call__(self, img, phase):\n        return self.data_transform[phase](img)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Dataset\nclass DogvsCatDataset(data.Dataset):\n    \n    def __init__(self, file_list, transform=None, phase='train'):    \n        self.file_list = file_list\n        self.transform = transform\n        self.phase = phase\n        \n    def __len__(self):\n        return len(self.file_list)\n    \n    def __getitem__(self, idx):\n        \n        img_path = self.file_list[idx]\n        img = Image.open(img_path)\n        \n        img_transformed = self.transform(img, self.phase)\n        \n        # Get Label\n        label = img_path.split('/')[-1].split('.')[0]\n        if label == 'dog':\n            label = 1\n        elif label == 'cat':\n            label = 0\n\n        return img_transformed, label","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Config\nsize = 224\nmean = (0.485, 0.456, 0.406)\nstd = (0.229, 0.224, 0.225)\nbatch_size = 32\ndevice = torch.device(\"cuda:0\" if torch.cuda.is_available() else \"cpu\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Dataset\ntrain_dataset = DogvsCatDataset(train_list, transform=ImageTransform(size, mean, std), phase='train')\nval_dataset = DogvsCatDataset(val_list, transform=ImageTransform(size, mean, std), phase='val')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"len(train_dataset)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Operation Check\nprint('Operation Check')\nindex = 0\nprint(train_dataset.__getitem__(index)[0].size())\nprint(train_dataset.__getitem__(index)[1])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# DataLoader\ntrain_dataloader = data.DataLoader(train_dataset, batch_size=batch_size, shuffle=True)\nval_dataloader = data.DataLoader(val_dataset, batch_size=batch_size, shuffle=False)\n\ndataloader_dict = {'train': train_dataloader, 'val': val_dataloader}\n\n# Operation Check\nprint('Operation Check')\nbatch_iterator = iter(train_dataloader)\ninputs, label = next(batch_iterator)\nprint(inputs.size())\nprint(label)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"use_pretrained = True\nnet = models.resnet50(pretrained=use_pretrained)\nprint(net)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"net.fc = nn.Linear(in_features=2048, out_features=2)\nprint('Done')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print(net)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Specify The Layers for updating\nparams_to_update = []\n\nupdate_params_name = ['fc.weight', 'fc.bias']\n\nfor name, param in net.named_parameters():\n    if name in update_params_name:\n        param.requires_grad = True\n        params_to_update.append(param)\n        print(name)\n    else:\n        param.requires_grad = False","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def lr_schedule(epoch):\n    lr = 1e-3\n    if epoch > 95:\n        lr *= 0.5e-3\n    elif epoch > 80:\n        lr *= 1e-3\n    elif epoch > 50:\n        lr *= 1e-2\n    elif epoch > 20:\n        lr *= 1e-1\n    print('Learning rate: ', lr)\n    return lr","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"criterion = nn.CrossEntropyLoss()\noptimizer = optim.Adam(params=params_to_update,lr=lr_schedule(0))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def train_model(net, dataloader_dict, criterion, optimizer, num_epoch):\n    \n    since = time.time()\n    best_model_wts = copy.deepcopy(net.state_dict())\n    best_acc = 0.0\n    net = net.to(device)\n    \n    for epoch in range(num_epoch):\n        print('Epoch {}/{}'.format(epoch + 1, num_epoch))\n        print('-'*20)\n        \n        for phase in ['train', 'val']:\n            \n            if phase == 'train':\n                net.train()\n            else:\n                net.eval()\n                \n            epoch_loss = 0.0\n            epoch_corrects = 0\n            \n            for inputs, labels in tqdm(dataloader_dict[phase]):\n                inputs = inputs.to(device)\n                labels = labels.to(device)\n                optimizer.zero_grad()\n                \n                with torch.set_grad_enabled(phase == 'train'):\n                    outputs = net(inputs)\n                    _, preds = torch.max(outputs, 1)\n                    loss = criterion(outputs, labels)\n                    \n                    if phase == 'train':\n                        loss.backward()\n                        optimizer.step()\n                        \n                    epoch_loss += loss.item() * inputs.size(0)\n                    epoch_corrects += torch.sum(preds == labels.data)\n                    \n            epoch_loss = epoch_loss / len(dataloader_dict[phase].dataset)\n            epoch_acc = epoch_corrects.double() / len(dataloader_dict[phase].dataset)\n            \n            print('{} Loss: {:.4f} Acc: {:.4f}'.format(phase, epoch_loss, epoch_acc))\n            \n            # deep copy the model\n            if phase == 'val' and epoch_acc > best_acc:\n                best_acc = epoch_acc\n                best_model_wts = copy.deepcopy(net.state_dict())\n                \n    time_elapsed = time.time() - since\n    print('Training complete in {:.0f}m {:.0f}s'.format(\n        time_elapsed // 60, time_elapsed % 60))\n    print('Best val Acc: {:4f}'.format(best_acc))\n\n    # load best model weights\n    net.load_state_dict(best_model_wts)\n    return net","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"num_epoch = 10\nnet = train_model(net, dataloader_dict, criterion, optimizer, num_epoch)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Prediction\nid_list = []\npred_list = []\n\nwith torch.no_grad():\n    for test_path in tqdm(test_list):\n        img = Image.open(test_path)\n        _id = int(test_path.split('/')[-1].split('.')[0])\n\n        transform = ImageTransform(size, mean, std)\n        img = transform(img, phase='val')\n        img = img.unsqueeze(0)\n        img = img.to(device)\n\n        net.eval()\n\n        outputs = net(img)\n        preds = F.softmax(outputs, dim=1)[:, 1].tolist()\n        \n        id_list.append(_id)\n        pred_list.append(preds[0])\n    \n    \nres = pd.DataFrame({\n    'id': id_list,\n    'label': pred_list\n})\n\nres.sort_values(by='id', inplace=True)\nres.reset_index(drop=True, inplace=True)\n\nres.to_csv('submission.csv', index=False)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"res.head(10)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Visualize Prediction\nid_list = []\nclass_ = {0: 'cat', 1: 'dog'}\n\nfig, axes = plt.subplots(2, 5, figsize=(20, 12), facecolor='w')\n\nfor ax in axes.ravel():\n    \n    i = random.choice(res['id'].values)\n    \n    label = res.loc[res['id'] == i, 'label'].values[0]\n    if label > 0.5:\n        label = 1\n    else:\n        label = 0\n        \n    img_path = os.path.join(test_dir, '{}.jpg'.format(i))\n    img = Image.open(img_path)\n    \n    ax.set_title(class_[label])\n    ax.imshow(img)","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":4}