{"cells":[{"metadata":{"trusted":true},"cell_type":"code","source":"import os\nimport random\nimport numbers\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n\n# train test split from sklearn\nfrom sklearn.model_selection import train_test_split\n\n# Import Torch \nimport torch\nimport torch.nn as nn\nimport torch.nn.functional as F\nfrom torchvision import transforms, models\nfrom torch.autograd import Variable\nfrom torch import nn, optim\nfrom torch.optim import lr_scheduler\nfrom torch.utils.data import DataLoader, Dataset, Subset\n\n# graphing\nfrom matplotlib import pyplot as plt\n\n# Image processing\nfrom PIL import Image, ImageOps, ImageEnhance\n\n# progress bar\nfrom tqdm import tqdm","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# extract files\nimport zipfile\n\n# train data\nif 'train' not in os.listdir('.'):\n    with zipfile.ZipFile(\"../input/dogs-vs-cats/train.zip\",\"r\") as z:\n        z.extractall(\".\")\n\n# test data\nif 'test1' not in os.listdir('.'):\n    with zipfile.ZipFile(\"../input/dogs-vs-cats/test1.zip\",\"r\") as z:\n        z.extractall(\".\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# set up transforms\ntrain_transforms = transforms.Compose([\n                                transforms.Resize(256),\n                                transforms.ColorJitter(),\n                                transforms.RandomCrop(224),\n                                transforms.RandomHorizontalFlip(),\n                                transforms.Resize((32,32)),\n                                transforms.ToTensor(), \n                                transforms.Normalize(mean=(0.5,), std=(0.5,))])\n\n# only resize transform for testing\ntest_transform = transforms.Compose([\n    transforms.Resize((32,32)),\n    transforms.ToTensor()\n])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"class CatsDogsDataSet(Dataset):\n     def __init__(self, train_dir, transform = train_transforms):       \n        self.train_dir = train_dir\n        self.transform = transform\n        self.images = []\n        self.labels = []\n        for fname in os.listdir(train_dir):\n            self.images.append(fname)\n            if 'cat' in fname.split('.')[0]:\n                self.labels.append(1)\n            else:\n                self.labels.append(0)\n                \n     def __len__(self):\n        return len(self.images)\n\n     def __getitem__(self, idx):\n        img = Image.open(os.path.join(self.train_dir, self.images[idx]))\n        if self.transform is not None:\n            img = self.transform(img)\n        else:\n            img = np.array(img).astype('float32')\n        return img, self.labels[idx]\n    \n     def split(self, start, end):\n        return self.labels[start:end+1]\n    \n    \n     def show_image(self, index):        \n        filename = os.path.join(self.train_dir, self.images[index])\n        img_array = np.array(Image.open(filename))\n        plt.imshow(img_array)\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# view sample data and check distribution of validation set\ntrain_dir = './test1'\nsample_dataset = CatsDogsDataSet(train_dir=train_dir, transform = train_transforms)  \nrand_index = random.randint(0, len(sample_dataset))\nsample_image, sample_label = sample_dataset.__getitem__(rand_index)\n\nprint(\"Shape: \", sample_image.shape)\nmy_split = sample_dataset.split(20001,25000)\n\nprint(\"Split: \", sum(my_split))\n\nprint(sample_label)\nsample = sample_dataset.show_image(2)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"batch_size = 64\n\n# create datasets from np arrays\ntrain_dataset = CatsDogsDataSet('train')\ntest_dataset = CatsDogsDataSet('test1', transform = test_transform)\n\ntrain_indexes =  [i for i in range(20000)]\nvalid_indexes =  [i for i in range(20001, 25000)]\n\ntrain_data = Subset(train_dataset, train_indexes)\nvalid_data  = Subset(train_dataset, valid_indexes)\n\n# torch dataloaders\ntrain_loader = torch.utils.data.DataLoader(dataset=train_data, batch_size=batch_size, shuffle=True)\nvalid_loader = torch.utils.data.DataLoader(dataset=valid_data, batch_size=batch_size, shuffle=True)\ntest_loader = torch.utils.data.DataLoader(dataset=test_dataset, batch_size=batch_size, shuffle=False)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"class CNN(nn.Module):\n    def __init__(self):\n        super(CNN, self).__init__()\n        self.conv1 = nn.Conv2d(3,50,5)\n        self.conv2 = nn.Conv2d(50,150,3)\n        self.conv3 = nn.Conv2d(150,300,3)\n        self.conv4 = nn.Conv2d(300, 120, 3)\n        self.fc1 = nn.Linear(5880, 1024)\n        self.fc2 = nn.Linear(1024, 512)\n        self.fc3 = nn.Linear (512, 2)\n    \n        \n    def forward(self,x): \n#        print('\\ninput')\n#        print(x.shape)\n        x = F.relu(self.conv1(x))\n#        print('\\nconv1 output')\n#        print(x.shape)\n        x = F.max_pool2d(x, kernel_size = 3, stride = 1)\n#       print('\\nmaxpool1 output')\n#        print(x.shape)\n        x = F.relu(self.conv2(x))\n#        print('\\nconv2 output')\n#        print(x.shape)\n        x = F.max_pool2d(x, kernel_size = 3, stride = 1)\n#        print('\\nmaxpool2 output')\n#        print(x.shape)\n        x = F.relu(self.conv3(x))\n#        print('\\nconv3 output')\n#        print(x.shape)\n        x = F.max_pool2d(x, kernel_size = 3, stride = 2)\n#        print('maxpool3 output')\n#        print(x.shape)\n        x = F.relu(self.conv4(x))\n#        print('conv4 output')\n#        print(x.shape)\n#        x = F.max_pool2d(x, kernel_size = 3, stride = 2)\n#        print('maxpool4 output')\n#        print(x.shape)\n        \n        x = torch.flatten(x, start_dim=1)\n        \n#        print('flatten output')\n#        print(x.shape)\n        x = F.relu(self.fc1(x))\n#        print('fc1 output')\n#        print(x.shape)\n        x = F.relu(self.fc2(x))\n#        print('fc2 output')\n#        print(x.shape)\n        x = self.fc3(x)\n#        print(x.shape)\n        return x\n\nprint(CNN())","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"model = CNN()    \noptimizer = optim.Adam(model.parameters(), lr=0.001)\ncriterion = nn.CrossEntropyLoss()\nexpr_lr_scheduler = optim.lr_scheduler.MultiStepLR(optimizer, milestones = [3, 7], gamma=0.1)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"loss_list = []\naccuracy_list = []\niteration_list = []\n\ndef train(epoch):\n    expr_lr_scheduler.step()\n    i = 0\n    for features, labels in tqdm(train_loader):\n        features, labels = Variable(features), Variable(labels)\n\n        # zero out gradients from previous iteration\n        optimizer.zero_grad()\n\n        # forward propagation\n        output = model(features)\n        \n        # calculate loss\n        loss = criterion(output, labels)\n\n        # backprop\n        loss.backward()\n        \n        # update params (gradient descent)\n        optimizer.step()\n            \n        i += 1","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def evaluate(data_loader):\n    model.eval()\n    loss = 0\n    correct = 0\n    \n    for features, labels in tqdm(data_loader):\n        with torch.no_grad():\n            features, labels = Variable(features), Variable(labels)\n            output = model(features)\n            \n        loss += F.cross_entropy(output, labels, size_average=False).data.item()\n        pred = output.data.max(1, keepdim=True)[1]\n        correct += pred.eq(labels.data.view_as(pred)).cpu().sum()\n        \n    loss /= len(data_loader.dataset)\n    accuracy = 100. * correct / len(data_loader.dataset)\n    print('Epoch: {}, Average loss: {:.4f}, Accuracy: {}/{} ({:.3f}%)'.format(\n        epoch,\n        loss, correct, len(data_loader.dataset),\n        accuracy))\n    loss_list.append(loss)\n    accuracy_list.append(accuracy)\n    iteration_list.append(epoch)","execution_count":null,"outputs":[]},{"metadata":{"tags":[],"trusted":true},"cell_type":"code","source":"n_epochs = 10\n\nfor epoch in range(n_epochs):\n    train(epoch)\n    evaluate(valid_loader)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# visualize loss \nplt.plot(iteration_list,loss_list)\nplt.xlabel(\"Number of epochs\")\nplt.ylabel(\"Loss\")\nplt.title(\"Loss vs Number of epochs\")\nplt.show()\n\n# visualize accuracy \nplt.plot(iteration_list,accuracy_list,color = \"red\")\nplt.xlabel(\"Number of epochs\")\nplt.ylabel(\"Accuracy\")\nplt.title(\"Accuracy vs Number of epochs\")\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# save model\ntorch.save(model, 'cnn-model.pt')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"model.eval()\nfn_list = []\npred_list = []\nfor x,_ in tqdm(test_loader):\n    with torch.no_grad():\n        output = model(x)\n        pred = torch.argmax(output, dim=1)\n    pred_list += [p.item() for p in pred]","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"##### "},{"metadata":{"trusted":true},"cell_type":"code","source":"ids = [i for i in range(1, len(pred_list)+1)]\nsubmission = pd.DataFrame({\"id\":ids, \"label\":pred_list})\nsubmission.to_csv('submission.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}