{"cells":[{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"# This Python 3 environment comes with many helpful analytics libraries installed\n# It is defined by the kaggle/python docker image: https://github.com/kaggle/docker-python\n# For example, here's several helpful packages to load in \n\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n\n# Input data files are available in the \"../input/\" directory.\n# For example, running this (by clicking run or pressing Shift+Enter) will list the files in the input directory\n\nimport os\nprint(os.listdir(\"../input\"))\n\nimport matplotlib.pyplot as plt\n\nimport torch\nfrom torchvision import datasets, transforms, models\n\n# Any results you write to the current directory are saved as output.\n\nfrom torch import nn, optim\nfrom torch.autograd import Variable\nfrom torch.utils.data.sampler import SubsetRandomSampler\nfrom torch.utils.data import Dataset, DataLoader\nfrom PIL import Image\nfrom skimage import io, transform\nimport torch.utils.data as data_utils","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_on_gpu = torch.cuda.is_available()\n\nif not train_on_gpu:\n    print('CUDA is not available.  Training on CPU ...')\nelse:\n    print('CUDA is available!  Training on GPU ...')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def 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","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"class DogBreedsDataset(Dataset):\n    \"\"\"Dog Breeds dataset.\"\"\"\n\n    def __init__(self, csv_file, root_dir, transform=None):\n        \"\"\"\n        Args:\n            csv_file (string): Path to the csv file with annotations.\n            root_dir (string): Directory with all the images.\n            transform (callable, optional): Optional transform to be applied\n                on a sample.\n        \"\"\"\n        self.labels_frame = pd.read_csv(csv_file)\n        self.map = dict(zip(self.labels_frame['breed'].unique(),range(0,len(self.labels_frame['breed'].unique()))))\n        self.labels_frame['breed'] = self.labels_frame['breed'].map(self.map)\n        self.root_dir = root_dir\n        self.transform = transform\n        \n    def getmap(self):\n        return self.map\n        \n    def __getclasses__(self):\n        return self.labels_frame['breed'].unique().tolist()\n\n    def __len__(self):\n        return len(self.labels_frame)\n\n    def __getitem__(self, idx):\n        img_name = os.path.join(self.root_dir,\n                                self.labels_frame.iloc[idx, 0])\n        img_name = img_name + '.jpg'\n        \n        image = io.imread(img_name)\n        PIL_image = Image.fromarray(image)\n        label = self.labels_frame.iloc[idx, 1:]\n        label = [int(label) for x in label]\n        label = np.asarray(label)\n        label = torch.from_numpy(label)\n        if self.transform:\n            image = self.transform(PIL_image)\n        #sample = {'image': image, 'label': label}\n        return image,label","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"class DogBreedsTestset(Dataset):\n    \"\"\"Dog Breeds Test dataset.\"\"\"\n\n    def __init__(self, csv_file, root_dir, transform=None):\n        \"\"\"\n        Args:\n            csv_file (string): Path to the csv file with annotations.\n            root_dir (string): Directory with all the images.\n            transform (callable, optional): Optional transform to be applied\n                on a sample.\n        \"\"\"\n        self.labels_frame = pd.read_csv(csv_file)\n        self.labels_frame = self.labels_frame[['id']]\n        self.root_dir = root_dir\n        self.transform = transform\n   \n    def __len__(self):\n        return len(self.labels_frame)\n\n\n    def __getitem__(self, idx):\n        title = self.labels_frame.iloc[idx, 0]\n        img_name = os.path.join(self.root_dir,\n                                title)\n        img_name = img_name + '.jpg'\n        \n        image = io.imread(img_name)\n        PIL_image = Image.fromarray(image)\n        \n        if self.transform:\n            image = self.transform(PIL_image)\n        sample = {'image': image, 'title': title}\n        return sample","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"data_dir = '../input'\n\n# how many samples per batch to load\nbatch_size = 20\n# percentage of training set to use as validation\nvalid_size = 0.2\n\n\n# TODO: Define transforms for the training data and testing data\ntransform = transforms.Compose([transforms.Resize(255),\n    transforms.CenterCrop(224),\n    transforms.ToTensor(),\n    transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))\n    ])\n\ntest_transforms = transforms.Compose([\n                                      transforms.ToTensor()])\n\ntrain_data = DogBreedsDataset(csv_file='../input/labels.csv',root_dir='../input/train', transform=transform)\n#test_data = datasets.ImageFolder(data_dir + '/test', transform=test_transforms)\nclasses = train_data.__getclasses__()\nprint(classes)\n#obtain training indices that will be used for validation\nnum_train = len(train_data)\nindices = list(range(num_train))\nnp.random.shuffle(indices)\nsplit = int(np.floor(valid_size * num_train))\ntrain_idx, valid_idx = indices[split:], indices[:split]\n\n# define samplers for obtaining training and validation batches\ntrain_sampler = SubsetRandomSampler(train_idx)\nvalid_sampler = SubsetRandomSampler(valid_idx)\n\n# prepare data loaders\ntrain_loader = torch.utils.data.DataLoader(train_data, batch_size=batch_size,\n    sampler=train_sampler)\nvalid_loader = torch.utils.data.DataLoader(train_data, batch_size=batch_size, \n    sampler=valid_sampler)\n#test_loader = torch.utils.data.DataLoader(test_data, batch_size=batch_size)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"df_test = pd.read_csv('../input/sample_submission.csv')\ndf_test.head(1)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"test_data = DogBreedsTestset(csv_file='../input/sample_submission.csv',root_dir='../input/test', transform=transform)\ntest_loader = torch.utils.data.DataLoader(test_data, batch_size=20)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"data_iter = iter(train_loader)\nimages, labels = data_iter.next()\nimages = images.numpy() # convert images to numpy for display\n# plot the images in the batch, along with the corresponding labels\nfig = plt.figure(figsize=(25, 4))\nfor idx in np.arange(20):\n    ax = fig.add_subplot(2, 20/2, idx+1, xticks=[], yticks=[])\n    plt.imshow(np.transpose(images[idx], (1, 2, 0)))\n    #ax.set_title(classes[labels[idx]])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Load the pretrained model from pytorch\nvgg16 = models.vgg16(pretrained=True)\n\n# print out the model structure\nprint(vgg16)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"\n# Freeze training for all \"features\" layers\nfor param in vgg16.features.parameters():\n    param.requires_grad = False","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"n_inputs = vgg16.classifier[6].in_features\n\n# add last linear layer (n_inputs -> 5 flower classes)\n# new layers automatically have requires_grad = True\nlast_layer = nn.Linear(n_inputs, len(classes))\n\nvgg16.classifier[6] = last_layer\n\n# if GPU is available, move the model to GPU\nif train_on_gpu:\n    vgg16.cuda()\n\n# check to see that your last layer produces the expected number of outputs\nprint(vgg16.classifier[6].out_features)\n#print(vgg16)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import torch.optim as optim\n\n# specify loss function (categorical cross-entropy)\ncriterion = nn.CrossEntropyLoss()\n\n# specify optimizer (stochastic gradient descent) and learning rate = 0.001\noptimizer = optim.SGD(vgg16.classifier.parameters(), lr=0.001)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# number of epochs to train the model\nn_epochs = 15\n\nfor epoch in range(1, n_epochs+1):\n\n    # keep track of training and validation loss\n    train_loss = 0.0\n    valid_loss = 0.0\n    ###################\n    # train the model #\n    ###################\n    # model by default is set to train\n    \n    for batch_i, (data, target) in enumerate(train_loader):\n        # move tensors to GPU if CUDA is available\n       \n        if train_on_gpu:\n            data, target = data.cuda(), target.cuda()\n        # clear the gradients of all optimized variables\n        optimizer.zero_grad()\n        # forward pass: compute predicted outputs by passing inputs to the model\n        output = vgg16(data)\n        # calculate the batch loss\n        loss = criterion(output, torch.max(target, 1)[1])\n        # backward pass: compute gradient of the loss with respect to model parameters\n        loss.backward()\n        # perform a single optimization step (parameter update)\n        optimizer.step()\n        # update training loss \n        train_loss += loss.item()\n        \n        if batch_i % 20 == 19:    # print training loss every specified number of mini-batches\n            print('Epoch %d, Batch %d loss: %.16f' %\n                  (epoch, batch_i + 1, train_loss / 20))\n            train_loss = 0.0","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"valid_loss = 0.0\nvgg16.eval()\nfor batch_i, (data, target) in enumerate(valid_loader):\n        # move tensors to GPU if CUDA is available\n       \n        if train_on_gpu:\n            data, target = data.cuda(), target.cuda()\n            \n        output = vgg16(data)\n        # calculate the batch loss\n        loss = criterion(output, torch.max(target, 1)[1])\n        \n        # update training loss \n        valid_loss += loss.item()\n        \n        if batch_i % 20 == 19:    # print validation loss every specified number of mini-batches\n            print('Validation Loss Batch %d loss: %.16f' %\n                  (batch_i + 1, valid_loss / 20))\n            valid_loss = 0.0","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"results = {}\nvgg16.eval()\n\nfor (_,data) in enumerate(test_loader):\n        # move tensors to GPU if CUDA is available\n        images,titles = data['image'], data['title']\n               \n        if train_on_gpu:\n            images = images.cuda()\n        #print(title)\n        logits = vgg16(images)\n        output = torch.nn.functional.softmax(logits, dim=1)\n        \n        for k in range(len(titles)):\n            name = titles[k]\n            results[name] = output[k].cpu().tolist()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"output_df = pd.DataFrame(results).transpose()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"inv_map = {v: k for k, v in train_data.getmap().items()}\ninv_map","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"output_df.rename(columns=inv_map,inplace=True)\noutput_df = output_df.reset_index()\noutput_df.rename(columns={'index':'id'},inplace=True)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"output_df.to_csv('output.csv',index=False)","execution_count":null,"outputs":[]}],"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"name":"python","version":"3.6.4","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"}},"nbformat":4,"nbformat_minor":1}