{"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"},"kaggle":{"accelerator":"none","dataSources":[{"sourceId":7327,"databundleVersionId":861871,"sourceType":"competition"}],"dockerImageVersionId":30042,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"test","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from __future__ import print_function, division\nimport numpy as np\nimport pandas as pd\nimport torch\nimport torch.nn as nn\nimport torch.optim as optim\nfrom torch.optim import lr_scheduler\nfrom torch.autograd import Variable\nfrom torch.utils.data import Dataset, DataLoader\nfrom torchvision import transforms, utils, models\n\nfrom PIL import Image\nimport matplotlib.pyplot as plt\nimport time\nimport os\n\nplt.ion()   # interactive mode\nmultiGPU = False","metadata":{"collapsed":true,"_uuid":"756fc55ddc14de0712204aee645fe3c6c74013fc","_cell_guid":"086f7268-82fb-4743-8ebb-3d998a051fea","jupyter":{"outputs_hidden":true}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"TRAIN_IMG_PATH = \"../input/train\"\nTEST_IMG_PATH = \"../input/test\"\nLABELS_CSV_PATH = \"../input/labels.csv\"\nSAMPLE_SUB_PATH = \"../input/sample_submission.csv\"","metadata":{"collapsed":true,"_uuid":"085602728c77b72820cea246f7366102da5ee71f","_cell_guid":"ac7aaa41-cadf-4e89-8e68-e8c891aad6d1","jupyter":{"outputs_hidden":true}},"outputs":[],"execution_count":null},{"cell_type":"code","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","jupyter":{"outputs_hidden":true}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"**Test**: Instantiate the class and show the first images and sizes.","metadata":{"_uuid":"6c7c3384a3fb116c1317fd26d1680ac695e49a19","_cell_guid":"3f0012a2-b780-4355-a289-c9c8e9b2c762"}},{"cell_type":"code","source":"dframe = pd.read_csv(LABELS_CSV_PATH)\nlabelnames = pd.read_csv(SAMPLE_SUB_PATH).keys()[1:]\ncodes = range(len(labelnames))\nbreed_to_code = dict(zip(labelnames, codes))\ncode_to_breed = dict(zip(codes, labelnames))\ndframe['target'] =  [breed_to_code[x] for x in dframe.breed]\n\ncut = int(len(dframe)*0.8)\ntrain, test = np.split(dframe, [cut], axis=0)\ntest = test.reset_index(drop=True)\n\ntrain_ds = DogsDataset(TRAIN_IMG_PATH, train)\ntest_ds = DogsDataset(TRAIN_IMG_PATH, test)\nidx = 29\nplt.imshow(train_ds[idx][0])\nprint(code_to_breed[train_ds[idx][1]])\nprint(\"Shape of the image is: \", train_ds[idx][0].size)","metadata":{"collapsed":true,"_uuid":"fef8eb5faa4ba59abea74a284a3141766be8e5b8","_cell_guid":"7d4821e0-e167-4dd8-97a0-20e3b7d5ec99","jupyter":{"outputs_hidden":true}},"outputs":[],"execution_count":null},{"cell_type":"markdown","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":"code","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","jupyter":{"outputs_hidden":true}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_ds = DogsDataset(TRAIN_IMG_PATH, train, data_transform)\ntest_ds = DogsDataset(TRAIN_IMG_PATH, test, data_transform)\ndatasets = {\"train\": train_ds, \"val\": test_ds}\n\nidx = 29\nprint(code_to_breed[train_ds[idx][1]])\nprint(\"Shape of the image is: \", train_ds[idx][0].shape)","metadata":{"collapsed":true,"_uuid":"0c0c03212b04abb492ec9773888745cfa78b2d1d","_cell_guid":"c4b42639-21ad-4a85-8244-e28959ad5e2a","jupyter":{"outputs_hidden":true}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"trainloader = DataLoader(train_ds, batch_size=4,\n                        shuffle=True, num_workers=4)\n\ntestloader = DataLoader(test_ds, batch_size=4,\n                        shuffle=True, num_workers=4)\n\ndataloaders = {\"train\": trainloader, \"val\": testloader}","metadata":{"collapsed":true,"_uuid":"067cfac5cf28bfc125034a50c7ebfea05b0e541f","_cell_guid":"50a35f51-75f6-42aa-9580-0988ac89a854","jupyter":{"outputs_hidden":true}},"outputs":[],"execution_count":null},{"cell_type":"markdown","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":"code","source":"if torch.cuda.is_available():\n    use_gpu = True\n    print(\"Using GPU\")\nelse:\n    use_gpu = False\nFloatTensor = torch.cuda.FloatTensor if use_gpu else torch.FloatTensor\nLongTensor = torch.cuda.LongTensor if use_gpu else torch.LongTensor\nByteTensor = torch.cuda.ByteTensor if use_gpu else torch.ByteTensor\nTensor = FloatTensor","metadata":{"collapsed":true,"_uuid":"1144d3c6710d28e8cea1f55c7c612b98f34a2074","_cell_guid":"b38ca60a-adc1-4b03-9e6d-b8a640de8afd","jupyter":{"outputs_hidden":true}},"outputs":[],"execution_count":null},{"cell_type":"code","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","jupyter":{"outputs_hidden":true}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"Load and Finetune model","metadata":{"_uuid":"ecddea1f4d7c5599987feb7bf2cd77460925b7df","_cell_guid":"4afd6f34-5369-4398-99ae-89da36279362"}},{"cell_type":"code","source":"model_ft = models.resnet152(pretrained=True)\nnum_ftrs = model_ft.fc.in_features\nmodel_ft.fc = nn.Linear(num_ftrs, 120)\n\nif 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\nif use_gpu:\n   model_ft.cuda()\n\ncriterion = nn.CrossEntropyLoss()\n\n# Observe that all parameters are being optimized\noptimizer_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\nexp_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","jupyter":{"outputs_hidden":true}},"outputs":[],"execution_count":null},{"cell_type":"code","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","jupyter":{"outputs_hidden":true}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## Preparing the submission","metadata":{"_uuid":"55e27ce599d6869dff4f7c148672a41ca20801c9","_cell_guid":"ca8edf52-eae8-45fc-8f43-8574ebc7e6d0"}},{"cell_type":"code","source":"submission_df = pd.read_csv(SAMPLE_SUB_PATH)\noutput_df = pd.DataFrame(index=submission_df.index, columns=submission_df.keys() )\noutput_df['id'] = submission_df['id']\nsubmission_df['target'] =  [0] * len(submission_df)\n\ntdata_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\nsubmission_ds = DogsDataset(TEST_IMG_PATH, submission_df, tdata_transform)\n\nsub_loader = DataLoader(submission_ds, batch_size=4,\n                        shuffle=False, num_workers=4)\n\n\ndef 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","jupyter":{"outputs_hidden":true}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"Obtain and save the submission file:","metadata":{"_uuid":"1b0848961d87a9bacc6b06a8af10ae51a11635e2","_cell_guid":"fa918698-ea3c-4fe0-9ae4-8bf2c8e2e4f5"}},{"cell_type":"code","source":"odf = test_sumission(model_ft)\nodf.to_csv(\"dogs_id.csv\", index=False)","metadata":{"collapsed":true,"_uuid":"454a257c6fdfbcce710b48428c7acb1436f888f6","_cell_guid":"df198d1b-fcdc-4d4d-9d86-2abfd48613e7","jupyter":{"outputs_hidden":true}},"outputs":[],"execution_count":null}]}