Skip to content

Instantly share code, notes, and snippets.

@mlelarge
Created January 8, 2019 18:55
Show Gist options
  • Save mlelarge/1d7af848dc2be27ca3d3ea6bae9b775d to your computer and use it in GitHub Desktop.
Save mlelarge/1d7af848dc2be27ca3d3ea6bae9b775d to your computer and use it in GitHub Desktop.
01_intro_DLDIY_colab.ipynb
Display the source blob
Display the rendered blob
Raw
{
"nbformat": 4,
"nbformat_minor": 0,
"metadata": {
"colab": {
"name": "01_intro_DLDIY_colab.ipynb",
"version": "0.3.2",
"provenance": [],
"private_outputs": true,
"include_colab_link": true
},
"kernelspec": {
"display_name": "Python [default]",
"language": "python",
"name": "python3"
},
"accelerator": "GPU"
},
"cells": [
{
"cell_type": "markdown",
"metadata": {
"id": "view-in-github",
"colab_type": "text"
},
"source": [
"<a href=\"https://colab.research.google.com/gist/mlelarge/1d7af848dc2be27ca3d3ea6bae9b775d/01_intro_dldiy_colab.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
]
},
{
"metadata": {
"colab_type": "text",
"id": "-SvfKxAGCdhF"
},
"cell_type": "markdown",
"source": [
"# Using CNN for dogs vs cats"
]
},
{
"metadata": {
"colab_type": "text",
"id": "VI1VQlwECdhG"
},
"cell_type": "markdown",
"source": [
"We are going to create a model to enter the [Dogs vs Cats](https://www.kaggle.com/c/dogs-vs-cats-redux-kernels-edition) competition at Kaggle."
]
},
{
"metadata": {
"colab_type": "text",
"id": "dyhW08piCdhH"
},
"cell_type": "markdown",
"source": [
"There are 25,000 labelled dog and cat photos available for training, and 12,500 in the test set that we have to try to label for this competition. According to the Kaggle web-site, when this competition was launched (end of 2013): *\"**State of the art**: The current literature suggests machine classifiers can score above 80% accuracy on this task\"*. So if you can beat 80%, then you will be at the cutting edge as of 2013!"
]
},
{
"metadata": {
"colab_type": "text",
"id": "uFXJDuj3C01w"
},
"cell_type": "markdown",
"source": [
"## Colab preparation"
]
},
{
"metadata": {
"colab_type": "code",
"id": "NcRY9-oUCdhJ",
"colab": {}
},
"cell_type": "code",
"source": [
"# to install pytorch on colab\n",
"from os import path\n",
"from wheel.pep425tags import get_abbr_impl, get_impl_ver, get_abi_tag\n",
"platform = '{}{}-{}'.format(get_abbr_impl(), get_impl_ver(), get_abi_tag())\n",
"\n",
"accelerator = 'cu80' if path.exists('/opt/bin/nvidia-smi') else 'cpu'\n",
"\n",
"!pip install -q http://download.pytorch.org/whl/{accelerator}/torch-0.4.1-{platform}-linux_x86_64.whl torchvision"
],
"execution_count": 0,
"outputs": []
},
{
"metadata": {
"colab_type": "code",
"id": "edhumzlSDB5h",
"colab": {}
},
"cell_type": "code",
"source": [
"!pip install -U bcolz"
],
"execution_count": 0,
"outputs": []
},
{
"metadata": {
"colab_type": "code",
"id": "2Os2SV8vDEai",
"colab": {}
},
"cell_type": "code",
"source": [
"!pip install Pillow==4.0.0"
],
"execution_count": 0,
"outputs": []
},
{
"metadata": {
"colab_type": "text",
"id": "h4dAhx8-CdhM"
},
"cell_type": "markdown",
"source": [
"## Imports"
]
},
{
"metadata": {
"colab_type": "code",
"id": "6oU4Z_DPCdhM",
"colab": {}
},
"cell_type": "code",
"source": [
"from PIL import Image\n",
"import numpy as np\n",
"import matplotlib.pyplot as plt\n",
"import os\n",
"import torch\n",
"import torch.nn as nn\n",
"import torchvision\n",
"from torchvision import models,transforms,datasets\n",
"import bcolz\n",
"import time\n",
"%matplotlib inline"
],
"execution_count": 0,
"outputs": []
},
{
"metadata": {
"colab_type": "code",
"id": "A66_r51xCdhS",
"colab": {}
},
"cell_type": "code",
"source": [
"torch.__version__"
],
"execution_count": 0,
"outputs": []
},
{
"metadata": {
"colab_type": "code",
"id": "KN3FFTFhHQyi",
"colab": {}
},
"cell_type": "code",
"source": [
"import sys\n",
"sys.version"
],
"execution_count": 0,
"outputs": []
},
{
"metadata": {
"colab_type": "text",
"id": "tuej9DPjCdhX"
},
"cell_type": "markdown",
"source": [
"Check if GPU is available and if not change the [runtime](https://jovianlin.io/pytorch-with-gpu-in-google-colab/)."
]
},
{
"metadata": {
"colab_type": "code",
"id": "t56d0zbFCdhY",
"colab": {}
},
"cell_type": "code",
"source": [
"use_gpu = torch.cuda.is_available()\n",
"print('Using gpu: %s ' % use_gpu)\n",
"\n",
"def gpu(x,use_gpu=use_gpu):\n",
" if use_gpu:\n",
" return x.cuda()\n",
" else:\n",
" return x"
],
"execution_count": 0,
"outputs": []
},
{
"metadata": {
"colab_type": "text",
"id": "dDLlOjT5Et4p"
},
"cell_type": "markdown",
"source": [
"## Downloading the data"
]
},
{
"metadata": {
"colab_type": "text",
"id": "FSmB5oKYCdhc"
},
"cell_type": "markdown",
"source": [
"You can download the full dataset from Kaggle directly.\n",
"\n",
"Alternatively, Jeremy Howard provides a direct link to the catvsdogs [dataset](http://files.fast.ai/data/dogscats.zip). He's separated the cats and dogs into separate folders and created a validation folder as well. You'll need this folder structure to run VGG.\n",
"\n",
"For test purpose (or if you run on cpu), you should use the (small) sample directory."
]
},
{
"metadata": {
"colab_type": "code",
"id": "Rnn5pLK6EyJK",
"colab": {}
},
"cell_type": "code",
"source": [
"%mkdir data\n",
"%cd /content/data/\n",
"!wget http://files.fast.ai/data/dogscats.zip"
],
"execution_count": 0,
"outputs": []
},
{
"metadata": {
"colab_type": "code",
"id": "BTobJ9vTE37J",
"colab": {}
},
"cell_type": "code",
"source": [
"!unzip dogscats.zip"
],
"execution_count": 0,
"outputs": []
},
{
"metadata": {
"colab_type": "code",
"id": "XsMtmnCbCdhd",
"colab": {}
},
"cell_type": "code",
"source": [
"%ls"
],
"execution_count": 0,
"outputs": []
},
{
"metadata": {
"colab_type": "code",
"id": "S5OW01WzCdhu",
"colab": {}
},
"cell_type": "code",
"source": [
"%cd dogscats/\n",
"%ls"
],
"execution_count": 0,
"outputs": []
},
{
"metadata": {
"colab_type": "text",
"id": "Mkj3DZjpCdha"
},
"cell_type": "markdown",
"source": [
"## Data processing"
]
},
{
"metadata": {
"colab_type": "code",
"id": "iasXk_FKCdhy",
"colab": {}
},
"cell_type": "code",
"source": [
"%cd .."
],
"execution_count": 0,
"outputs": []
},
{
"metadata": {
"colab_type": "code",
"id": "MJRnJgGOCdh4",
"colab": {}
},
"cell_type": "code",
"source": [
"data_dir = '/content/data/dogscats'"
],
"execution_count": 0,
"outputs": []
},
{
"metadata": {
"colab_type": "text",
"id": "U3lE0cvyCdh8"
},
"cell_type": "markdown",
"source": [
"```datasets``` is a class of the ```torchvision``` package (see [torchvision.datasets](http://pytorch.org/docs/master/torchvision/datasets.html)) and deals with data loading. It integrates a multi-threaded loader that fetches images from the disk, groups them in mini-batches and serves them continously to the GPU right after each _forward_/_backward_ pass through the network.\n",
"\n",
"Images needs a bit of preparation before passing them throught the network. They need to have all the same size $224\\times 224 \\times 3$ plus some extra formatting done below by the normalize transform (explained later)."
]
},
{
"metadata": {
"colab_type": "code",
"id": "8t4vokNrF19p",
"colab": {}
},
"cell_type": "code",
"source": [
"normalize = transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])\n",
"\n",
"vgg_format = transforms.Compose([\n",
" transforms.CenterCrop(224),\n",
" transforms.ToTensor(),\n",
" normalize,\n",
" ])"
],
"execution_count": 0,
"outputs": []
},
{
"metadata": {
"colab_type": "code",
"id": "l8LMReVECdh-",
"colab": {}
},
"cell_type": "code",
"source": [
"dsets = {x: datasets.ImageFolder(os.path.join(data_dir, x), vgg_format)\n",
" for x in ['train', 'valid']}"
],
"execution_count": 0,
"outputs": []
},
{
"metadata": {
"colab_type": "code",
"id": "pMh7kjEBCdiC",
"colab": {}
},
"cell_type": "code",
"source": [
"os.path.join(data_dir,'train')"
],
"execution_count": 0,
"outputs": []
},
{
"metadata": {
"colab_type": "text",
"id": "VNyS0TyeKwdO"
},
"cell_type": "markdown",
"source": [
"Interactive help on jupyter notebook thanks to `?`"
]
},
{
"metadata": {
"colab_type": "code",
"id": "WX5pkMX4CdiF",
"colab": {}
},
"cell_type": "code",
"source": [
"?datasets.ImageFolder"
],
"execution_count": 0,
"outputs": []
},
{
"metadata": {
"colab_type": "text",
"id": "oYmIGNEjKwdR"
},
"cell_type": "markdown",
"source": [
"We see that `datasets.ImageFolder` has attributes: classes, class_to_idx, imgs.\n",
"\n",
"Let see what they are?"
]
},
{
"metadata": {
"colab_type": "code",
"id": "m9ifn_R7CdiH",
"colab": {}
},
"cell_type": "code",
"source": [
"dsets['train'].classes"
],
"execution_count": 0,
"outputs": []
},
{
"metadata": {
"colab_type": "code",
"id": "TB6sTwFuCdiK",
"colab": {}
},
"cell_type": "code",
"source": [
"dsets['train'].class_to_idx"
],
"execution_count": 0,
"outputs": []
},
{
"metadata": {
"colab_type": "code",
"id": "y9ECrD2ACdiO",
"colab": {}
},
"cell_type": "code",
"source": [
"dsets['train'].imgs[:5]"
],
"execution_count": 0,
"outputs": []
},
{
"metadata": {
"colab_type": "code",
"id": "WefhjZb2CdiQ",
"colab": {}
},
"cell_type": "code",
"source": [
"dset_sizes = {x: len(dsets[x]) for x in ['train', 'valid']}\n",
"dset_sizes"
],
"execution_count": 0,
"outputs": []
},
{
"metadata": {
"colab_type": "code",
"id": "SCLV1YgaCdiT",
"colab": {}
},
"cell_type": "code",
"source": [
"dset_classes = dsets['train'].classes"
],
"execution_count": 0,
"outputs": []
},
{
"metadata": {
"colab_type": "text",
"id": "Zy52-XhACdiX"
},
"cell_type": "markdown",
"source": [
"The ```torchvision``` packages allows complex pre-processing/transforms of the input data (_e.g._ normalization, cropping, flipping, jittering). A sequence of transforms can be grouped in a pipeline with the help of the ```torchvision.transforms.Compose``` function, see [torchvision.transforms](http://pytorch.org/docs/master/torchvision/transforms.html)"
]
},
{
"metadata": {
"colab_type": "text",
"id": "iphL57PhKwdh"
},
"cell_type": "markdown",
"source": [
"The magic help `?` allows you to retrieve function you defined and forgot!"
]
},
{
"metadata": {
"colab_type": "code",
"id": "X_ARYwraCdiY",
"colab": {}
},
"cell_type": "code",
"source": [
"?vgg_format"
],
"execution_count": 0,
"outputs": []
},
{
"metadata": {
"colab_type": "code",
"id": "tWnJQiWgGP_R",
"colab": {}
},
"cell_type": "code",
"source": [
"def shuffle_valtrain(x):\n",
" if x == 'train':\n",
" return True\n",
" else:\n",
" return False"
],
"execution_count": 0,
"outputs": []
},
{
"metadata": {
"colab_type": "code",
"id": "8KQj0Zm3Cdic",
"colab": {}
},
"cell_type": "code",
"source": [
"dset_loaders = {x: torch.utils.data.DataLoader(dsets[x], batch_size=64,\n",
" shuffle=shuffle_valtrain(x), num_workers=6)\n",
" for x in ['train', 'valid']}"
],
"execution_count": 0,
"outputs": []
},
{
"metadata": {
"colab_type": "code",
"id": "Iern_6GNCdie",
"colab": {}
},
"cell_type": "code",
"source": [
"?torch.utils.data.DataLoader"
],
"execution_count": 0,
"outputs": []
},
{
"metadata": {
"colab_type": "code",
"id": "wN1BKHfDCdig",
"colab": {}
},
"cell_type": "code",
"source": [
"dataset_valid = torch.utils.data.DataLoader(dsets['valid'], batch_size=5, shuffle=True, num_workers=6)"
],
"execution_count": 0,
"outputs": []
},
{
"metadata": {
"colab_type": "code",
"id": "Z4Be7lSLCdik",
"colab": {}
},
"cell_type": "code",
"source": [
"count = 1\n",
"for data in dataset_valid:\n",
" print(count, end=',')\n",
" if count == 1:\n",
" inputs_try,labels_try = data\n",
" count +=1"
],
"execution_count": 0,
"outputs": []
},
{
"metadata": {
"colab_type": "code",
"id": "3BvxQqfzCdiq",
"colab": {}
},
"cell_type": "code",
"source": [
"labels_try"
],
"execution_count": 0,
"outputs": []
},
{
"metadata": {
"colab_type": "code",
"id": "MLNsfqc8Cdis",
"colab": {}
},
"cell_type": "code",
"source": [
"inputs_try.shape"
],
"execution_count": 0,
"outputs": []
},
{
"metadata": {
"colab_type": "text",
"id": "vsaL21ouKwd9"
},
"cell_type": "markdown",
"source": [
"A small function to display images:"
]
},
{
"metadata": {
"colab_type": "code",
"id": "346yl-gbcLLm",
"colab": {}
},
"cell_type": "code",
"source": [
"def imshow(inp, title=None):\n",
"# Imshow for Tensor.\n",
" inp = inp.numpy().transpose((1, 2, 0))\n",
" mean = np.array([0.485, 0.456, 0.406])\n",
" std = np.array([0.229, 0.224, 0.225])\n",
" inp = np.clip(std * inp + mean, 0,1)\n",
" plt.imshow(inp)\n",
" if title is not None:\n",
" plt.title(title)\n",
" plt.pause(0.001) # pause a bit so that plots are updated"
],
"execution_count": 0,
"outputs": []
},
{
"metadata": {
"colab_type": "code",
"id": "IJbW-QzGCdiv",
"colab": {}
},
"cell_type": "code",
"source": [
"# Make a grid from batch\n",
"out = torchvision.utils.make_grid(inputs_try)\n",
"\n",
"imshow(out, title=[dset_classes[x] for x in labels_try])"
],
"execution_count": 0,
"outputs": []
},
{
"metadata": {
"colab_type": "text",
"id": "8ZK7nRSWKweH"
},
"cell_type": "markdown",
"source": [
"What is an image for your computer?"
]
},
{
"metadata": {
"colab_type": "code",
"id": "hrzxYMXXCdix",
"colab": {}
},
"cell_type": "code",
"source": [
"inputs_try"
],
"execution_count": 0,
"outputs": []
},
{
"metadata": {
"colab_type": "code",
"id": "2HvFNWJICdiz",
"colab": {}
},
"cell_type": "code",
"source": [
"# Get a batch of training data\n",
"inputs, classes = next(iter(dset_loaders['train']))\n",
"\n",
"n_images = 8\n",
"\n",
"# Make a grid from batch\n",
"out = torchvision.utils.make_grid(inputs[0:n_images])\n",
"\n",
"imshow(out, title=[dset_classes[x] for x in classes[0:n_images]])"
],
"execution_count": 0,
"outputs": []
},
{
"metadata": {
"colab_type": "code",
"id": "iUrTGlTpCdi5",
"colab": {}
},
"cell_type": "code",
"source": [
"# Get a batch of validation data\n",
"inputs, classes = next(iter(dset_loaders['valid']))\n",
"\n",
"n_images = 8\n",
"\n",
"# Make a grid from batch\n",
"out = torchvision.utils.make_grid(inputs[0:n_images])\n",
"\n",
"imshow(out, title=[dset_classes[x] for x in classes[0:n_images]])"
],
"execution_count": 0,
"outputs": []
},
{
"metadata": {
"colab_type": "text",
"id": "LOvkYiROCdi7"
},
"cell_type": "markdown",
"source": [
"## Creating VGG Model"
]
},
{
"metadata": {
"colab_type": "text",
"id": "BO5LAG4bCdi7"
},
"cell_type": "markdown",
"source": [
"The torchvision module comes with a zoo of popular CNN architectures which are already trained on [ImageNet](http://www.image-net.org/) (1.2M training images). When called the first time, if ```pretrained=True``` the model is fetched over the internet and downloaded to ```~/.torch/models```.\n",
"For next calls, the model will be directly read from there."
]
},
{
"metadata": {
"colab_type": "code",
"id": "K9PsHjXgCdi9",
"colab": {}
},
"cell_type": "code",
"source": [
"model_vgg = models.vgg16(pretrained=True)"
],
"execution_count": 0,
"outputs": []
},
{
"metadata": {
"colab_type": "text",
"id": "VBzGe2mlCdi-"
},
"cell_type": "markdown",
"source": [
"We will first use VGG Model without any modification. In order to interpret the results, we need to import the 1000 ImageNet categories, available at: [https://s3.amazonaws.com/deep-learning-models/image-models/imagenet_class_index.json](https://s3.amazonaws.com/deep-learning-models/image-models/imagenet_class_index.json)"
]
},
{
"metadata": {
"colab_type": "code",
"id": "qhvs0ki_Cdi_",
"colab": {}
},
"cell_type": "code",
"source": [
"!wget https://s3.amazonaws.com/deep-learning-models/image-models/imagenet_class_index.json"
],
"execution_count": 0,
"outputs": []
},
{
"metadata": {
"colab_type": "code",
"id": "Hppljqo5CdjC",
"colab": {}
},
"cell_type": "code",
"source": [
"import json\n",
"\n",
"fpath = '/content/data/imagenet_class_index.json'\n",
"\n",
"with open(fpath) as f:\n",
" class_dict = json.load(f)\n",
"dic_imagenet = [class_dict[str(i)][1] for i in range(len(class_dict))]"
],
"execution_count": 0,
"outputs": []
},
{
"metadata": {
"colab_type": "code",
"id": "QATvAFILCdjF",
"colab": {}
},
"cell_type": "code",
"source": [
"dic_imagenet[:4]"
],
"execution_count": 0,
"outputs": []
},
{
"metadata": {
"colab_type": "code",
"id": "p6QQhwruCdjI",
"colab": {}
},
"cell_type": "code",
"source": [
"inputs_try , labels_try = gpu(inputs_try),gpu(labels_try)\n",
"\n",
"model_vgg = gpu(model_vgg)"
],
"execution_count": 0,
"outputs": []
},
{
"metadata": {
"colab_type": "code",
"id": "epMB0UF9CdjM",
"colab": {}
},
"cell_type": "code",
"source": [
"outputs_try = model_vgg(inputs_try)"
],
"execution_count": 0,
"outputs": []
},
{
"metadata": {
"colab_type": "code",
"id": "dOlx7YcPCdjO",
"colab": {}
},
"cell_type": "code",
"source": [
"outputs_try"
],
"execution_count": 0,
"outputs": []
},
{
"metadata": {
"colab_type": "code",
"id": "MCIxHN2QCdjT",
"colab": {}
},
"cell_type": "code",
"source": [
"m_softm = nn.Softmax(dim=1)\n",
"vals_try,preds_try = torch.max(m_softm(outputs_try.data),1)"
],
"execution_count": 0,
"outputs": []
},
{
"metadata": {
"colab_type": "code",
"id": "CvGbb2bQCdjZ",
"colab": {}
},
"cell_type": "code",
"source": [
"vals_try"
],
"execution_count": 0,
"outputs": []
},
{
"metadata": {
"colab_type": "code",
"id": "0TUdNKCJCdjc",
"colab": {}
},
"cell_type": "code",
"source": [
"print([dic_imagenet[i] for i in preds_try.data])"
],
"execution_count": 0,
"outputs": []
},
{
"metadata": {
"colab_type": "code",
"id": "jtzuHob9Cdjf",
"colab": {}
},
"cell_type": "code",
"source": [
"out = torchvision.utils.make_grid(inputs_try.data.cpu())\n",
"\n",
"imshow(out, title=[dset_classes[x] for x in labels_try.data.cpu()])"
],
"execution_count": 0,
"outputs": []
},
{
"metadata": {
"colab_type": "text",
"id": "f3Bktt5PCdjh"
},
"cell_type": "markdown",
"source": [
"### Modifying the last layer and setting the gradient false to all layers"
]
},
{
"metadata": {
"colab_type": "code",
"collapsed": true,
"id": "L8kr3-tjCdji",
"colab": {}
},
"cell_type": "code",
"source": [
"print(model_vgg)"
],
"execution_count": 0,
"outputs": []
},
{
"metadata": {
"colab_type": "text",
"id": "IXoMW73MCdjl"
},
"cell_type": "markdown",
"source": [
"We'll learn about what these different blocks do later in the course. For now, it's enough to know that:\n",
"\n",
"- Convolution layers are for finding small to medium size patterns in images -- analyzing the images locally\n",
"- Dense (fully connected) layers are for combining patterns across an image -- analyzing the images globally\n",
"- Pooling layers downsample -- in order to reduce image size and to improve invariance of learned features"
]
},
{
"metadata": {
"colab_type": "text",
"id": "hA2f5FRuCdjm"
},
"cell_type": "markdown",
"source": [
"![vgg16](https://mlelarge.github.io/dataflowr/Notebooks/vgg16.png)"
]
},
{
"metadata": {
"colab_type": "text",
"id": "SK6lfAzfCdjn"
},
"cell_type": "markdown",
"source": [
"In this practical example, our goal is to use the already trained model and just change the number of output classes. To this end we replace the last ```nn.Linear``` layer trained for 1000 classes to ones with 2 classes. In order to freeze the weights of the other layers during training, we set the field ```required_grad=False```. In this manner no gradient will be computed for them during backprop and hence no update in the weights. Only the weights for the 2 class layer will be updated."
]
},
{
"metadata": {
"colab_type": "code",
"collapsed": true,
"id": "rQwRKKC-Cdjo",
"colab": {}
},
"cell_type": "code",
"source": [
"for param in model_vgg.parameters():\n",
" param.requires_grad = False\n",
"model_vgg.classifier._modules['6'] = nn.Linear(4096, 2)\n",
"model_vgg.classifier._modules['7'] = torch.nn.LogSoftmax(dim = 1)"
],
"execution_count": 0,
"outputs": []
},
{
"metadata": {
"colab_type": "text",
"id": "qAr5tj2NKwfF"
},
"cell_type": "markdown",
"source": [
"PyTorch documentation for [LogSoftmax](https://pytorch.org/docs/stable/nn.html#logsoftmax)"
]
},
{
"metadata": {
"colab_type": "code",
"collapsed": true,
"id": "jJ3OenJpCdjp",
"colab": {}
},
"cell_type": "code",
"source": [
"print(model_vgg.classifier)"
],
"execution_count": 0,
"outputs": []
},
{
"metadata": {
"colab_type": "code",
"collapsed": true,
"id": "9ITZFX2MCdju",
"colab": {}
},
"cell_type": "code",
"source": [
"model_vgg = gpu(model_vgg)"
],
"execution_count": 0,
"outputs": []
},
{
"metadata": {
"colab_type": "text",
"id": "hMAwUx7QCdjv"
},
"cell_type": "markdown",
"source": [
"### Calculating preconvoluted features"
]
},
{
"metadata": {
"colab_type": "code",
"collapsed": true,
"id": "iWZ0BguiCdjw",
"colab": {}
},
"cell_type": "code",
"source": [
"def preconvfeat(dataset):\n",
" conv_features = []\n",
" labels_list = []\n",
" for data in dataset:\n",
" inputs,labels = data\n",
" inputs = gpu(inputs)\n",
" labels = gpu(labels)\n",
" # if you find code like below on internet (or in this course!):\n",
" # Variable is a PyTorch v0.3 recollection...\n",
" # it should still run with newer versions of PyTorch\n",
" #if use_gpu:\n",
" # inputs , labels = Variable(inputs.cuda()),Variable(labels.cuda())\n",
" #else:\n",
" # inputs , labels = Variable(inputs),Variable(labels)\n",
" \n",
" x = model_vgg.features(inputs)\n",
" conv_features.extend(x.data.cpu().numpy())\n",
" labels_list.extend(labels.data.cpu().numpy())\n",
" conv_features = np.concatenate([[feat] for feat in conv_features])\n",
" return (conv_features,labels_list)"
],
"execution_count": 0,
"outputs": []
},
{
"metadata": {
"colab_type": "code",
"collapsed": true,
"id": "UHxk_fBaCdjx",
"colab": {}
},
"cell_type": "code",
"source": [
"x_try = model_vgg.features(inputs_try)"
],
"execution_count": 0,
"outputs": []
},
{
"metadata": {
"colab_type": "code",
"collapsed": true,
"id": "4_XDasbkCdj0",
"colab": {}
},
"cell_type": "code",
"source": [
"?x_try"
],
"execution_count": 0,
"outputs": []
},
{
"metadata": {
"colab_type": "code",
"collapsed": true,
"id": "XoKGJ-4iCdj2",
"colab": {}
},
"cell_type": "code",
"source": [
"x_try.data.shape"
],
"execution_count": 0,
"outputs": []
},
{
"metadata": {
"colab_type": "code",
"collapsed": true,
"id": "KX0SqD0CCdj4",
"colab": {}
},
"cell_type": "code",
"source": [
"7*7*512"
],
"execution_count": 0,
"outputs": []
},
{
"metadata": {
"colab_type": "code",
"collapsed": true,
"id": "pbAyXnwgCdj6",
"colab": {}
},
"cell_type": "code",
"source": [
"labels_try"
],
"execution_count": 0,
"outputs": []
},
{
"metadata": {
"colab_type": "code",
"collapsed": true,
"id": "bs_NwTKcCdj8",
"colab": {}
},
"cell_type": "code",
"source": [
"labels_try.data"
],
"execution_count": 0,
"outputs": []
},
{
"metadata": {
"colab_type": "code",
"collapsed": true,
"id": "AHYRm_z8Cdj-",
"colab": {}
},
"cell_type": "code",
"source": [
"%%time\n",
"conv_feat_train,labels_train = preconvfeat(dset_loaders['train'])"
],
"execution_count": 0,
"outputs": []
},
{
"metadata": {
"colab_type": "code",
"collapsed": true,
"id": "lNAc7zX9CdkB",
"colab": {}
},
"cell_type": "code",
"source": [
"%%time\n",
"conv_feat_val,labels_val = preconvfeat(dset_loaders['valid'])"
],
"execution_count": 0,
"outputs": []
},
{
"metadata": {
"colab_type": "code",
"collapsed": true,
"id": "3-APvzkACdkD",
"colab": {}
},
"cell_type": "code",
"source": [
"def save_array(fname, arr):\n",
" c=bcolz.carray(arr, rootdir=fname, mode='w')\n",
" c.flush()\n",
"def load_array(fname):\n",
" return bcolz.open(fname)[:]\n",
"\n",
"\n",
"%mkdir /content/data/dogscats/vgg16\n"
],
"execution_count": 0,
"outputs": []
},
{
"metadata": {
"colab_type": "code",
"collapsed": true,
"id": "AWadFbvtCdkF",
"colab": {}
},
"cell_type": "code",
"source": [
"save_array(os.path.join(data_dir,'vgg16','feat_train.bc'),conv_feat_train)\n",
"save_array(os.path.join(data_dir,'vgg16','labels_train.bc'),labels_train)\n",
"save_array(os.path.join(data_dir,'vgg16','feat_val.bc'),conv_feat_val)\n",
"save_array(os.path.join(data_dir,'vgg16','labels_val.bc'),labels_val)"
],
"execution_count": 0,
"outputs": []
},
{
"metadata": {
"colab_type": "text",
"id": "pyjlrH4wCdkH"
},
"cell_type": "markdown",
"source": [
"### Uploading Precomputed features\n",
"\n",
"This section will allow you to store the precomputed features on your Google drive for later use."
]
},
{
"metadata": {
"colab_type": "code",
"collapsed": true,
"id": "27gRV8KiJw6H",
"colab": {}
},
"cell_type": "code",
"source": [
"%cd /content/data/dogscats/\n",
"!zip -r vgg16 vgg16/*"
],
"execution_count": 0,
"outputs": []
},
{
"metadata": {
"colab_type": "code",
"collapsed": true,
"id": "de4y59inJx_p",
"colab": {}
},
"cell_type": "code",
"source": [
"!pip install -U -q PyDrive\n",
"\n",
"from pydrive.auth import GoogleAuth\n",
"from pydrive.drive import GoogleDrive\n",
"from google.colab import auth\n",
"from oauth2client.client import GoogleCredentials\n",
"\n",
"# 1. Authenticate and create the PyDrive client.\n",
"auth.authenticate_user()\n",
"gauth = GoogleAuth()\n",
"gauth.credentials = GoogleCredentials.get_application_default()\n",
"drive = GoogleDrive(gauth)"
],
"execution_count": 0,
"outputs": []
},
{
"metadata": {
"colab_type": "code",
"collapsed": true,
"id": "JIaZyCpcJ1Hd",
"colab": {}
},
"cell_type": "code",
"source": [
"upload = drive.CreateFile({'title': 'vgg16_drive.zip'})\n",
"upload.SetContentFile('vgg16.zip')\n",
"upload.Upload()\n",
"print('Uploaded file with ID {}'.format(upload.get('id')))"
],
"execution_count": 0,
"outputs": []
},
{
"metadata": {
"colab_type": "code",
"collapsed": true,
"id": "rCxGfgBHCdkJ",
"colab": {}
},
"cell_type": "code",
"source": [
"conv_feat_train.shape"
],
"execution_count": 0,
"outputs": []
},
{
"metadata": {
"colab_type": "text",
"id": "fU9vWWT2CdkN"
},
"cell_type": "markdown",
"source": [
"## Training fully connected module"
]
},
{
"metadata": {
"colab_type": "text",
"id": "qqp2u3IXCdkO"
},
"cell_type": "markdown",
"source": [
"### Creating loss function and optimizer\n",
"\n",
"PyTorch documentation for [NLLLoss](https://pytorch.org/docs/stable/nn.html#nllloss) and the [torch.optim module](https://pytorch.org/docs/stable/optim.html#module-torch.optim)"
]
},
{
"metadata": {
"colab_type": "code",
"collapsed": true,
"id": "oP1F4yb8CdkO",
"colab": {}
},
"cell_type": "code",
"source": [
"criterion = nn.NLLLoss()\n",
"lr = 0.01\n",
"optimizer_vgg = torch.optim.SGD(model_vgg.classifier[6].parameters(),lr = lr)"
],
"execution_count": 0,
"outputs": []
},
{
"metadata": {
"colab_type": "text",
"id": "NUSxP3BZCdkP"
},
"cell_type": "markdown",
"source": [
"### Creating Data generator"
]
},
{
"metadata": {
"colab_type": "code",
"collapsed": true,
"id": "KQxZBVOGCdkQ",
"colab": {}
},
"cell_type": "code",
"source": [
"def data_gen(conv_feat,labels,batch_size=64,shuffle=True):\n",
" labels = np.array(labels)\n",
" if shuffle:\n",
" index = np.random.permutation(len(conv_feat))\n",
" conv_feat = conv_feat[index]\n",
" labels = labels[index]\n",
" for idx in range(0,len(conv_feat),batch_size):\n",
" yield(conv_feat[idx:idx+batch_size],labels[idx:idx+batch_size])"
],
"execution_count": 0,
"outputs": []
},
{
"metadata": {
"colab_type": "text",
"id": "tenuLj67CdkS"
},
"cell_type": "markdown",
"source": [
"### Training the model"
]
},
{
"metadata": {
"colab_type": "code",
"collapsed": true,
"id": "7nNAUibjCdkS",
"colab": {}
},
"cell_type": "code",
"source": [
"def train_model(model,size,conv_feat=None,labels=None,epochs=1,optimizer=None,train=True,shuffle=True):\n",
" if train:\n",
" model.train()\n",
" else:\n",
" model.eval()\n",
" \n",
" for epoch in range(epochs):\n",
" batches = data_gen(conv_feat=conv_feat,labels=labels,shuffle=shuffle)\n",
" total = 0\n",
" running_loss = 0.0\n",
" running_corrects = 0\n",
" for inputs,classes in batches:\n",
" inputs , classes = gpu(torch.from_numpy(inputs)), gpu(torch.from_numpy(classes))\n",
" \n",
" inputs = inputs.view(inputs.size(0), -1)\n",
" outputs = model(inputs)\n",
" loss = criterion(outputs,classes) \n",
" if train:\n",
" if optimizer is None:\n",
" raise ValueError('Pass optimizer for train mode')\n",
" optimizer = optimizer\n",
" optimizer.zero_grad()\n",
" loss.backward()\n",
" optimizer.step()\n",
" _,preds = torch.max(outputs.data,1)\n",
" # statistics\n",
" running_loss += loss.data.item()\n",
" running_corrects += torch.sum(preds == classes.data)\n",
" epoch_loss = running_loss / size\n",
" epoch_acc = running_corrects.data.item() / size\n",
" print('Loss: {:.4f} Acc: {:.4f}'.format(\n",
" epoch_loss, epoch_acc))\n",
" "
],
"execution_count": 0,
"outputs": []
},
{
"metadata": {
"colab_type": "code",
"collapsed": true,
"id": "_Jts2jK1CdkV",
"scrolled": false,
"colab": {}
},
"cell_type": "code",
"source": [
"%%time\n",
"(train_model(model=gpu(model_vgg.classifier),size=dset_sizes['train'],conv_feat=conv_feat_train,labels=labels_train,\n",
" epochs=10,optimizer=optimizer_vgg,train=True,shuffle=True))"
],
"execution_count": 0,
"outputs": []
},
{
"metadata": {
"colab_type": "code",
"collapsed": true,
"id": "y3JjYayKCdkW",
"colab": {}
},
"cell_type": "code",
"source": [
"train_model(conv_feat=conv_feat_val,labels=labels_val,model=gpu(model_vgg.classifier)\n",
" ,size=dset_sizes['valid'],train=False,shuffle=False)"
],
"execution_count": 0,
"outputs": []
},
{
"metadata": {
"colab_type": "code",
"collapsed": true,
"id": "Cn6cIwZNCdkY",
"colab": {}
},
"cell_type": "code",
"source": [
"# Get a batch of training data\n",
"inputs, classes = next(iter(dset_loaders['valid']))\n",
"\n",
"out = torchvision.utils.make_grid(inputs[0:n_images])\n",
"\n",
"imshow(out, title=[dset_classes[x] for x in classes[0:n_images]])"
],
"execution_count": 0,
"outputs": []
},
{
"metadata": {
"colab_type": "code",
"collapsed": true,
"id": "Ghkbm7ByCdke",
"colab": {}
},
"cell_type": "code",
"source": [
"inputs = torch.from_numpy(conv_feat_val[:n_images])\n",
"inputs = inputs.view(inputs.size(0), -1)\n",
"if use_gpu:\n",
" outputs = model_vgg.classifier(inputs.cuda())\n",
"else:\n",
" outputs = model_vgg.classifier(inputs)\n",
"print(torch.exp(outputs))"
],
"execution_count": 0,
"outputs": []
},
{
"metadata": {
"colab_type": "code",
"collapsed": true,
"id": "F1qdUtvjCdkg",
"colab": {}
},
"cell_type": "code",
"source": [
"labels_val[:n_images]"
],
"execution_count": 0,
"outputs": []
},
{
"metadata": {
"colab_type": "code",
"collapsed": true,
"id": "Fl5_aK0uOjSG",
"colab": {}
},
"cell_type": "code",
"source": [
""
],
"execution_count": 0,
"outputs": []
}
]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment