{"metadata": {"kernelspec": {"display_name": "Python 3", "name": "python3", "language": "python"}, "language_info": {"pygments_lexer": "ipython3", "name": "python", "nbconvert_exporter": "python", "mimetype": "text/x-python", "version": "3.6.1", "codemirror_mode": {"name": "ipython", "version": 3}, "file_extension": ".py"}}, "cells": [{"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", "\n", "import numpy as np # linear algebra\n", "import pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n", "import io\n", "\n", "import bson                       # this is installed with the pymongo package\n", "from skimage.data import imread   # or, whatever image library you prefer\n", "import multiprocessing as mp      # will come in handy due to the size of the data\n", "import time\n", "import datetime as dt\n", "\n", "import cv2\n", "import matplotlib.pyplot as plt\n", "from tqdm import tqdm_notebook\n", "import concurrent.futures\n", "from multiprocessing import cpu_count\n", "\n", "\n", "from keras.optimizers import SGD\n", "from keras import layers\n", "from keras.layers import Input, Dense, Conv2D, MaxPooling2D, AveragePooling2D, ZeroPadding2D, Dropout, Flatten, merge, Reshape, Activation\n", "from keras.layers import GlobalAveragePooling2D\n", "from keras.layers.normalization import BatchNormalization\n", "from keras.models import Model\n", "from keras.preprocessing.image import ImageDataGenerator, array_to_img, img_to_array, load_img\n", "from keras import backend as K\n", "from keras.utils.data_utils import get_file\n", "\n", "from sklearn.metrics import log_loss\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", "\n", "from subprocess import check_output\n", "print(check_output([\"ls\", \"../input\"]).decode(\"utf8\"))\n", "\n", "# Any results you write to the current directory are saved as output."], "outputs": [], "execution_count": null, "metadata": {"_uuid": "c9bab02b7c08fa7bbab705a5c6cfd1643db2032f", "_cell_guid": "b34e5738-2f83-49e5-9f2e-4a1c02b174d8"}, "cell_type": "code"}, {"source": ["INPUT_PATH  = '../input/'\n", "train_data_dir      = '../output/train'\n", "validation_data_dir = '../output/validation'\n", "\n", "WEIGHTS_PATH = 'https://github.com/fchollet/deep-learning-models/releases/download/v0.5/inception_v3_weights_tf_dim_ordering_tf_kernels.h5'\n", "WEIGHTS_PATH_NO_TOP = 'https://github.com/fchollet/deep-learning-models/releases/download/v0.5/inception_v3_weights_tf_dim_ordering_tf_kernels_notop.h5'\n", "\n", "\n", "img_width  = 128\n", "img_height = 128\n", "batch_size = 300"], "outputs": [], "execution_count": null, "metadata": {"collapsed": true}, "cell_type": "code"}, {"source": ["Classification of images has reached a quite mature state and several models have been trained with high accuracy. I want to remain working in the Keras environment for as long as possible because of its easy of use. \n", "\n", "Keras has several deep models like VGG16, VGG19, GoogLeNet, Inception-V3, and ResNet50 among others. \n", "\n", "This kernel makes use of Inception-V3 a truly deep model with 27 layers that only uses 96 MB to store the model weights in memory  compared to VGG16's 574 MB.\n", "\n", "Within the Keras framework, one can modify the last stages of the models to suit the task in hand; in our case we need to  extend the number of classes from 1000 to 5270.\n", "\n", "Once the model is defined, one can load pre-trained weights (ImageNet) and resume training on a new data set. One can also turn off any number of consecutive layers starting from the input layer. The idea is to benefit from expert training and beeing able to train the Cdiscount data in reasonable time.\n", "\n", "The fitting of models in Keras can use python generators reading training and validation samples stored in folders that have the structure:\n", "\n", "../output/train/[category]/[_id]-[index].jpg\n", "\n", "../output/validation/[category]/[_id]-[index].jpg\n", "\n", "You can see the kernel writen by Bruno do Amaral that I modified slightly to write train and validation folders:\n", "\n", "https://www.kaggle.com/rdebbe/prepare-train-and-validation-data-for-keras-models\n", "\n", "The output of the generators are batches of tuples (data, label) "], "metadata": {}, "cell_type": "markdown"}, {"source": ["# the generators do the reading of input files\n", "# If you want to use image augmentation use this configuration. For more choices and details\n", "# consult the Keras manual: https://keras.io/preprocessing/image/\n", "\n", "train_datagen = ImageDataGenerator(\n", "        rescale=1./255,\n", "        shear_range=0.2,\n", "        zoom_range=0.2,\n", "        horizontal_flip=True)\n", "\n", "# only rescaling\n", "test_datagen = ImageDataGenerator(rescale=1./255)\n", "print('Time right now: ', dt.datetime.now())\n", "start = time.time()\n", "\n", "# As we get familiar with this project, we forgo image augmentation, \n", "# we will later set shuffle of the samples to true as the optimizer of the fit is SGD\n", "\n", "train_generator = test_datagen.flow_from_directory(\n", "    train_data_dir,\n", "    target_size=(img_width, img_height),\n", "    batch_size=batch_size,\n", "    class_mode=\"categorical\",\n", "    shuffle=False)\n", "end = time.time()\n", "print('Time right now: ', dt.datetime.now())\n", "print('It took ', end-start, ' seconds to prepare train gen')\n", "start = time.time()\n", "validation_generator = test_datagen.flow_from_directory(\n", "    validation_data_dir,\n", "    target_size=(img_width, img_height),\n", "    batch_size=batch_size,\n", "    class_mode=\"categorical\",\n", "    shuffle=False)\n", "\n", "end = time.time()\n", "\n", "print('It took ', end-start, ' seconds to prepare valid gen')"], "outputs": [], "execution_count": null, "metadata": {"_kg_hide-output": true}, "cell_type": "code"}, {"source": ["img_rows = 128\n", "img_cols = 128\n", "num_classes = 5270\n", "channel = 3\n", "#from https://github.com/fchollet/deep-learning-models/blob/master/inception_v3.py\n", "def conv2d_bn(x,\n", "              filters,\n", "              num_row,\n", "              num_col,\n", "              padding='same',\n", "              strides=(1, 1),\n", "              name=None):\n", "    \"\"\"Utility function to apply conv + BN.\n", "    Arguments:\n", "        x: input tensor.\n", "        filters: filters in `Conv2D`.\n", "        num_row: height of the convolution kernel.\n", "        num_col: width of the convolution kernel.\n", "        padding: padding mode in `Conv2D`.\n", "        strides: strides in `Conv2D`.\n", "        name: name of the ops; will become `name + '_conv'`\n", "            for the convolution and `name + '_bn'` for the\n", "            batch norm layer.\n", "    Returns:\n", "        Output tensor after applying `Conv2D` and `BatchNormalization`.\n", "    \"\"\"\n", "    if name is not None:\n", "        bn_name = name + '_bn'\n", "        conv_name = name + '_conv'\n", "    else:\n", "        bn_name = None\n", "        conv_name = None\n", "    if K.image_data_format() == 'channels_first':\n", "        bn_axis = 1\n", "    else:\n", "        bn_axis = 3\n", "    x = Conv2D(\n", "        filters, (num_row, num_col),\n", "        strides=strides,\n", "        padding=padding,\n", "        use_bias=False,\n", "        name=conv_name)(x)\n", "    x = BatchNormalization(axis=bn_axis, scale=False, name=bn_name)(x)\n", "    x = Activation('relu', name=name)(x)\n", "    return x\n", "\n", "\n", "def InceptionV3(include_top=True,\n", "                weights='imagenet',\n", "                input_tensor=None,\n", "                input_shape=None,\n", "                pooling=None,\n", "                classes=1000):\n", "    \"\"\"Instantiates the Inception v3 architecture.\n", "    Optionally loads weights pre-trained\n", "    on ImageNet. Note that when using TensorFlow,\n", "    for best performance you should set\n", "    `image_data_format=\"channels_last\"` in your Keras config\n", "    at ~/.keras/keras.json.\n", "    The model and the weights are compatible with both\n", "    TensorFlow and Theano. The data format\n", "    convention used by the model is the one\n", "    specified in your Keras config file.\n", "    Note that the default input image size for this model is 299x299.\n", "    Arguments:\n", "        include_top: whether to include the fully-connected\n", "            layer at the top of the network.\n", "        weights: one of `None` (random initialization)\n", "            or \"imagenet\" (pre-training on ImageNet).\n", "        input_tensor: optional Keras tensor (i.e. output of `layers.Input()`)\n", "            to use as image input for the model.\n", "        input_shape: optional shape tuple, only to be specified\n", "            if `include_top` is False (otherwise the input shape\n", "            has to be `(299, 299, 3)` (with `channels_last` data format)\n", "            or `(3, 299, 299)` (with `channels_first` data format).\n", "            It should have exactly 3 inputs channels,\n", "            and width and height should be no smaller than 139.\n", "            E.g. `(150, 150, 3)` would be one valid value.\n", "        pooling: Optional pooling mode for feature extraction\n", "            when `include_top` is `False`.\n", "            - `None` means that the output of the model will be\n", "                the 4D tensor output of the\n", "                last convolutional layer.\n", "            - `avg` means that global average pooling\n", "                will be applied to the output of the\n", "                last convolutional layer, and thus\n", "                the output of the model will be a 2D tensor.\n", "            - `max` means that global max pooling will\n", "                be applied.\n", "        classes: optional number of classes to classify images\n", "            into, only to be specified if `include_top` is True, and\n", "            if no `weights` argument is specified.\n", "    Returns:\n", "        A Keras model instance.\n", "    Raises:\n", "        ValueError: in case of invalid argument for `weights`,\n", "            or invalid input shape.\n", "    \"\"\"\n", "    if weights not in {'imagenet', None}:\n", "        raise ValueError('The `weights` argument should be either '\n", "                         '`None` (random initialization) or `imagenet` '\n", "                         '(pre-training on ImageNet).')\n", "\n", "    if weights == 'imagenet' and include_top and classes != 1000:\n", "        raise ValueError('If using `weights` as imagenet with `include_top`'\n", "                         ' as true, `classes` should be 1000')\n", "\n", "    # Determine proper input shape\n", "    #input_shape = _obtain_input_shape(\n", "    #    input_shape,\n", "    #    default_size=299,\n", "    #    min_size=139,\n", "    #    data_format=K.image_data_format(),\n", "    #    include_top=include_top)\n", "\n", "    if input_tensor is None:\n", "        #img_input = Input(shape=input_shape)\n", "        img_input = Input(shape=(img_rows, img_cols, channel))\n", "    else:\n", "        img_input = Input(tensor=input_tensor, shape=input_shape)\n", "\n", "    if K.image_data_format() == 'channels_first':\n", "        channel_axis = 1\n", "        print('Theano')\n", "    else:\n", "        channel_axis = 3\n", "        print('TensorFlow')\n", "\n", "    x = conv2d_bn(img_input, 32, 3, 3, strides=(2, 2), padding='valid')\n", "    x = conv2d_bn(x, 32, 3, 3, padding='valid')\n", "    x = conv2d_bn(x, 64, 3, 3)\n", "    x = MaxPooling2D((3, 3), strides=(2, 2))(x)\n", "\n", "    x = conv2d_bn(x, 80, 1, 1, padding='valid')\n", "    x = conv2d_bn(x, 192, 3, 3, padding='valid')\n", "    x = MaxPooling2D((3, 3), strides=(2, 2))(x)\n", "\n", "    # mixed 0, 1, 2: 35 x 35 x 256\n", "    branch1x1 = conv2d_bn(x, 64, 1, 1)\n", "\n", "    branch5x5 = conv2d_bn(x, 48, 1, 1)\n", "    branch5x5 = conv2d_bn(branch5x5, 64, 5, 5)\n", "\n", "    branch3x3dbl = conv2d_bn(x, 64, 1, 1)\n", "    branch3x3dbl = conv2d_bn(branch3x3dbl, 96, 3, 3)\n", "    branch3x3dbl = conv2d_bn(branch3x3dbl, 96, 3, 3)\n", "\n", "    branch_pool = AveragePooling2D((3, 3), strides=(1, 1), padding='same')(x)\n", "    branch_pool = conv2d_bn(branch_pool, 32, 1, 1)\n", "    x = layers.concatenate(\n", "        [branch1x1, branch5x5, branch3x3dbl, branch_pool],\n", "        axis=channel_axis,\n", "        name='mixed0')\n", "\n", "    # mixed 1: 35 x 35 x 256\n", "    branch1x1 = conv2d_bn(x, 64, 1, 1)\n", "\n", "    branch5x5 = conv2d_bn(x, 48, 1, 1)\n", "    branch5x5 = conv2d_bn(branch5x5, 64, 5, 5)\n", "\n", "    branch3x3dbl = conv2d_bn(x, 64, 1, 1)\n", "    branch3x3dbl = conv2d_bn(branch3x3dbl, 96, 3, 3)\n", "    branch3x3dbl = conv2d_bn(branch3x3dbl, 96, 3, 3)\n", "\n", "    branch_pool = AveragePooling2D((3, 3), strides=(1, 1), padding='same')(x)\n", "    branch_pool = conv2d_bn(branch_pool, 64, 1, 1)\n", "    x = layers.concatenate(\n", "        [branch1x1, branch5x5, branch3x3dbl, branch_pool],\n", "        axis=channel_axis,\n", "        name='mixed1')\n", "\n", "    # mixed 2: 35 x 35 x 256\n", "    branch1x1 = conv2d_bn(x, 64, 1, 1)\n", "\n", "    branch5x5 = conv2d_bn(x, 48, 1, 1)\n", "    branch5x5 = conv2d_bn(branch5x5, 64, 5, 5)\n", "\n", "    branch3x3dbl = conv2d_bn(x, 64, 1, 1)\n", "    branch3x3dbl = conv2d_bn(branch3x3dbl, 96, 3, 3)\n", "    branch3x3dbl = conv2d_bn(branch3x3dbl, 96, 3, 3)\n", "\n", "    branch_pool = AveragePooling2D((3, 3), strides=(1, 1), padding='same')(x)\n", "    branch_pool = conv2d_bn(branch_pool, 64, 1, 1)\n", "    x = layers.concatenate(\n", "        [branch1x1, branch5x5, branch3x3dbl, branch_pool],\n", "        axis=channel_axis,\n", "        name='mixed2')\n", "\n", "    # mixed 3: 17 x 17 x 768\n", "    branch3x3 = conv2d_bn(x, 384, 3, 3, strides=(2, 2), padding='valid')\n", "\n", "    branch3x3dbl = conv2d_bn(x, 64, 1, 1)\n", "    branch3x3dbl = conv2d_bn(branch3x3dbl, 96, 3, 3)\n", "    branch3x3dbl = conv2d_bn(\n", "        branch3x3dbl, 96, 3, 3, strides=(2, 2), padding='valid')\n", "\n", "    branch_pool = MaxPooling2D((3, 3), strides=(2, 2))(x)\n", "    x = layers.concatenate(\n", "        [branch3x3, branch3x3dbl, branch_pool], axis=channel_axis, name='mixed3')\n", "\n", "    # mixed 4: 17 x 17 x 768\n", "    branch1x1 = conv2d_bn(x, 192, 1, 1)\n", "\n", "    branch7x7 = conv2d_bn(x, 128, 1, 1)\n", "    branch7x7 = conv2d_bn(branch7x7, 128, 1, 7)\n", "    branch7x7 = conv2d_bn(branch7x7, 192, 7, 1)\n", "\n", "    branch7x7dbl = conv2d_bn(x, 128, 1, 1)\n", "    branch7x7dbl = conv2d_bn(branch7x7dbl, 128, 7, 1)\n", "    branch7x7dbl = conv2d_bn(branch7x7dbl, 128, 1, 7)\n", "    branch7x7dbl = conv2d_bn(branch7x7dbl, 128, 7, 1)\n", "    branch7x7dbl = conv2d_bn(branch7x7dbl, 192, 1, 7)\n", "\n", "    branch_pool = AveragePooling2D((3, 3), strides=(1, 1), padding='same')(x)\n", "    branch_pool = conv2d_bn(branch_pool, 192, 1, 1)\n", "    x = layers.concatenate(\n", "        [branch1x1, branch7x7, branch7x7dbl, branch_pool],\n", "        axis=channel_axis,\n", "        name='mixed4')\n", "\n", "    # mixed 5, 6: 17 x 17 x 768\n", "    for i in range(2):\n", "        branch1x1 = conv2d_bn(x, 192, 1, 1)\n", "\n", "        branch7x7 = conv2d_bn(x, 160, 1, 1)\n", "        branch7x7 = conv2d_bn(branch7x7, 160, 1, 7)\n", "        branch7x7 = conv2d_bn(branch7x7, 192, 7, 1)\n", "\n", "        branch7x7dbl = conv2d_bn(x, 160, 1, 1)\n", "        branch7x7dbl = conv2d_bn(branch7x7dbl, 160, 7, 1)\n", "        branch7x7dbl = conv2d_bn(branch7x7dbl, 160, 1, 7)\n", "        branch7x7dbl = conv2d_bn(branch7x7dbl, 160, 7, 1)\n", "        branch7x7dbl = conv2d_bn(branch7x7dbl, 192, 1, 7)\n", "\n", "        branch_pool = AveragePooling2D(\n", "            (3, 3), strides=(1, 1), padding='same')(x)\n", "        branch_pool = conv2d_bn(branch_pool, 192, 1, 1)\n", "        x = layers.concatenate(\n", "            [branch1x1, branch7x7, branch7x7dbl, branch_pool],\n", "            axis=channel_axis,\n", "            name='mixed' + str(5 + i))\n", "\n", "    # mixed 7: 17 x 17 x 768\n", "    branch1x1 = conv2d_bn(x, 192, 1, 1)\n", "\n", "    branch7x7 = conv2d_bn(x, 192, 1, 1)\n", "    branch7x7 = conv2d_bn(branch7x7, 192, 1, 7)\n", "    branch7x7 = conv2d_bn(branch7x7, 192, 7, 1)\n", "\n", "    branch7x7dbl = conv2d_bn(x, 192, 1, 1)\n", "    branch7x7dbl = conv2d_bn(branch7x7dbl, 192, 7, 1)\n", "    branch7x7dbl = conv2d_bn(branch7x7dbl, 192, 1, 7)\n", "    branch7x7dbl = conv2d_bn(branch7x7dbl, 192, 7, 1)\n", "    branch7x7dbl = conv2d_bn(branch7x7dbl, 192, 1, 7)\n", "\n", "    branch_pool = AveragePooling2D((3, 3), strides=(1, 1), padding='same')(x)\n", "    branch_pool = conv2d_bn(branch_pool, 192, 1, 1)\n", "    x = layers.concatenate(\n", "        [branch1x1, branch7x7, branch7x7dbl, branch_pool],\n", "        axis=channel_axis,\n", "        name='mixed7')\n", "\n", "    # mixed 8: 8 x 8 x 1280\n", "    branch3x3 = conv2d_bn(x, 192, 1, 1)\n", "    branch3x3 = conv2d_bn(branch3x3, 320, 3, 3,\n", "                          strides=(2, 2), padding='valid')\n", "\n", "    branch7x7x3 = conv2d_bn(x, 192, 1, 1)\n", "    branch7x7x3 = conv2d_bn(branch7x7x3, 192, 1, 7)\n", "    branch7x7x3 = conv2d_bn(branch7x7x3, 192, 7, 1)\n", "    branch7x7x3 = conv2d_bn(\n", "        branch7x7x3, 192, 3, 3, strides=(2, 2), padding='valid')\n", "\n", "    branch_pool = MaxPooling2D((3, 3), strides=(2, 2))(x)\n", "    x = layers.concatenate(\n", "        [branch3x3, branch7x7x3, branch_pool], axis=channel_axis, name='mixed8')\n", "\n", "    # mixed 9: 8 x 8 x 2048\n", "    for i in range(2):\n", "        branch1x1 = conv2d_bn(x, 320, 1, 1)\n", "\n", "        branch3x3 = conv2d_bn(x, 384, 1, 1)\n", "        branch3x3_1 = conv2d_bn(branch3x3, 384, 1, 3)\n", "        branch3x3_2 = conv2d_bn(branch3x3, 384, 3, 1)\n", "        branch3x3 = layers.concatenate(\n", "            [branch3x3_1, branch3x3_2], axis=channel_axis, name='mixed9_' + str(i))\n", "\n", "        branch3x3dbl = conv2d_bn(x, 448, 1, 1)\n", "        branch3x3dbl = conv2d_bn(branch3x3dbl, 384, 3, 3)\n", "        branch3x3dbl_1 = conv2d_bn(branch3x3dbl, 384, 1, 3)\n", "        branch3x3dbl_2 = conv2d_bn(branch3x3dbl, 384, 3, 1)\n", "        branch3x3dbl = layers.concatenate(\n", "            [branch3x3dbl_1, branch3x3dbl_2], axis=channel_axis)\n", "\n", "        branch_pool = AveragePooling2D(\n", "            (3, 3), strides=(1, 1), padding='same')(x)\n", "        branch_pool = conv2d_bn(branch_pool, 192, 1, 1)\n", "        x = layers.concatenate(\n", "            [branch1x1, branch3x3, branch3x3dbl, branch_pool],\n", "            axis=channel_axis,\n", "            name='mixed' + str(9 + i))\n", "    if include_top:\n", "        # Classification block\n", "        x_fc = GlobalAveragePooling2D(name='avg_pool')(x)\n", "        x_fc = Dense(classes, activation='softmax', name='predictions')(x_fc)\n", "    else:\n", "        if pooling == 'avg':\n", "            x_fc = GlobalAveragePooling2D()(x_fc)\n", "        elif pooling == 'max':\n", "            x_fc = GlobalMaxPooling2D()(x_fc)\n", "\n", "    # Ensure that the model takes into account\n", "    # any potential predecessors of `input_tensor`.\n", "    if input_tensor is not None:\n", "        inputs = get_source_inputs(input_tensor)\n", "    else:\n", "        inputs = img_input\n", "    # Create model.\n", "    model = Model(inputs, x_fc, name='inception_v3')\n", "\n", "    # load weights\n", "    if weights == 'imagenet':\n", "        if K.image_data_format() == 'channels_first':\n", "            if K.backend() == 'tensorflow':\n", "                warnings.warn('You are using the TensorFlow backend, yet you '\n", "                              'are using the Theano '\n", "                              'image data format convention '\n", "                              '(`image_data_format=\"channels_first\"`). '\n", "                              'For best performance, set '\n", "                              '`image_data_format=\"channels_last\"` in '\n", "                              'your Keras config '\n", "                              'at ~/.keras/keras.json.')\n", "        if include_top:\n", "            weights_path = get_file(\n", "                'inception_v3_weights_tf_dim_ordering_tf_kernels.h5',\n", "                WEIGHTS_PATH,\n", "                cache_subdir='models',\n", "                md5_hash='9a0d58056eeedaa3f26cb7ebd46da564')\n", "        #else:\n", "        #    weights_path = get_file(\n", "        #        'inception_v3_weights_tf_dim_ordering_tf_kernels_notop.h5',\n", "        #        WEIGHTS_PATH_NO_TOP,\n", "        #        cache_subdir='models',\n", "        #        md5_hash='bcbd6486424b2319ff4ef7d526e38f63')\n", "        model.load_weights(weights_path)\n", "    #\n", "    # define a new version of \"bottleneck\" with our number of classes\n", "    #\n", "    x_newfc = GlobalAveragePooling2D( name='avg_pool')(x)\n", "    x_newfc = Dense(num_classes, activation='softmax', name='predictions')(x_newfc)\n", "\n", "    # Create another model with our customized softmax\n", "    model = Model(inputs, x_newfc)\n", "    # set the first 25 layers \n", "    # to non-trainable (weights will not be updated)\n", "    #\n", "    # Uncomment the next two lines if you want to trun of tunning of some number of consecutive\n", "    # layers starting from layer 0\n", "    #\n", "    #for layer in model.layers[:25]:\n", "    #    layer.trainable = False\n", "    # Learning rate 0.01 when tunning all layers)\n", "    sgd = SGD(lr=1e-2, decay=1e-6, momentum=0.9, nesterov=True)\n", "    model.compile(optimizer=sgd, loss='categorical_crossentropy', metrics=['accuracy'])\n", "\n", "    return model\n", "\n", "\n", "def preprocess_input(x):\n", "    x /= 255.\n", "    x -= 0.5\n", "    x *= 2.\n", "    return x\n"], "outputs": [], "execution_count": null, "metadata": {"collapsed": true}, "cell_type": "code"}, {"source": ["# If you do not have the weights file in your computer Keras will try to connect \n", "# and download it from:\n", "# https://github.com/fchollet/deep-learning-models/releases/download/v0.5/inception_v3_weights_tf_dim_ordering_tf_kernels.h5\n", "# You can also use your browser to download the file and mv or cp to\n", "#   ~/.keras/models/.\n", "\n", "model = InceptionV3(include_top=True, weights='imagenet')\n", "\n", "model.summary()"], "outputs": [], "execution_count": null, "metadata": {"_kg_hide-output": true}, "cell_type": "code"}, {"source": ["# Start Fine-tuning\n", "nb_train_samples = 9916514\n", "nb_validation_samples = 2454434\n", "epochs = 2\n", "model.fit_generator(\n", "        train_generator,\n", "        steps_per_epoch=nb_train_samples // batch_size,\n", "        epochs=epochs,\n", "        validation_data=validation_generator,\n", "        validation_steps=nb_validation_samples // batch_size)\n", "\n", "# you may want to start with steps_per_epoch ~ 100 - 300 and explore the migration to GPU's"], "outputs": [], "execution_count": null, "metadata": {"_kg_hide-output": true}, "cell_type": "code"}, {"source": ["As you can see, kaggle doen'st provide permission to create folders. The kernel fails at several stages and it can only be tested if you ran in your own computer and have the data in the proper train and validation folders. \n", "\n", "Please use the comments sections if you need a hand to make the kernel work.\n", "\n", "Thanks for your comments and suggestions."], "metadata": {}, "cell_type": "markdown"}, {"source": [], "outputs": [], "execution_count": null, "metadata": {"collapsed": true}, "cell_type": "code"}], "nbformat_minor": 1, "nbformat": 4}