{"cells":[{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"import os\nimport numpy as np # linear algebra\nfrom tqdm import tqdm # progress bar to ease my anxiety\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n\nimport time\nimport json\nimport copy\n\nimport torch\nimport torch.nn as nn\nimport torch.optim as optim\nimport torchvision\nfrom torchvision import datasets, models, transforms\nfrom torch.utils.data import DataLoader, Dataset\nfrom torch.autograd import Variable\nimport matplotlib.pyplot as plt\nfrom collections import OrderedDict\nfrom sklearn.preprocessing import LabelEncoder, OneHotEncoder\n\nfrom PIL import Image\n%matplotlib inline\n%load_ext autoreload\n%autoreload 2","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"5cc4aeef58c634d79d71747aa8015c9cbdf6a9c4"},"cell_type":"code","source":"# check if CUDA is available\ntrain_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":{"_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","trusted":true},"cell_type":"code","source":"# visualize the label map & number of classes\nlabels = pd.read_csv(\"../input/train.csv\")\nlabels.head()\nprint(type(labels))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"fc0c78387900bb7e2e31e85dae926ce7021f4495"},"cell_type":"code","source":"num_classes = len(labels['Id'].unique())\nprint(num_classes)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"f16f3bc7d2b8e758c50584eff14993e4703289a3"},"cell_type":"code","source":"# define data directories \ndata_dir = '../input'\ntrain_dir = data_dir + '/train'\ntest_dir = data_dir + '/test'","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"616ca7b14e6c2af32c845f1ab3c9353abf80198a"},"cell_type":"code","source":"# pytorch provides a function to convert PIL images to tensors.\n# credit: https://www.cs.virginia.edu/~vicente/recognition/notebooks/image_processing_lab.html\npil2tensor = transforms.ToTensor()\ntensor2pil = transforms.ToPILImage()\n\n# Read the image from file. Assuming it is in the same directory.\npil_image = Image.open(train_dir + '/0a750c2e8.jpg') \nrgb_image = pil2tensor(pil_image)\n\n# Plot the image here using matplotlib.\ndef plot_image(tensor):\n    plt.figure()\n    # imshow needs a numpy array with the channel dimension\n    # as the the last dimension so we have to transpose things.\n    plt.imshow(tensor.numpy().transpose(1, 2, 0))\n    plt.show()\n\nplot_image(rgb_image)\n\n# Show the image tensor type and tensor size here.\nprint('Image type: ' + str(rgb_image.type()))\nprint('Image size: ' + str(rgb_image.size()))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"f6d90c0b89e5c9a73f6e2c0aba3130649dcc5a45"},"cell_type":"code","source":"# credit: https://www.cs.virginia.edu/~vicente/recognition/notebooks/image_processing_lab.html\nfrom io import BytesIO\nimport IPython.display\n\nr_image = rgb_image[0]\ng_image = rgb_image[1]\nb_image = rgb_image[2]\n\ndef show_grayscale_image(tensor):\n    f = BytesIO()\n    a = np.uint8(tensor.mul(255).numpy()) \n    Image.fromarray(a).save(f, 'png')\n    IPython.display.display(IPython.display.Image(data = f.getvalue()))\n\nshow_grayscale_image(torch.cat((r_image, g_image, b_image), 1))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"e904d04f0af0a99b35e980f22bcd17b2713aa811"},"cell_type":"code","source":"# Define transforms and data augmentation\nmean = [0.485, 0.456, 0.406]\nstd = [0.229, 0.224, 0.225]\n\ntrain_data = transforms.Compose([transforms.Resize(256),\n                                       transforms.RandomResizedCrop(224),\n                                       transforms.RandomRotation(25),\n                                       transforms.RandomHorizontalFlip(),\n                                       transforms.ColorJitter(brightness=0, contrast=0, saturation=0, hue=0),\n                                       transforms.RandomAffine(degrees=4, translate=None, scale=None, shear=None, resample=False, fillcolor=0),\n                                       transforms.ToTensor(),\n                                       transforms.Normalize(mean, std)])\n\ntest_data = transforms.Compose([transforms.Resize(256),\n                                      transforms.CenterCrop(224),\n                                      transforms.ToTensor(),\n                                      transforms.Normalize(mean, std)])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"cac63c8810b95322aeff1ffcb3a7eecf9f103383"},"cell_type":"code","source":"# one-hot encode the labels\ndef encode_labels(y):\n    values = np.array(y)\n    label_encoder = LabelEncoder()\n    integer_encoded = label_encoder.fit_transform(values)\n    \n    print(values)\n    print(integer_encoded)\n\n    onehot_encoder = OneHotEncoder(sparse=False)\n    integer_encoded = integer_encoded.reshape(len(integer_encoded), 1)\n    print(integer_encoded)\n    onehot_encoded = onehot_encoder.fit_transform(integer_encoded)\n    print(len(integer_encoded))\n    print(onehot_encoded)\n    print(len(onehot_encoded[0]))\n\n    y = onehot_encoded\n    return y, label_encoder\n\ny, label_encoder = encode_labels(labels['Id'])\n# this will throw a FutureWarning, ignore it.","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"a3d5ae15c66e3f41fe9d9628345bd0c7f1a87c82"},"cell_type":"code","source":"# create a dataset out of the whale tail data\nclass WhaleTailDataset(Dataset):\n    def __init__(self, image_folder, data_type='train', df=None, transform=None, y=None):\n        self.image_folder = image_folder\n        self.imgs_list = [img for img in os.listdir(image_folder)]\n        self.data_type = data_type\n        self.transform = transform\n        self.y = y # one hot vector \n        if self.data_type == 'train':\n            self.df = df.values\n            print(self.df) #self.df refers to img,class array\n    \n    def __len__(self):\n        return len(self.imgs_list)\n    \n    def __getitem__(self, idx):\n        if self.data_type == 'train':\n            img_name = os.path.join(self.image_folder, self.df[idx][0])\n            label = self.y[idx] #return one hot vector \n        \n        elif self.data_type == 'test':\n            img_name = os.path.join(self.image_folder, self.imgs_list[idx])\n            label = np.zeros((num_classes,))\n        \n        img = Image.open(img_name).convert('RGB')\n        img = self.transform(img)\n        if self.data_type == 'train':\n            return img, label\n        elif self.data_type == 'test':\n            return img, label, self.imgs_list[idx]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"973a99e9f40fe5a0070e532cde4aeb0f5022b250"},"cell_type":"code","source":"# load and define the datasets\nimage_datasets = dict()\nimage_datasets['train'] = WhaleTailDataset(image_folder=train_dir, data_type='train', df=labels, transform=train_data, y=y)\nimage_datasets['test'] = WhaleTailDataset(image_folder=test_dir, data_type='test', transform=test_data)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"f44fb43056e70f47a6f1278c32617067dda77f6a"},"cell_type":"code","source":"# define data & batch loaders\ntrain_size = 512\ntest_size = 32\nnum_workers = 0\n\ndataloaders = dict()\ndataloaders['train'] = torch.utils.data.DataLoader(image_datasets['train'], batch_size=train_size, num_workers=num_workers)\ndataloaders['test'] = torch.utils.data.DataLoader(image_datasets['test'], batch_size=test_size, num_workers=num_workers)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"17a609a43e04f5736ce1b7fccd93cd866c0a4c20"},"cell_type":"code","source":"# view data statistics by type\nprint('Number of training images: ', len(image_datasets['train']))\nprint('Number of test images: ', len(image_datasets['test']))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"46e43b223fe64db8322c619e013cb982684b53d4"},"cell_type":"code","source":"# view tensor size \ndataiter = iter(dataloaders['train'])\nimages, labels = dataiter.next()\n\nprint('Batch shape: ', images.size())","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"695fef42f042d5b077bb1a3ff653d5e7875c8ec2","collapsed":true},"cell_type":"code","source":"# define pre-trained model\nmodel = models.resnet152(pretrained=True)\n\n# freeze parameters\nfor param in model.parameters():\n    param.requires_grad = False\n    \nprint(model)    ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"627feb8f09817fc0e552d84c4ae03648d49e88e8"},"cell_type":"code","source":"# define new untrained network\nclassifier = nn.Sequential(nn.Linear(2048, 1024),\n                         nn.ReLU(),\n                         nn.Dropout(0.5),\n                         nn.Linear(1024, 512),\n                         nn.ReLU(),\n                         nn.Dropout(0.5),\n                         nn.Linear(512, 5005),\n                         nn.LogSoftmax(dim=1)\n                        )\nmodel.fc = classifier","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"889603cd3eca669edb97ee6348ff019b75ff6580"},"cell_type":"code","source":"# define hyperperameters\nfrom torch.optim import lr_scheduler\n\nnum_epochs = 6\nlearning_rate = 0.001\n\ncriterion = nn.BCEWithLogitsLoss()\noptimizer = optim.Adam(model.fc.parameters(), lr=learning_rate)\nscheduler = lr_scheduler.StepLR(optimizer, step_size=3, gamma=0.1)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"ec718642fd2adc33601b1aa40f3ad1c690d4306c"},"cell_type":"code","source":"# train the model\nimport matplotlib.pyplot as plt\nmodel = model.cuda()\ntrain_loss = []\nfor epoch in range(1, num_epochs+1):\n\n    \n    for batch_i, (data, target) in tqdm(enumerate(dataloaders['train']), total = len(dataloaders['train'])):\n        data, target = data.cuda(), target.cuda()\n\n        optimizer.zero_grad()\n        output = model(data)\n        loss = criterion(output, target.float())\n        train_loss.append(loss.item())\n\n        loss.backward()\n        optimizer.step()\n    \n    scheduler.step()\n    \n    print(f'Epoch - {epoch} // Training Loss: {np.mean(train_loss):.4f}')\n\nprint(train_loss)\nplt.figure()\nplt.plot(train_loss)\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"20f2252ab3d8ff29ad88a46b6779680155cc083a"},"cell_type":"code","source":"sub = pd.read_csv('../input/sample_submission.csv')\n\nmodel.eval()\nfor (data, target, name) in tqdm(dataloaders['test']):\n    data = data.cuda()\n    output = model(data)\n    output = output.cpu().detach().numpy()\n    for i, (e, n) in enumerate(list(zip(output, name))):\n        sub.loc[sub['Image'] == n, 'Id'] = ' '.join(label_encoder.inverse_transform(e.argsort()[-5:][::-1]))\n        \nsub.to_csv('submission.csv', index=False)","execution_count":null,"outputs":[]}],"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"name":"python","version":"3.6.6","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"}},"nbformat":4,"nbformat_minor":1}