{"cells":[{"metadata":{"id":"zSzpZr5x2kVs"},"cell_type":"markdown","source":"# 1. Pre-setup","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"# %%capture is to hide the output\n%%capture\nimport os\nfor dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n        print(os.path.join(dirname, filename))","execution_count":null,"outputs":[]},{"metadata":{"id":"XBA-1F3kNF-e","trusted":true},"cell_type":"code","source":"%%capture\n!unzip '../input/dogs-vs-cats/train'\n!unzip '../input/dogs-vs-cats/test1'","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"!mkdir train_","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import shutil\nimport os\n\nos.mkdir('train_/cat/')\nos.mkdir('train_/dog/')\n\nfor f in os.listdir('train'):\n    if f.split('.')[0] == 'cat':\n        shutil.move('train/'+f,'train_/cat/'+f)\n    else:\n        shutil.move('train/'+f,'train_/dog/'+f)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"os.rmdir('train')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print(f\"Number of testing imgaes : {len(os.listdir('test1'))}\")","execution_count":null,"outputs":[]},{"metadata":{"id":"wdxAWJNuNbq5"},"cell_type":"markdown","source":"# 2. Loading the Data","execution_count":null},{"metadata":{"id":"BDYWz3c_PgNu","trusted":true},"cell_type":"code","source":"import torch\nfrom torchvision import transforms, datasets,models\nimport numpy as np\nimport pandas as pd\nfrom torch import nn,optim\nfrom PIL import Image","execution_count":null,"outputs":[]},{"metadata":{"id":"dFbL2ViOOgB9"},"cell_type":"markdown","source":"Lets Create DataLoaders along with some Data Augmentation on the Input data","execution_count":null},{"metadata":{"id":"2aJTKXwpO4xz","trusted":true},"cell_type":"code","source":"train_dir = 'train_'\n\n\n# We create the transforms for train (Data Augmentation)\ntrain_transform = transforms.Compose([\n  transforms.Resize(256),\n  transforms.CenterCrop(224),\n  transforms.RandomRotation(30),\n  transforms.RandomHorizontalFlip(),\n  transforms.ToTensor(),\n  transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),\n])\n\n\n# Creating Train DataSet\ntrain_dataset = datasets.ImageFolder(train_dir,transform=train_transform)\n\n# Creating a Data Generator (to obtain data in batches)\ntrain_dataloader = torch.utils.data.DataLoader(\n  train_dataset,  \n  batch_size = 128,\n  shuffle = True\n)","execution_count":null,"outputs":[]},{"metadata":{"id":"i8acBKVERM08","outputId":"53fd6d82-d956-48de-f8a0-73c6bc144b6f","trusted":true},"cell_type":"code","source":"import matplotlib.pyplot as plt\n\ndef imshow(image, ax=None, title=None, normalize=True):\n    \"\"\"Imshow for Tensor.\"\"\"\n    if ax is None:\n        fig, ax = plt.subplots()\n    image = image.numpy().transpose((1, 2, 0))\n\n    if normalize:\n        mean = np.array([0.485, 0.456, 0.406])\n        std = np.array([0.229, 0.224, 0.225])\n        image = std * image + mean\n        image = np.clip(image, 0, 1)\n\n    ax.imshow(image)\n    ax.spines['top'].set_visible(False)\n    ax.spines['right'].set_visible(False)\n    ax.spines['left'].set_visible(False)\n    ax.spines['bottom'].set_visible(False)\n    ax.tick_params(axis='both', length=0)\n    ax.set_xticklabels('')\n    ax.set_yticklabels('')\n\n    return ax\n\n\n\nimages, labels = next(iter(train_dataloader))\n\ntitle = 'Dog' if labels[0].item() == 1 else 'Cat'\nimshow(images[0])","execution_count":null,"outputs":[]},{"metadata":{"id":"stdsGDsnhD6Q"},"cell_type":"markdown","source":"# 3. Loading the Pre-Trained model","execution_count":null},{"metadata":{"id":"p3dCzB82kTnK"},"cell_type":"markdown","source":"We are going to be using the Densenet 121 model","execution_count":null},{"metadata":{"id":"cvOJNlmJkYAK","outputId":"c404320b-aa4d-4352-97d0-6ce6b3f3397f","trusted":true},"cell_type":"code","source":"model = models.vgg16(pretrained=True)\nmodel","execution_count":null,"outputs":[]},{"metadata":{"id":"NGgWVrWskgDx"},"cell_type":"markdown","source":"We can see that the model has to major components which are the *Features* and the *Classifier*.\n\nThe *Features* are obtained by passing the image throught the many Convolutions \n\nThe *Classifier* is built and trained to the \"Imagenet\" dataset so it has about 1000 neurons in the output layer as it can map upto 1000 different classes.\n\nFor out Cats-Dogs classifier we need to train a binary classifier and can train a new classifier from scratch which uses the features learnt from the \"Imagenet\" dataset of the Densenet121","execution_count":null},{"metadata":{"id":"N2X9cw76k4g4","trusted":true},"cell_type":"code","source":"# Freeze our feature parameters as we don't wanna retrain them to the new data\nfor param in model.parameters():\n  param.requires_grad = False","execution_count":null,"outputs":[]},{"metadata":{"id":"DbfBbnv1l4tQ"},"cell_type":"markdown","source":"Lets now build our binary classifier","execution_count":null},{"metadata":{"id":"30tTIGoEmEDG","trusted":true},"cell_type":"code","source":"from collections import OrderedDict\n\nclassifier = nn.Sequential(OrderedDict([\n  # Layer 1\n  ('dropout1',nn.Dropout(0.3)),\n  ('fc1', nn.Linear(25088,500)),\n  ('relu', nn.ReLU()),\n  # output layer\n  ('fc2', nn.Linear(500,2)),\n  ('output', nn.LogSoftmax(dim=1))\n]))\n\n# Attach the classifier to the model\nmodel.classifier = classifier","execution_count":null,"outputs":[]},{"metadata":{"id":"Jn9BSfQ0nq44"},"cell_type":"markdown","source":"# 4. Train the Model","execution_count":null},{"metadata":{"id":"LE0c9fOCn_GP","trusted":true},"cell_type":"code","source":"# Loss\ncriterion = nn.NLLLoss()\n\n# Optimizer \noptimizer = optim.Adam(model.classifier.parameters(),lr =0.001)","execution_count":null,"outputs":[]},{"metadata":{"id":"8s9d3Mcdol8y","outputId":"f5c69237-e99b-4a35-cee5-1017ee7d99ca","trusted":true},"cell_type":"code","source":"# Lets use GPU if available\ndevice = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\ndevice","execution_count":null,"outputs":[]},{"metadata":{"id":"5ccRbiBwpKtv","trusted":true},"cell_type":"code","source":"# Moving model to GPU\nmodel = model.to(device)","execution_count":null,"outputs":[]},{"metadata":{"id":"y3JRhplVpb10","outputId":"6d79be0a-ecf4-4676-fb47-06b25af93c9d","trusted":true},"cell_type":"code","source":"from tqdm import tqdm\nepochs = 5\n\n\nfor e in range(epochs):\n  running_loss, total, correct = 0, 0 , 0\n\n  model.train()\n    \n  for images,labels in tqdm(train_dataloader):\n    \n    # Moving input to GPU\n    images, labels = images.to(device), labels.to(device)\n\n    # Forward prop\n    outputs = model(images)\n    loss = criterion(outputs,labels)\n\n    # Backward prop\n    optimizer.zero_grad()\n    loss.backward()\n    optimizer.step()\n\n    # Metrics \n    running_loss += loss.item()\n    total += labels.size(0)\n\n    _, predicted = torch.max(torch.exp(outputs).data,1)\n    correct += (predicted == labels).sum().item()\n  else:\n    # Logs \n    print(f'Epoch {e} Training: Loss={running_loss:.5f} Acc={correct/total * 100:.2f}')\n","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"**Save the Model**","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"# The checkpoints dictionary will consist of necessary details for rebuilding the model with pretrained weights\ncheckpoints = {\n     'pre-trained':'vgg16',\n     'classifier':nn.Sequential(OrderedDict([\n          # Layer 1\n          ('dropout1',nn.Dropout(0.3)),\n          ('fc1', nn.Linear(25088,500)),\n          ('relu', nn.ReLU()),\n          # output layer\n          ('fc2', nn.Linear(500,2)),\n          ('output', nn.LogSoftmax(dim=1))\n    ])),\n    'state_dict':model.state_dict()\n}\n\ntorch.save(checkpoints,'vgg16_catsVdogs.pth')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Loading and Rebuilding the saved model\n\ndef load_saved_model(path):\n    \n    # Loading the checkpoint dictionary\n    checkpoint = torch.load(path)\n    \n    # Loading features of the pretrained vgg16\n    model = models.vgg16(pretrained=True)\n    for param in model.parameters():\n        param.requires_grad = False\n        \n    # Reconstruct the classifier by loading the structure from checkpoint\n    model.classifier = checkpoint['classifier']\n    \n    # Loading the weights\n    model.load_state_dict(checkpoints['state_dict'])\n    \n    # Set model to Evaluation mode to avoid training\n    model.eval()\n    \n    return model","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"loaded_model = load_saved_model('vgg16_catsVdogs.pth')\nloaded_model.to(device)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"loaded_model","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"**Testing and creating submission**","execution_count":null},{"metadata":{},"cell_type":"markdown","source":"**Prediction**","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"# Test Transform\ntest_transform = transforms.Compose([\n          transforms.Resize(256),\n          transforms.CenterCrop(224),\n          transforms.ToTensor(),\n          transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),\n        ])\n\npredictions = []\n\nfor i in tqdm(range(1,12501)):\n    path = 'test1/'+str(i)+'.jpg'\n    X = Image.open(path).convert('RGB')\n    X = test_transform(X)[:3,:,:]\n    X = X.unsqueeze(0)\n    X = X.to(device)\n    outputs = loaded_model(X)\n    predictions.append(torch.argmax(outputs).item())\n    ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Making the subimission\ndata = {'id':list(range(1,12501)),'label':predictions}\ndf = pd.DataFrame(data)\ndf.shape","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"df.to_csv('cats-dogs-submission.csv',index=False)","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}