{"cells":[{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"import os\nimport zipfile\nimport time\nimport copy\nimport numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\nimport torch\nimport torch.nn as nn\nimport torch.nn.functional as F\nimport torchvision\n\nfrom torchvision.utils import make_grid\nfrom torchvision import transforms\nfrom PIL import Image\nfrom torch.utils.data import Dataset, random_split, DataLoader","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"**Extract data from zip**","execution_count":null},{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true},"cell_type":"code","source":"PATH = '../input/dogs-vs-cats-redux-kernels-edition/'\nTRAIN_PATH = os.path.join(PATH, 'train.zip')\nTEST_PATH = os.path.join(PATH, 'test.zip')\n\nwith zipfile.ZipFile(TRAIN_PATH, 'r') as z:\n    z.extractall('.')\n    \nwith zipfile.ZipFile(TEST_PATH, 'r') as z:\n    z.extractall('.')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"extract_label = lambda img_name: img_name.split('.')[0]","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"**Custom dataset class for loading images from folder and assigning labels to them**","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"class CatsDogsDataset(Dataset):\n    def __init__(self, img_list, transform=None):\n        self.img_list = img_list\n        self.transform = transform\n        \n    def __getitem__(self, index):\n        img_name = self.img_list[index]\n        \n        image = Image.open('train/' + img_name)\n        if self.transform:\n            image = self.transform(image)\n        \n        label_img = extract_label(img_name)\n        label = 1 if label_img == 'dog' else 0\n        \n        return image, label\n    \n    def __len__(self):\n        return len(self.img_list)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"data_transform = transforms.Compose([\n    transforms.RandomResizedCrop(224),\n    transforms.RandomHorizontalFlip(),\n    transforms.ToTensor(),\n    transforms.Normalize(mean=[0.485, 0.456, 0.406],\n                         std=[0.229, 0.224, 0.225])\n])\n\nimg_list = os.listdir('train/')\ndataset = CatsDogsDataset(img_list=img_list, transform=data_transform)\n\ntrain_size = 20000\nval_size = 5000\n\ntrain_data, val_data = random_split(dataset, [train_size, val_size])\n\ntrain_loader = DataLoader(train_data, batch_size=64, shuffle=False,\n                          num_workers=4, pin_memory=True)\nval_loader = DataLoader(val_data, batch_size=64, shuffle=False,\n                        num_workers=4, pin_memory=True)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"for imgs, _ in train_loader:\n    print('Image shape: ', imgs.shape)\n    plt.figure(figsize=(16, 10))\n    plt.axis('off')\n    plt.imshow(make_grid(imgs, nrow=16, normalize=True).permute(1, 2, 0))\n    break","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"model = torchvision.models.resnet50(pretrained=True)\nmodel","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"for param in model.parameters():\n    param.requires_grad = False\n\nfc_in_features = model.fc.in_features\nmodel.fc = nn.Linear(fc_in_features, 2)\nmodel = model.to(device)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"optimizer = torch.optim.SGD(model.parameters(), lr=1e-2)\ncriterion = nn.CrossEntropyLoss()\n\nlr_scheduler = torch.optim.lr_scheduler.StepLR(optimizer, step_size=7, gamma=0.1)\n\ndataloaders = {'train': train_loader,\n                'val': val_loader}\n\ndataset_sizes = {'train': len(train_data),\n                 'val': len(val_data)}\n\ndef train_model(model, criterion, optimizer, dataloaders, scheduler, num_epochs):\n    since = time.time()\n\n    best_model_wts = copy.deepcopy(model.state_dict())\n    best_acc = 0.0\n\n    for epoch in range(num_epochs):\n        print('Epoch {}/{}'.format(epoch, num_epochs - 1))\n        print('-' * 10)\n\n        # Each epoch has a training and validation phase\n        for phase in ['train', 'val']:\n            if phase == 'train':\n                model.train()  # Set model to training mode\n            else:\n                model.eval()   # Set model to evaluate mode\n\n            running_loss = 0.0\n            running_corrects = 0\n\n            # Iterate over data.\n            for inputs, labels in dataloaders[phase]:\n                inputs = inputs.to(device)\n                labels = labels.to(device)\n\n                # zero the parameter gradients\n                optimizer.zero_grad()\n\n                # forward\n                # track history if only in train\n                with torch.set_grad_enabled(phase == 'train'):\n                    outputs = model(inputs)\n                    _, preds = torch.max(outputs, 1)\n                    loss = criterion(outputs, labels)\n\n                    # backward + optimize only if in training phase\n                    if phase == 'train':\n                        loss.backward()\n                        optimizer.step()\n\n                # statistics\n                running_loss += loss.item() * inputs.size(0)\n                running_corrects += torch.sum(preds == labels.data)\n            if phase == 'train':\n                scheduler.step()\n\n            epoch_loss = running_loss / dataset_sizes[phase]\n            epoch_acc = running_corrects.double() / dataset_sizes[phase]\n\n            print('{} Loss: {:.4f} Acc: {:.4f}'.format(\n                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(model.state_dict())\n\n        print()\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    model.load_state_dict(best_model_wts)\n    return model\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"trained_model = train_model(model, criterion, optimizer, dataloaders, scheduler=lr_scheduler, num_epochs=5)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"test_imgs = os.listdir('test/')\n\nlabels = []\n\nwith torch.no_grad():\n    for test_img in test_imgs:\n        img = Image.open('test/'+test_img)\n        img = data_transform(img)\n        img = img.unsqueeze(0)\n        img = img.to(device)\n        \n        trained_model.eval()\n        output = trained_model(img)\n        pred = F.softmax(output, dim=1)[:, 1].tolist()\n        \n        labels.append(pred[0])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"df = pd.read_csv('../input/dogs-vs-cats-redux-kernels-edition/sample_submission.csv')\ndf['label'] = labels\ndf.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"df.to_csv('subm_2.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":4}