{"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, shutil, re\nprint(os.listdir(\"../input\"))\n\n# Any results you write to the current directory are saved as output.","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"1e39384c1263a1d4730a0bc9f7cb9c865d9c120c","scrolled":false},"cell_type":"code","source":"\n!cp ../input/train/train ./train","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"f0b3d228e85cd683a8db3b5cdb189fee18f12857"},"cell_type":"code","source":"!mkdir ./train/cat\n!mkdir ./train/dog","execution_count":null,"outputs":[]},{"metadata":{"_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","trusted":true},"cell_type":"code","source":"# check submission file\nsub = pd.read_csv('../input/sampleSubmission.csv')\nsub.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"bffd185fcd43cf9c00b48433f8a6b9e05ccdb073"},"cell_type":"code","source":"from os import listdir\nfrom tqdm import tqdm_notebook\ntrain1 = []\nfor i in tqdm_notebook(listdir('../input/train/train')):\n    if re.search(\"cat\", i):\n        shutil.move('./train/'+i, './train/cat/')\n    else:\n        shutil.move('./train/'+i, './train/dog/')\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"b382dd6e637e7cb9a54395ef6b8f42c504ff611d"},"cell_type":"code","source":"\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"fd7b046e631586ba7a094631a7da988ec66f885d"},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"df326492c9c19d6db1eca1b55537b5d6a1ea2f0d"},"cell_type":"code","source":"import matplotlib.pyplot as plt\nimport matplotlib.image as image\n\nplt.imshow(image.imread(\"../input/train/train/dog.12497.jpg\")) ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"333c6d65a389593e7f79f8b5f9b695fbc8bccd6b"},"cell_type":"code","source":"import torch\nfrom torch import nn, optim\nfrom torchvision import datasets, transforms, models\nfrom torch.utils.data.sampler import SubsetRandomSampler\n\n\ntrain_transform = transforms.Compose([transforms.RandomRotation(30),\n                               transforms.RandomResizedCrop(224),\n                               transforms.RandomHorizontalFlip(),\n                               transforms.ToTensor(),\n                               transforms.Normalize([0.485, 0.456, 0.406],\n                                                    [0.229, 0.224, 0.225])])\n\ntest_transform = transforms.Compose([transforms.Resize(255),\n                               transforms.CenterCrop(224),\n                               transforms.ToTensor(),\n                               transforms.Normalize([0.485, 0.456, 0.406],\n                                                    [0.229, 0.224, 0.225])])\n\n\ntrain_data = datasets.ImageFolder(\"./train/\", transform = train_transform)\ntest_data = datasets.ImageFolder(\"../input/test1\", transform = test_transform)\n\nvalid_size = 0.2\nl = list(range(len(train_data)))\nnp.random.shuffle(l)\nsplit = int(np.floor(valid_size*len(train_data)))\ntrain_idx, valid_idx = l[split:], l[:split]\n\ntrain_sampler = torch.utils.data.sampler.SubsetRandomSampler(train_idx)\nvalid_sampler = torch.utils.data.sampler.SubsetRandomSampler(valid_idx)\n\ntrain_loader = torch.utils.data.DataLoader(train_data, batch_size = 20, sampler=train_sampler)\nvalid_loader = torch.utils.data.DataLoader(train_data, sampler=valid_sampler, batch_size = 20)\ntest_loader = torch.utils.data.DataLoader(test_data, batch_size=20)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"a2bfd5b011b4cc6cca924cfe7a8c1fba9f5e4ecf"},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"scrolled":true,"_uuid":"84b6dcb46baddcef5d2ff2f32a91e1cc1087924c"},"cell_type":"code","source":"first = iter(train_loader)\nimage, label = next(first)\nprint(image.shape)\nimage = image.numpy()\nimage = image[0] / 2 + 0.5  # unnormalize\nplt.imshow(np.transpose(image, (1, 2, 0)))\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"a133699354768ac1cab8c320417533251ee6b48a","scrolled":true},"cell_type":"code","source":"device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\n\nmodel = models.densenet121(pretrained=True)\n\n# Freeze parameters so we don't backprop through them\nfor param in model.parameters():\n    param.requires_grad = False\n    \nmodel.classifier = nn.Sequential(nn.Linear(1024, 256),\n                                 nn.ReLU(),\n                                 nn.Dropout(0.2),\n                                 nn.Linear(256, 2),\n                                 nn.LogSoftmax(dim=1))\n\ncriterion = nn.NLLLoss()\n\n# Only train the classifier parameters, feature parameters are frozen\noptimizer = optim.Adam(model.classifier.parameters(), lr=0.003)\n\nmodel.to(device);","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"e58d95c9570ee17e39835b58dde8675b776c9c07"},"cell_type":"code","source":"# number of epochs to train the model\nn_epochs = 1\n\nvalid_loss_min = np.Inf # track change in validation loss\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    ###################\n    # train the model #\n    ###################\n    model.train()\n    for data, target in tqdm_notebook(train_loader):\n        # move tensors to GPU if CUDA is available\n        if torch.cuda.is_available():\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 = model.forward(data)\n        # calculate the batch loss\n        loss = criterion(output, target)\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()*data.size(0)\n        \n    ######################    \n    # validate the model #\n    ######################\n    model.eval()\n    for data, target in valid_loader:\n        # move tensors to GPU if CUDA is available\n        if torch.cuda.is_available():\n            data, target = data.cuda(), target.cuda()\n        # forward pass: compute predicted outputs by passing inputs to the model\n        output = model.forward(data)\n        # calculate the batch loss\n        loss = criterion(output, target)\n        # update average validation loss \n        valid_loss += loss.item()*data.size(0)\n    \n    # calculate average losses\n    train_loss = train_loss/len(train_loader.dataset)\n    valid_loss = valid_loss/len(valid_loader.dataset)\n        \n    # print training/validation statistics \n    print('Epoch: {} \\tTraining Loss: {:.6f} \\tValidation Loss: {:.6f}'.format(\n        epoch, train_loss, valid_loss))\n    \n    # save model if validation loss has decreased\n    if valid_loss <= valid_loss_min:\n        print('Validation loss decreased ({:.6f} --> {:.6f}).  Saving model ...'.format(\n        valid_loss_min,\n        valid_loss))\n        torch.save(model.state_dict(), 'model_cifar.pt')\n        valid_loss_min = valid_loss","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"c929b262693fead0603d9bc5ef513265fd28e9ac"},"cell_type":"code","source":"model.load_state_dict(torch.load('model_cifar.pt'))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"9a3854cde2b07d72e2b39981abf23896c72825ae"},"cell_type":"code","source":"import warnings\nwarnings.filterwarnings('ignore')\nmodel.eval()\nfor data, target in test_loader:\n    \n    data, target = data.cuda(), target.cuda()\n    output = model(data)\n\n    ps = torch.exp(output)\n    top_p, top_class = ps.topk(1, dim=1)\n    image = data\n    image = image.cpu().numpy()\n    t = top_class.cpu().numpy()\n    w=10\n    h=10\n\n \n\n    plt.figure(figsize=(12, 12))\n    for i in range(0,15):\n        plt.subplot(5, 3, i+1)\n        \n        plt.tight_layout()\n        \n        img = image[i] / 2 + 0.5  # unnormalize\n        if t[i]==1: a=\"dog\"\n        else: a = \"cat\"\n        plt.title(a)\n        plt.axis('off')\n        plt.imshow(np.transpose(img, (1, 2, 0)))\n\n    plt.show()\n\n    break","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"6afb0de4bfa4a5352757a2b9c28939b4e2d94aa5"},"cell_type":"code","source":"len(test_data)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"218bbae4c2eef9a104acdd9ef926563d7eeb54cb","scrolled":true},"cell_type":"code","source":"import torch.utils.data as data\n\nfrom PIL import Image\n\nimport os\nimport os.path\nimport sys\n\n\ndef has_file_allowed_extension(filename, extensions):\n    \"\"\"Checks if a file is an allowed extension.\n    Args:\n        filename (string): path to a file\n        extensions (iterable of strings): extensions to consider (lowercase)\n    Returns:\n        bool: True if the filename ends with one of given extensions\n    \"\"\"\n    filename_lower = filename.lower()\n    return any(filename_lower.endswith(ext) for ext in extensions)\n\n\ndef is_image_file(filename):\n    \"\"\"Checks if a file is an allowed image extension.\n    Args:\n        filename (string): path to a file\n    Returns:\n        bool: True if the filename ends with a known image extension\n    \"\"\"\n    return has_file_allowed_extension(filename, IMG_EXTENSIONS)\n\n\ndef make_dataset(dir, class_to_idx, extensions):\n    images = []\n    dir = os.path.expanduser(dir)\n    for target in sorted(class_to_idx.keys()):\n        d = os.path.join(dir, target)\n        if not os.path.isdir(d):\n            continue\n\n        for root, _, fnames in sorted(os.walk(d)):\n            for fname in sorted(fnames):\n                if has_file_allowed_extension(fname, extensions):\n                    path = os.path.join(root, fname)\n                    item = (path, class_to_idx[target])\n                    images.append(item)\n\n    return images\n\n\nclass DatasetFolder(data.Dataset):\n    \"\"\"A generic data loader where the samples are arranged in this way: ::\n        root/class_x/xxx.ext\n        root/class_x/xxy.ext\n        root/class_x/xxz.ext\n        root/class_y/123.ext\n        root/class_y/nsdf3.ext\n        root/class_y/asd932_.ext\n    Args:\n        root (string): Root directory path.\n        loader (callable): A function to load a sample given its path.\n        extensions (list[string]): A list of allowed extensions.\n        transform (callable, optional): A function/transform that takes in\n            a sample and returns a transformed version.\n            E.g, ``transforms.RandomCrop`` for images.\n        target_transform (callable, optional): A function/transform that takes\n            in the target and transforms it.\n     Attributes:\n        classes (list): List of the class names.\n        class_to_idx (dict): Dict with items (class_name, class_index).\n        samples (list): List of (sample path, class_index) tuples\n        targets (list): The class_index value for each image in the dataset\n    \"\"\"\n\n    def __init__(self, root, loader, extensions, transform=None, target_transform=None):\n        classes, class_to_idx = self._find_classes(root)\n        samples = make_dataset(root, class_to_idx, extensions)\n        if len(samples) == 0:\n            raise(RuntimeError(\"Found 0 files in subfolders of: \" + root + \"\\n\"\n                               \"Supported extensions are: \" + \",\".join(extensions)))\n\n        self.root = root\n        self.loader = loader\n        self.extensions = extensions\n\n        self.classes = classes\n        self.class_to_idx = class_to_idx\n        self.samples = samples\n        self.targets = [s[1] for s in samples]\n\n        self.transform = transform\n        self.target_transform = target_transform\n\n    def _find_classes(self, dir):\n        \"\"\"\n        Finds the class folders in a dataset.\n        Args:\n            dir (string): Root directory path.\n        Returns:\n            tuple: (classes, class_to_idx) where classes are relative to (dir), and class_to_idx is a dictionary.\n        Ensures:\n            No class is a subdirectory of another.\n        \"\"\"\n        if sys.version_info >= (3, 5):\n            # Faster and available in Python 3.5 and above\n            classes = [d.name for d in os.scandir(dir) if d.is_dir()]\n        else:\n            classes = [d for d in os.listdir(dir) if os.path.isdir(os.path.join(dir, d))]\n        classes.sort()\n        class_to_idx = {classes[i]: i for i in range(len(classes))}\n        return classes, class_to_idx\n\n    def __getitem__(self, index):\n        \"\"\"\n        Args:\n            index (int): Index\n        Returns:\n            tuple: (sample, target) where target is class_index of the target class.\n        \"\"\"\n        path, target = self.samples[index]\n        sample = self.loader(path)\n        if self.transform is not None:\n            sample = self.transform(sample)\n        if self.target_transform is not None:\n            target = self.target_transform(target)\n\n        return sample, path\n\n    def __len__(self):\n        return len(self.samples)\n\n    def __repr__(self):\n        fmt_str = 'Dataset ' + self.__class__.__name__ + '\\n'\n        fmt_str += '    Number of datapoints: {}\\n'.format(self.__len__())\n        fmt_str += '    Root Location: {}\\n'.format(self.root)\n        tmp = '    Transforms (if any): '\n        fmt_str += '{0}{1}\\n'.format(tmp, self.transform.__repr__().replace('\\n', '\\n' + ' ' * len(tmp)))\n        tmp = '    Target Transforms (if any): '\n        fmt_str += '{0}{1}'.format(tmp, self.target_transform.__repr__().replace('\\n', '\\n' + ' ' * len(tmp)))\n        return fmt_str\n\n\nIMG_EXTENSIONS = ['.jpg', '.jpeg', '.png', '.ppm', '.bmp', '.pgm', '.tif', '.tiff', 'webp']\n\n\ndef pil_loader(path):\n    # open path as file to avoid ResourceWarning (https://github.com/python-pillow/Pillow/issues/835)\n    with open(path, 'rb') as f:\n        img = Image.open(f)\n        return img.convert('RGB')\n\n\ndef accimage_loader(path):\n    import accimage\n    try:\n        return accimage.Image(path)\n    except IOError:\n        # Potentially a decoding problem, fall back to PIL.Image\n        return pil_loader(path)\n\n\ndef default_loader(path):\n    from torchvision import get_image_backend\n    if get_image_backend() == 'accimage':\n        return accimage_loader(path)\n    else:\n        return pil_loader(path)\n\n\nclass ImageFolder(DatasetFolder):\n    \"\"\"A generic data loader where the images are arranged in this way: ::\n        root/dog/xxx.png\n        root/dog/xxy.png\n        root/dog/xxz.png\n        root/cat/123.png\n        root/cat/nsdf3.png\n        root/cat/asd932_.png\n    Args:\n        root (string): Root directory path.\n        transform (callable, optional): A function/transform that  takes in an PIL image\n            and returns a transformed version. E.g, ``transforms.RandomCrop``\n        target_transform (callable, optional): A function/transform that takes in the\n            target and transforms it.\n        loader (callable, optional): A function to load an image given its path.\n     Attributes:\n        classes (list): List of the class names.\n        class_to_idx (dict): Dict with items (class_name, class_index).\n        imgs (list): List of (image path, class_index) tuples\n    \"\"\"\n    def __init__(self, root, transform=None, target_transform=None,\n                 loader=default_loader):\n        super(ImageFolder, self).__init__(root, loader, IMG_EXTENSIONS,\n                                          transform=transform,\n                                          target_transform=target_transform)\n        self.imgs = self.samples","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"3f0492cfe213dfcf5bfdb0eaf606babaead5d94b"},"cell_type":"code","source":"data_dir = '../input/test1'\na = ImageFolder(data_dir, transform = test_transform)\ntest_loader = DataLoader(a,batch_size=20,shuffle=False)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"583110502010bc37a99bf6227d140ca4c77edf57"},"cell_type":"code","source":"subm = {}\nfor image,name in test_loader:\n    n,l = {}, {}\n    for i in range(len(name)):\n        n[i] = name[i].split('/')\n        l[i] = n[i][4].split('.')[0]\n      \n    data = image.cuda()\n    output = model(data)\n\n    ps = torch.exp(output)\n    top_p, top_class = ps.topk(1, dim=1)\n    t = top_class.cpu().numpy()\n\n    for i in range(len(name)):\n        subm[int(l[i])] = t[i].item()\n    \n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"d76fdf36eb50dda131bda528e1a1a1369bbe2910"},"cell_type":"code","source":"q =  pd.DataFrame(list(subm.items()), columns=['id', 'label'])\nq = q.sort_values(by=['id'])\nq.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"0b99731f8296a9714443be0da70ca1c7f1fe1bff"},"cell_type":"code","source":"q.to_csv('submission.csv', sep='\\t')\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"7b516acd71b64609c3f65159ceece949087fbb0e"},"cell_type":"code","source":"from IPython.display import HTML\nimport pandas as pd\nimport numpy as np\nimport base64\n\n# function that takes in a dataframe and creates a text link to  \n# download it (will only work for files < 2MB or so)\ndef create_download_link(df, title = \"Download CSV file\", filename = \"submission.csv\"):  \n    csv = df.to_csv()\n    b64 = base64.b64encode(csv.encode())\n    payload = b64.decode()\n    html = '<a download=\"{filename}\" href=\"data:text/csv;base64,{payload}\" target=\"_blank\">{title}</a>'\n    html = html.format(payload=payload,title=title,filename=filename)\n    return HTML(html)\n\n# create a random sample dataframe\ndf = pd.DataFrame(list(subm.items()), columns=['id', 'label'])\ndf = df.sort_values(by=['id'])\n\n# create a link to download the dataframe\ncreate_download_link(df)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"49224c9b4008396045c24d35f4723979f459ff7c"},"cell_type":"code","source":"","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}