{
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "_cell_guid": "4c1518a6-76a0-44f4-0f56-3231efc206fa"
      },
      "source": [
        "Public Leader-board of 0.89094\n",
        "===================================================="
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "_cell_guid": "f75ef7fc-84d2-8ed9-4617-9cf09facb4e0"
      },
      "source": [
        "Save train and test images to normalized numpy arrays once for running multiple neural network configuration tests"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "_cell_guid": "6466c479-a18f-00b5-98a0-6f105de69b3e"
      },
      "outputs": [],
      "source": [
        "from PIL import ImageFilter, ImageStat, Image, ImageDraw\n",
        "from multiprocessing import Pool, cpu_count\n",
        "from sklearn.preprocessing import LabelEncoder\n",
        "import pandas as pd\n",
        "import numpy as np\n",
        "import glob\n",
        "import cv2\n",
        "\n",
        "def im_multi(path):\n",
        "    try:\n",
        "        im_stats_im_ = Image.open(path)\n",
        "        return [path, {'size': im_stats_im_.size}]\n",
        "    except:\n",
        "        print(path)\n",
        "        return [path, {'size': [0,0]}]\n",
        "\n",
        "def im_stats(im_stats_df):\n",
        "    im_stats_d = {}\n",
        "    p = Pool(cpu_count())\n",
        "    ret = p.map(im_multi, im_stats_df['path'])\n",
        "    for i in range(len(ret)):\n",
        "        im_stats_d[ret[i][0]] = ret[i][1]\n",
        "    im_stats_df['size'] = im_stats_df['path'].map(lambda x: ' '.join(str(s) for s in im_stats_d[x]['size']))\n",
        "    return im_stats_df\n",
        "\n",
        "def get_im_cv2(path):\n",
        "    img = cv2.imread(path)\n",
        "    resized = cv2.resize(img, (32, 32), cv2.INTER_LINEAR) #use cv2.resize(img, (64, 64), cv2.INTER_LINEAR)\n",
        "    return [path, resized]\n",
        "\n",
        "def normalize_image_features(paths):\n",
        "    imf_d = {}\n",
        "    p = Pool(cpu_count())\n",
        "    ret = p.map(get_im_cv2, paths)\n",
        "    for i in range(len(ret)):\n",
        "        imf_d[ret[i][0]] = ret[i][1]\n",
        "    ret = []\n",
        "    fdata = [imf_d[f] for f in paths]\n",
        "    fdata = np.array(fdata, dtype=np.uint8)\n",
        "    fdata = fdata.transpose((0, 3, 1, 2))\n",
        "    fdata = fdata.astype('float32')\n",
        "    fdata = fdata / 255\n",
        "    return fdata\n",
        "\n",
        "train = glob.glob('../input/train/**/*.jpg') + glob.glob('../input/additional/**/*.jpg')\n",
        "train = pd.DataFrame([[p.split('/')[3],p.split('/')[4],p] for p in train], columns = ['type','image','path'])[::5] #limit for Kaggle Demo\n",
        "train = im_stats(train)\n",
        "train = train[train['size'] != '0 0'].reset_index(drop=True) #remove bad images\n",
        "train_data = normalize_image_features(train['path'])\n",
        "np.save('train.npy', train_data, allow_pickle=True, fix_imports=True)\n",
        "\n",
        "le = LabelEncoder()\n",
        "train_target = le.fit_transform(train['type'].values)\n",
        "print(le.classes_) #in case not 1 to 3 order\n",
        "np.save('train_target.npy', train_target, allow_pickle=True, fix_imports=True)\n",
        "\n",
        "test = glob.glob('../input/test/*.jpg')\n",
        "test = pd.DataFrame([[p.split('/')[3],p] for p in test], columns = ['image','path']) #[::20] #limit for Kaggle Demo\n",
        "test_data = normalize_image_features(test['path'])\n",
        "np.save('test.npy', test_data, allow_pickle=True, fix_imports=True)\n",
        "\n",
        "test_id = test.image.values\n",
        "np.save('test_id.npy', test_id, allow_pickle=True, fix_imports=True)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "_cell_guid": "d47ca73e-fe3b-5450-beb7-e6c37ef99441"
      },
      "source": [
        "Start your neural network high performance engines\n",
        "\n",
        " - I'll admit as you've no doubt noticed by now that I still don't know what I am doing with Neural Networks 'yet'."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "_cell_guid": "fc97dacc-9466-b369-b190-c979de910ba7"
      },
      "outputs": [],
      "source": [
        "from keras.wrappers.scikit_learn import KerasClassifier\n",
        "from keras.models import Sequential\n",
        "from keras.layers.core import Dense, Dropout, Flatten, Activation\n",
        "from keras.layers.convolutional import Convolution2D, ZeroPadding2D, MaxPooling2D\n",
        "from keras import optimizers\n",
        "from keras.preprocessing.image import ImageDataGenerator\n",
        "from sklearn.model_selection import train_test_split\n",
        "from keras import backend as K\n",
        "K.set_image_dim_ordering('th')\n",
        "K.set_floatx('float32')\n",
        "\n",
        "import pandas as pd\n",
        "import numpy as np\n",
        "np.random.seed(17)\n",
        "\n",
        "train_data = np.load('train.npy')\n",
        "train_target = np.load('train_target.npy')\n",
        "\n",
        "x_train,x_val_train,y_train,y_val_train = train_test_split(train_data,train_target,test_size=0.4, random_state=17)\n",
        "\n",
        "def create_model(opt_='adamax'):\n",
        "    model = Sequential()\n",
        "    model.add(Convolution2D(4, 3, 3, activation='relu', dim_ordering='th', input_shape=(3, 32, 32))) #use input_shape=(3, 64, 64)\n",
        "    model.add(MaxPooling2D(pool_size=(2, 2), strides=(2, 2), dim_ordering='th'))\n",
        "    model.add(Convolution2D(8, 3, 3, activation='relu', dim_ordering='th'))\n",
        "    model.add(MaxPooling2D(pool_size=(2, 2), strides=(2, 2), dim_ordering='th'))\n",
        "    model.add(Dropout(0.2))\n",
        "    \n",
        "    model.add(Flatten())\n",
        "    model.add(Dense(12, activation='tanh'))\n",
        "    model.add(Dropout(0.1))\n",
        "    model.add(Dense(3, activation='softmax'))\n",
        "\n",
        "    model.compile(optimizer=opt_, loss='sparse_categorical_crossentropy', metrics=['accuracy']) \n",
        "    return model\n",
        "\n",
        "datagen = ImageDataGenerator(rotation_range=0.3, zoom_range=0.3)\n",
        "datagen.fit(train_data)\n",
        "\n",
        "model = create_model()\n",
        "model.fit_generator(datagen.flow(x_train,y_train, batch_size=15, shuffle=True), nb_epoch=200, samples_per_epoch=len(x_train), verbose=20, validation_data=(x_val_train, y_val_train))\n",
        "\n",
        "test_data = np.load('test.npy')\n",
        "test_id = np.load('test_id.npy')\n",
        "\n",
        "pred = model.predict_proba(test_data)\n",
        "df = pd.DataFrame(pred, columns=['Type_1','Type_2','Type_3'])\n",
        "df['image_name'] = test_id\n",
        "df.to_csv('submission.csv', index=False)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "_cell_guid": "d1ce9481-0f89-dbe1-81b6-68a925dc24dd"
      },
      "outputs": [],
      "source": [
        "print(cpu_count())"
      ]
    }
  ],
  "metadata": {
    "_change_revision": 0,
    "_is_fork": false,
    "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.6.0"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 0
}