{"cells":[{"metadata":{"trusted":true},"cell_type":"code","source":"import pandas as pd\nsampleSubmission = pd.read_csv(\"../input/dogs-vs-cats/sampleSubmission.csv\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"collapsed":true},"cell_type":"code","source":"!  unzip /kaggle/input/dogs-vs-cats/test1.zip -d /dev/shm\n# !  unzip /kaggle/input/dogs-vs-cats/test1.zip -d /dev/shm","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"collapsed":true},"cell_type":"code","source":"!  unzip /kaggle/input/dogs-vs-cats/train.zip -d /dev/shm","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# print(os.listdir(os.getcwd()))\nprint(sampleSubmission.head(1))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print(type(sampleSubmission))\nprint(sampleSubmission)\nprint(sampleSubmission.next())","execution_count":null,"outputs":[]},{"metadata":{"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 all files under the input directory\n\nimport os\nfor dirname, _, filenames in os.walk('/dev/shm/'):\n    for filename in filenames:\n        print(os.path.join(dirname, filename))\n\n# Any results you write to the current directory are saved as output.","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Transfer Learning\n\nIn this notebook, you'll learn how to use pre-trained networks to solved challenging problems in computer vision. Specifically, you'll use networks trained on [ImageNet](http://www.image-net.org/) [available from torchvision](http://pytorch.org/docs/0.3.0/torchvision/models.html). \n\nImageNet is a massive dataset with over 1 million labeled images in 1000 categories. It's used to train deep neural networks using an architecture called convolutional layers. I'm not going to get into the details of convolutional networks here, but if you want to learn more about them, please [watch this](https://www.youtube.com/watch?v=2-Ol7ZB0MmU).\n\nOnce trained, these models work astonishingly well as feature detectors for images they weren't trained on. Using a pre-trained network on images not in the training set is called transfer learning. Here we'll use transfer learning to train a network that can classify our cat and dog photos with near perfect accuracy.\n\nWith `torchvision.models` you can download these pre-trained networks and use them in your applications. We'll include `models` in our imports now."},{"metadata":{"trusted":true},"cell_type":"code","source":"%matplotlib inline\n%config InlineBackend.figure_format = 'retina'\n\nimport matplotlib.pyplot as plt\n\nimport torch\nfrom torch import nn\nfrom torch import optim\nimport torch.nn.functional as F\nfrom torchvision import datasets, transforms, models","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Most of the pretrained models require the input to be 224x224 images. Also, we'll need to match the normalization used when the models were trained. Each color channel was normalized separately, the means are `[0.485, 0.456, 0.406]` and the standard deviations are `[0.229, 0.224, 0.225]`."},{"metadata":{"trusted":true},"cell_type":"code","source":"# data_dir = os.walk('/dev/shm/')\n\n# a,b,c = os.walk('/dev/shm/')\n# print(a)\n# print(b)\n# print(c)\n\n# TODO: Define transforms for the training data and testing data\ntrain_transforms = transforms.Compose([transforms.Resize(224),transforms.Normalize([0.485, 0.456, 0.406],\n                                                                                   [0.229, 0.224, 0.225]),\n                                      transforms.ToTensor()])\n\n# test_transforms =\n\n# Pass transforms in here, then run the next cell to see how the transforms look\ntrain_data = datasets.ImageFolder('/dev/shm/',transform = train_transforms)\n# test_data = datasets.ImageFolder(data_dir)\n\ntrainloader = torch.utils.data.DataLoader(train_data, batch_size=64, shuffle=True)\nprint(len(trainloader))\n# testloader = torch.utils.data.DataLoader(test_data, batch_size=64)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"We can load in a model such as [DenseNet](http://pytorch.org/docs/0.3.0/torchvision/models.html#id5). Let's print out the model architecture so we can see what's going on."},{"metadata":{"scrolled":true,"trusted":true},"cell_type":"code","source":"model = models.densenet121(pretrained=True)\nmodel","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"This model is built out of two main parts, the features and the classifier. The features part is a stack of convolutional layers and overall works as a feature detector that can be fed into a classifier. The classifier part is a single fully-connected layer `(classifier): Linear(in_features=1024, out_features=1000)`. This layer was trained on the ImageNet dataset, so it won't work for our specific problem. That means we need to replace the classifier, but the features will work perfectly on their own. In general, I think about pre-trained networks as amazingly good feature detectors that can be used as the input for simple feed-forward classifiers."},{"metadata":{"trusted":true},"cell_type":"code","source":"# Freeze parameters so we don't backprop through them\nfor param in model.parameters():\n    param.requires_grad = False\n\nfrom collections import OrderedDict\nclassifier = nn.Sequential(OrderedDict([\n                          ('fc1', nn.Linear(1024, 500)),\n                          ('relu', nn.ReLU()),\n                          ('fc2', nn.Linear(500, 2)),\n                          ('output', nn.LogSoftmax(dim=1))\n                          ]))\n    \nmodel.classifier = classifier","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"With our model built, we need to train the classifier. However, now we're using a **really deep** neural network. If you try to train this on a CPU like normal, it will take a long, long time. Instead, we're going to use the GPU to do the calculations. The linear algebra computations are done in parallel on the GPU leading to 100x increased training speeds. It's also possible to train on multiple GPUs, further decreasing training time.\n\nPyTorch, along with pretty much every other deep learning framework, uses [CUDA](https://developer.nvidia.com/cuda-zone) to efficiently compute the forward and backwards passes on the GPU. In PyTorch, you move your model parameters and other tensors to the GPU memory using `model.to('cuda')`. You can move them back from the GPU with `model.to('cpu')` which you'll commonly do when you need to operate on the network output outside of PyTorch. As a demonstration of the increased speed, I'll compare how long it takes to perform a forward and backward pass with and without a GPU."},{"metadata":{"trusted":true},"cell_type":"code","source":"import time","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"for device in [ 'cuda']:\n\n    criterion = nn.NLLLoss()\n    # Only train the classifier parameters, feature parameters are frozen\n    optimizer = optim.Adam(model.classifier.parameters(), lr=0.001)\n\n    model.to(device)\n\n    for ii, (inputs, labels) in enumerate(trainloader):\n\n        # Move input and label tensors to the GPU\n        inputs, labels = inputs.to(device), labels.to(device)\n\n        start = time.time()\n\n        outputs = model.forward(inputs)\n        loss = criterion(outputs, labels)\n        loss.backward()\n        optimizer.step()\n\n        if ii==3:\n            break\n        \n    print(f\"Device = {device}; Time per batch: {(time.time() - start)/3:.3f} seconds\")","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"You can write device agnostic code which will automatically use CUDA if it's enabled like so:\n```python\n# at beginning of the script\ndevice = torch.device(\"cuda:0\" if torch.cuda.is_available() else \"cpu\")\n\n...\n\n# then whenever you get a new Tensor or Module\n# this won't copy if they are already on the desired device\ninput = data.to(device)\nmodel = MyModule(...).to(device)\n```\n\nFrom here, I'll let you finish training the model. The process is the same as before except now your model is much more powerful. You should get better than 95% accuracy easily.\n\n>**Exercise:** Train a pretrained models to classify the cat and dog images. Continue with the DenseNet model, or try ResNet, it's also a good model to try out first. Make sure you are only training the classifier and the parameters for the features part are frozen."},{"metadata":{"trusted":false},"cell_type":"code","source":"## TODO: Use a pretrained model to classify the cat and dog images","execution_count":null,"outputs":[]},{"metadata":{"_cell_guid":"","_uuid":"","trusted":true},"cell_type":"code","source":"import pandas as pd\nsampleSubmission = pd.read_csv(\"../input/dogs-vs-cats/sampleSubmission.csv\")","execution_count":0,"outputs":[]}],"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"codemirror_mode":{"name":"ipython","version":3},"file_extension":".py","mimetype":"text/x-python","name":"python","nbconvert_exporter":"python","pygments_lexer":"ipython3","version":"3.7.4"}},"nbformat":4,"nbformat_minor":1}