{"cells": [{"execution_count": null, "source": ["from __future__ import print_function, division\n", "import numpy as np\n", "import pandas as pd\n", "import torch\n", "import torch.nn as nn\n", "import torch.optim as optim\n", "from torch.optim import lr_scheduler\n", "from torch.autograd import Variable\n", "from torch.utils.data import Dataset, DataLoader\n", "from torchvision import transforms, utils, models\n", "\n", "from PIL import Image\n", "import matplotlib.pyplot as plt\n", "import time\n", "import os\n", "\n", "plt.ion()   # interactive mode\n", "multiGPU = False"], "metadata": {"collapsed": true, "_uuid": "756fc55ddc14de0712204aee645fe3c6c74013fc", "_cell_guid": "086f7268-82fb-4743-8ebb-3d998a051fea"}, "cell_type": "code", "outputs": []}, {"execution_count": null, "source": ["TRAIN_IMG_PATH = \"../input/train\"\n", "TEST_IMG_PATH = \"../input/test\"\n", "LABELS_CSV_PATH = \"../input/labels.csv\"\n", "SAMPLE_SUB_PATH = \"../input/sample_submission.csv\""], "metadata": {"collapsed": true, "_uuid": "085602728c77b72820cea246f7366102da5ee71f", "_cell_guid": "ac7aaa41-cadf-4e89-8e68-e8c891aad6d1"}, "cell_type": "code", "outputs": []}, {"execution_count": null, "source": ["class DogsDataset(Dataset):\n", "    \"\"\"Dog breed identification dataset.\"\"\"\n", "\n", "    def __init__(self, img_dir, dataframe, transform=None):\n", "        \"\"\"\n", "        Args:\n", "            img_dir (string): Directory with all the images.        \n", "            dataframe (pandas.core.frame.DataFrame): Pandas dataframe obtained\n", "                by read_csv().\n", "            transform (callable, optional): Optional transform to be applied\n", "                on a sample.\n", "        \"\"\"\n", "        self.labels_frame = dataframe\n", "        self.img_dir = img_dir\n", "        self.transform = transform\n", "\n", "    def __len__(self):\n", "        return len(self.labels_frame)\n", "\n", "    def __getitem__(self, idx):\n", "        img_name = os.path.join(self.img_dir, self.labels_frame.id[idx]) + \".jpg\"\n", "        image = Image.open(img_name)\n", "        label = self.labels_frame.target[idx]\n", "\n", "        if self.transform:\n", "            image = self.transform(image)\n", "\n", "        return [image, label] "], "metadata": {"collapsed": true, "_uuid": "28b6a1313549f8fa8bfd8a0a5ccde999fb5ca805", "_cell_guid": "327095d4-6a66-4dba-9f06-6a70d8dc4e32"}, "cell_type": "code", "outputs": []}, {"source": ["**Test**: Instantiate the class and show the first images and sizes."], "metadata": {"_uuid": "6c7c3384a3fb116c1317fd26d1680ac695e49a19", "_cell_guid": "3f0012a2-b780-4355-a289-c9c8e9b2c762"}, "cell_type": "markdown"}, {"execution_count": null, "source": ["dframe = pd.read_csv(LABELS_CSV_PATH)\n", "labelnames = pd.read_csv(SAMPLE_SUB_PATH).keys()[1:]\n", "codes = range(len(labelnames))\n", "breed_to_code = dict(zip(labelnames, codes))\n", "code_to_breed = dict(zip(codes, labelnames))\n", "dframe['target'] =  [breed_to_code[x] for x in dframe.breed]\n", "\n", "cut = int(len(dframe)*0.8)\n", "train, test = np.split(dframe, [cut], axis=0)\n", "test = test.reset_index(drop=True)\n", "\n", "train_ds = DogsDataset(TRAIN_IMG_PATH, train)\n", "test_ds = DogsDataset(TRAIN_IMG_PATH, test)\n", "idx = 29\n", "plt.imshow(train_ds[idx][0])\n", "print(code_to_breed[train_ds[idx][1]])\n", "print(\"Shape of the image is: \", train_ds[idx][0].size)"], "metadata": {"collapsed": true, "_uuid": "fef8eb5faa4ba59abea74a284a3141766be8e5b8", "_cell_guid": "7d4821e0-e167-4dd8-97a0-20e3b7d5ec99"}, "cell_type": "code", "outputs": []}, {"source": ["**Problem**: Need to reshape the images to feed them to the NN"], "metadata": {"_uuid": "f56b75ee702f8196c27ffbf262f210fa20bae56c", "_cell_guid": "b3c0fb37-6639-45e8-8e9c-6f8527093e32"}, "cell_type": "markdown"}, {"execution_count": null, "source": ["data_transform = transforms.Compose([\n", "        transforms.RandomSizedCrop(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", "    ])"], "metadata": {"collapsed": true, "_uuid": "bcbb21a353c846ffd1e03578e8d0b2e73e633871", "_cell_guid": "850e1251-3042-49f9-a0a2-f9df7db071d8"}, "cell_type": "code", "outputs": []}, {"execution_count": null, "source": ["train_ds = DogsDataset(TRAIN_IMG_PATH, train, data_transform)\n", "test_ds = DogsDataset(TRAIN_IMG_PATH, test, data_transform)\n", "datasets = {\"train\": train_ds, \"val\": test_ds}\n", "\n", "idx = 29\n", "print(code_to_breed[train_ds[idx][1]])\n", "print(\"Shape of the image is: \", train_ds[idx][0].shape)"], "metadata": {"collapsed": true, "_uuid": "0c0c03212b04abb492ec9773888745cfa78b2d1d", "_cell_guid": "c4b42639-21ad-4a85-8244-e28959ad5e2a"}, "cell_type": "code", "outputs": []}, {"execution_count": null, "source": ["trainloader = DataLoader(train_ds, batch_size=4,\n", "                        shuffle=True, num_workers=4)\n", "\n", "testloader = DataLoader(test_ds, batch_size=4,\n", "                        shuffle=True, num_workers=4)\n", "\n", "dataloaders = {\"train\": trainloader, \"val\": testloader}"], "metadata": {"collapsed": true, "_uuid": "067cfac5cf28bfc125034a50c7ebfea05b0e541f", "_cell_guid": "50a35f51-75f6-42aa-9580-0988ac89a854"}, "cell_type": "code", "outputs": []}, {"source": ["## Training"], "metadata": {"_uuid": "3a9a5678742ae60cb33a81891694421ec9e388d3", "_cell_guid": "727a3461-b568-4747-b160-b858bd9898db"}, "cell_type": "markdown"}, {"source": ["Define variables if GPU is to be used"], "metadata": {"_uuid": "37218d86db94489f51c1022146b71844daad77f9", "_cell_guid": "10814599-84db-49e6-ac42-7f0848b37bdc"}, "cell_type": "markdown"}, {"execution_count": null, "source": ["if torch.cuda.is_available():\n", "    use_gpu = True\n", "    print(\"Using GPU\")\n", "else:\n", "    use_gpu = False\n", "FloatTensor = torch.cuda.FloatTensor if use_gpu else torch.FloatTensor\n", "LongTensor = torch.cuda.LongTensor if use_gpu else torch.LongTensor\n", "ByteTensor = torch.cuda.ByteTensor if use_gpu else torch.ByteTensor\n", "Tensor = FloatTensor"], "metadata": {"collapsed": true, "_uuid": "1144d3c6710d28e8cea1f55c7c612b98f34a2074", "_cell_guid": "b38ca60a-adc1-4b03-9e6d-b8a640de8afd"}, "cell_type": "code", "outputs": []}, {"execution_count": null, "source": ["def train_model(model, criterion, optimizer, scheduler, num_epochs=25):\n", "    since = time.time()\n", "\n", "    best_model_wts = 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", "            since_epoch = time.time()\n", "            if phase == 'train':\n", "                scheduler.step()\n", "                model.train(True)  # Set model to training mode\n", "            else:\n", "                model.train(False)  # Set model to evaluate mode\n", "    \n", "            running_loss = 0.0\n", "            running_corrects = 0\n", "\n", "            # Iterate over data.\n", "            for data in dataloaders[phase]:\n", "                # get the inputs\n", "                inputs, labels = data\n", "\n", "                inputs = Variable(inputs.type(Tensor))\n", "                labels = Variable(labels.type(LongTensor))\n", "\n", "                # zero the parameter gradients\n", "                optimizer.zero_grad()\n", "\n", "                # forward\n", "                outputs = model(inputs)\n", "                _, preds = torch.max(outputs.data, 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.data[0]\n", "                running_corrects += torch.sum(preds == labels.data)\n", "\n", "            epoch_loss = running_loss / len(datasets[phase])\n", "            epoch_acc = running_corrects / len(datasets[phase])\n", "\n", "            time_elapsed_epoch = time.time() - since_epoch\n", "            print('{} Loss: {:.4f} Acc: {:.4f} in {:.0f}m {:.0f}s'.format(\n", "                phase, epoch_loss, epoch_acc, time_elapsed_epoch // 60, time_elapsed_epoch % 60))\n", "            \n", "            # deep copy the model\n", "            if phase == 'val' and epoch_acc > best_acc:\n", "                best_acc = epoch_acc\n", "                best_model_wts = model.state_dict()\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"], "metadata": {"collapsed": true, "_uuid": "fe877b962ee30d726523edb7cab41870a1803906", "_cell_guid": "86370b72-4ea4-4c62-a860-f7562a5acf21"}, "cell_type": "code", "outputs": []}, {"source": ["Load and Finetune model"], "metadata": {"_uuid": "ecddea1f4d7c5599987feb7bf2cd77460925b7df", "_cell_guid": "4afd6f34-5369-4398-99ae-89da36279362"}, "cell_type": "markdown"}, {"execution_count": null, "source": ["model_ft = models.resnet152(pretrained=True)\n", "num_ftrs = model_ft.fc.in_features\n", "model_ft.fc = nn.Linear(num_ftrs, 120)\n", "\n", "if torch.cuda.device_count() > 1 and multiGPU:\n", "  print(\"Using\", torch.cuda.device_count(), \"GPUs!\")\n", "  # dim = 0 [30, xxx] -> [10, ...], [10, ...], [10, ...] on 3 GPUs\n", "  model_ft = nn.DataParallel(model_ft)\n", "\n", "if use_gpu:\n", "   model_ft.cuda()\n", "\n", "criterion = nn.CrossEntropyLoss()\n", "\n", "# Observe that all parameters are being optimized\n", "optimizer_ft = optim.SGD(model_ft.parameters(), lr=0.001, momentum=0.9)\n", "\n", "# Decay LR by a factor of 0.1 every 7 epochs\n", "exp_lr_scheduler = lr_scheduler.StepLR(optimizer_ft, step_size=7, gamma=0.1)"], "metadata": {"collapsed": true, "_uuid": "f5999bce76f4e06fb51d5223b71e6dac41bf3142", "_cell_guid": "38c5a44f-1804-4f56-b597-94cb40d7ce51"}, "cell_type": "code", "outputs": []}, {"execution_count": null, "source": ["model_ft = train_model(model_ft, criterion, optimizer_ft, exp_lr_scheduler,\n", "                           num_epochs=25)"], "metadata": {"collapsed": true, "_uuid": "8fdf3619b1be1f3bd7635ec44b93bcbbb1d93daa", "_cell_guid": "e1952b5f-ae92-4bac-8080-aa41db9eb589"}, "cell_type": "code", "outputs": []}, {"source": ["## Preparing the submission"], "metadata": {"_uuid": "55e27ce599d6869dff4f7c148672a41ca20801c9", "_cell_guid": "ca8edf52-eae8-45fc-8f43-8574ebc7e6d0"}, "cell_type": "markdown"}, {"execution_count": null, "source": ["submission_df = pd.read_csv(SAMPLE_SUB_PATH)\n", "output_df = pd.DataFrame(index=submission_df.index, columns=submission_df.keys() )\n", "output_df['id'] = submission_df['id']\n", "submission_df['target'] =  [0] * len(submission_df)\n", "\n", "tdata_transform = transforms.Compose([\n", "        transforms.Scale(256),\n", "        transforms.CenterCrop(224),\n", "        transforms.ToTensor(),\n", "        transforms.Normalize(mean=[0.485, 0.456, 0.406],\n", "                             std=[0.229, 0.224, 0.225])\n", "])\n", "\n", "submission_ds = DogsDataset(TEST_IMG_PATH, submission_df, tdata_transform)\n", "\n", "sub_loader = DataLoader(submission_ds, batch_size=4,\n", "                        shuffle=False, num_workers=4)\n", "\n", "\n", "def test_sumission(model):\n", "    since = time.time()\n", "    sub_outputs = []\n", "    model.train(False)  # Set model to evaluate mode\n", "    # Iterate over data.\n", "    for data in sub_loader:\n", "        # get the inputs\n", "        inputs, labels = data\n", "\n", "        inputs = Variable(inputs.type(Tensor))\n", "        labels = Variable(labels.type(LongTensor))\n", "\n", "        # forward\n", "        outputs = model(inputs)\n", "        _, preds = torch.max(outputs.data, 1)\n", "        sub_outputs.append(outputs.data.cpu().numpy())\n", "\n", "    sub_outputs = np.concatenate(sub_outputs)\n", "    for idx,row in enumerate(sub_outputs.astype(float)):\n", "        sub_outputs[idx] = np.exp(row)/np.sum(np.exp(row))\n", "\n", "    output_df.loc[:,1:] = sub_outputs\n", "        \n", "    print()\n", "    time_elapsed = time.time() - since\n", "    print('Run complete in {:.0f}m {:.0f}s'.format(\n", "        time_elapsed // 60, time_elapsed % 60))\n", "\n", "    return output_df"], "metadata": {"collapsed": true, "_uuid": "0558295029ce6cfb4cb6eb442907ee0a7b40df19", "_cell_guid": "b50136b4-adb8-4f7a-bf2e-27889b10f397"}, "cell_type": "code", "outputs": []}, {"source": ["Obtain and save the submission file:"], "metadata": {"_uuid": "1b0848961d87a9bacc6b06a8af10ae51a11635e2", "_cell_guid": "fa918698-ea3c-4fe0-9ae4-8bf2c8e2e4f5"}, "cell_type": "markdown"}, {"execution_count": null, "source": ["odf = test_sumission(model_ft)\n", "odf.to_csv(\"dogs_id.csv\", index=False)"], "metadata": {"collapsed": true, "_uuid": "454a257c6fdfbcce710b48428c7acb1436f888f6", "_cell_guid": "df198d1b-fcdc-4d4d-9d86-2abfd48613e7"}, "cell_type": "code", "outputs": []}], "metadata": {"kernelspec": {"language": "python", "display_name": "Python 3", "name": "python3"}, "language_info": {"name": "python", "mimetype": "text/x-python", "codemirror_mode": {"version": 3, "name": "ipython"}, "pygments_lexer": "ipython3", "file_extension": ".py", "nbconvert_exporter": "python", "version": "3.6.3"}}, "nbformat": 4, "nbformat_minor": 1}