{"metadata": {"kernelspec": {"language": "python", "display_name": "Python 3", "name": "python3"}, "language_info": {"mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "file_extension": ".py", "version": "3.6.1", "codemirror_mode": {"name": "ipython", "version": 3}}}, "nbformat": 4, "nbformat_minor": 1, "cells": [{"cell_type": "markdown", "metadata": {}, "source": ["Try to predict the mask without looking at the images. Use only the supplied metadata and the orientation of the car. You won't win the competition that way, but it's a fun little image generation demo. Image resolution is quite low but might me increased if run locally."]}, {"cell_type": "code", "metadata": {"_kg_hide-output": false, "_uuid": "b35ef3bad0aca65fb348248667f04ffc605b0333", "_kg_hide-input": false, "_cell_guid": "fdbb40b0-d93d-46f8-b155-9959e0e914f3"}, "execution_count": null, "outputs": [], "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 os \n", "from glob import glob\n", "\n", "# Input data files are available in the \"../input/\" directory.\n", "\n", "INPUT_PATH = '../input'\n", "IMG_SIZE_LOG2=6\n", "IMG_SIZE=1<<IMG_SIZE_LOG2\n", "print('Mask size will be %dx%d'%(IMG_SIZE,IMG_SIZE))\n"]}, {"cell_type": "code", "metadata": {"_uuid": "6e6e4e37b2b79a3fee6e2c7087b135d2a435640f", "_kg_hide-input": false, "_cell_guid": "52ff693e-959b-400c-9b63-96a88bbbc39f"}, "execution_count": null, "outputs": [], "source": ["df_train = pd.read_csv('%s/train_masks.csv'%INPUT_PATH)\n", "df_train = df_train[['img']]\n", "ids_train_tmp = df_train['img'].map(lambda s: s.split('.')[0])\n", "df_train['img'] = ids_train_tmp\n", "df_train['id'] = ids_train_tmp.map(lambda s: s.split('_')[0])\n", "df_train['angle'] = ids_train_tmp.map(lambda s: s.split('_')[1])\n", "df_train['x_angle'] = (df_train['angle'].astype(float) - 1.0) / 16.0\n", "df_train.head()"]}, {"cell_type": "code", "metadata": {"_uuid": "39751b86252d86623965ad297cb216a31f07f5fb", "_cell_guid": "83427a1f-5f97-412f-9112-bf70ed46213a"}, "execution_count": null, "outputs": [], "source": ["df_meta = pd.read_csv('%s/metadata.csv'%INPUT_PATH)\n", "df_meta.head()"]}, {"cell_type": "code", "metadata": {"_uuid": "d3c78ed4bd07582f75452113812fb58336e0dc8a", "_cell_guid": "44bb4bf3-e9b6-4ead-a621-7a435008852d"}, "execution_count": null, "outputs": [], "source": ["#normalize data\n", "df_meta['make'] = df_meta['make'].str.lower()\n", "model = df_meta['model'].fillna(df_meta['trim1']).str.lower()\n", "# normalize further\n", "model = model.str.replace('series', '')\n", "model = model.str.replace('plug-in', '')\n", "model = model.str.replace('hybrid', '')\n", "model = model.str.replace(' ev', '')\n", "model = model.str.replace(' el', '')\n", "model = model.str.replace(' limited', '')\n", "model = model.str.replace(' 250c', ' 250')\n", "model = model.str.replace(' 350c', ' 350')\n", "model = model.str.replace('a8 l', 'a8')\n", "model = model.str.replace('cts-v', 'cts')\n", "model = model.str.replace(' esv', '')\n", "model = model.str.replace(' turbo', '')\n", "model = model.str.replace('grand ', '')\n", "model = model.str.replace(' select', '')\n", "model = model.str.replace(' gti', '')\n", "model = model.str.replace(' unlimited', '')\n", "model = model.str.replace('prius c', 'prius')\n", "model = model.str.replace('prius v', 'prius')\n", "model = model.str.replace('slk-class', 'slk')\n", "model = model.str.strip()\n", "car = df_meta['make'].str.lower()+ ' ' + model\n", "car = car.str.replace('dodge ram', 'ram')\n", "car = car.str.replace('ram ram', 'ram')\n", "df_meta['car'] = car\n", "\n", "df_meta.head()"]}, {"cell_type": "markdown", "metadata": {"_uuid": "4d321dc02ab60ab0ae8b89bfad69c9f8fdefccc8", "_cell_guid": "d94f7645-67a2-47dd-be8b-abcf453ad9a3"}, "source": ["# Prepare DNN input"]}, {"cell_type": "code", "metadata": {"_uuid": "1fd491d40589b5a79ac8bf51d8473370b44ba902", "_cell_guid": "f0155c28-9d47-441e-ac31-f064b2fb1e69"}, "execution_count": null, "outputs": [], "source": ["df_meta_x=pd.get_dummies(df_meta, prefix='x', columns=['car'])\n", "df_meta_x['x_year']=(2017.0 - df_meta['year']) / 7.0\n", "df_meta_x.set_index(['id'], inplace=True)\n", "df_in = pd.merge(df_train, df_meta_x, left_on='id', right_index=True)\n", "df_in.set_index(['img'], inplace=True)\n", "df_in = df_in.filter(regex='x_')\n", "from sklearn.model_selection import train_test_split\n", "df_train_split, df_valid_split = train_test_split(df_in, test_size=0.2, random_state=42)\n", "df_in.head()"]}, {"cell_type": "code", "metadata": {"collapsed": true, "_uuid": "ff982158c2d1302c0f95221cd30522b12c97055b", "_kg_hide-output": false, "_cell_guid": "fb0c8447-3c32-4a6d-b242-039375bfbf54"}, "execution_count": null, "outputs": [], "source": ["import cv2\n", "\n", "def bbox(img):\n", "    img = (img > 0)\n", "    rows = np.any(img, axis=1)\n", "    cols = np.any(img, axis=0)\n", "    rmin, rmax = np.argmax(rows), img.shape[0] - 1 - np.argmax(np.flipud(rows))\n", "    cmin, cmax = np.argmax(cols), img.shape[1] - 1 - np.argmax(np.flipud(cols))\n", "    return rmin, rmax, cmin, cmax\n", "\n", "def read_mask_centered(name):\n", "    png_file = '{}/train_masks/{}_mask.png'.format(INPUT_PATH, name)\n", "    if os.path.exists(png_file):\n", "        img_arr = cv2.imread(png_file, cv2.IMREAD_GRAYSCALE)\n", "    else:\n", "        gif_file = '{}/train_masks/{}_mask.gif'.format(INPUT_PATH, name)\n", "        from scipy import ndimage\n", "        img_arr = ndimage.imread(gif_file,flatten=True)\n", "\n", "    # find mask bounding box\n", "    r1, r2, c1, c2 = bbox(img_arr)\n", "    # crop and resize\n", "    img_cr = img_arr[r1:r2, c1:c2]\n", "    mask = cv2.resize(img_cr,(IMG_SIZE,IMG_SIZE))\n", "    return mask\n"]}, {"cell_type": "code", "metadata": {"_uuid": "9bfb2c95ff87fc70dbf29d9fe271661606990902", "collapsed": true, "_cell_guid": "cea477ad-713e-48d1-970c-36af59db56dc"}, "execution_count": null, "outputs": [], "source": ["def input_generator(df_in, batch_size):\n", "    while True:\n", "        for start in range(0, len(df_in), batch_size):\n", "            end = min(start + batch_size, len(df_in))\n", "            x_batch = np.array(df_in[start:end], dtype=np.float32)\n", "            y_batch = []\n", "            for img_id in df_in[start:end].index:\n", "                mask = read_mask_centered(img_id)\n", "                mask = np.expand_dims(mask, axis=2)\n", "                y_batch.append(mask)\n", "            y_batch = np.array(y_batch, np.float32) / 255\n", "            yield x_batch, y_batch\n"]}, {"cell_type": "markdown", "metadata": {"_uuid": "f2a3d31375f0e50d989a8bcf30a5ceb3d149f1e1", "_cell_guid": "f7f26073-dd35-45fd-825e-39b49998ff55"}, "source": ["Import some network stuff\n"]}, {"cell_type": "code", "metadata": {"_uuid": "d1561553e150a2a075b61829e6d3e995296223e1", "_kg_hide-input": true, "_cell_guid": "5dff9ef7-1189-49ab-bd86-64d4eb148496"}, "execution_count": null, "outputs": [], "source": ["from keras.layers import Input, concatenate, Conv2D, UpSampling2D, BatchNormalization, Reshape, Dropout\n", "from keras.losses import binary_crossentropy\n", "from keras.models import Model\n", "from keras.optimizers import Adam\n", "from keras.callbacks import EarlyStopping, ReduceLROnPlateau\n", "import keras.backend as K\n", "\n", "def dice_loss(y_true, y_pred):\n", "    smooth = 1.\n", "    y_true_f = K.flatten(y_true)\n", "    y_pred_f = K.flatten(y_pred)\n", "    intersection = K.sum(y_true_f * y_pred_f)\n", "    return (2. * intersection + smooth) / (K.sum(y_true_f) + K.sum(y_pred_f) + smooth)\n", "\n", "def bce_dice_loss(y_true, y_pred):\n", "    return binary_crossentropy(y_true, y_pred) + (1 - dice_loss(y_true, y_pred))"]}, {"cell_type": "markdown", "metadata": {}, "source": ["# Create the Network"]}, {"cell_type": "code", "metadata": {"_uuid": "d38e83e0e41fd8bbc44fc93865cf3082e9c0eaf8", "_cell_guid": "19518899-1a23-4764-b05c-f7e0d2296c24"}, "execution_count": null, "outputs": [], "source": ["def create_up(input, filter_count, n_layers=2):\n", "    up = UpSampling2D((2, 2))(input)\n", "    up = BatchNormalization()(up)\n", "    up = Dropout(0.7)(up)\n", "    for i in range(n_layers):\n", "        up = Conv2D(filter_count, (3, 3), padding='same', activation='relu')(up)\n", "        up = BatchNormalization()(up)\n", "    return up\n", "\n", "def create_model(n_inputs):\n", "    inputs = Input(shape=(n_inputs,))\n", "    x = Reshape((1,1,n_inputs))(inputs)\n", "    n_filters = n_inputs // 2\n", "    for depth in range(IMG_SIZE_LOG2):\n", "        x = create_up(x, n_filters)\n", "        n_filters = int(n_filters / 1.5)\n", "    classify = Conv2D(1, (1, 1), activation='sigmoid')(x)\n", "    model = Model(inputs=inputs, outputs=classify) \n", "    return model\n", "\n", "n_inputs = df_in.values.shape[1]\n", "model = create_model(n_inputs)\n", "#model.summary(line_length=80)\n", "model.compile(optimizer=Adam(), loss=bce_dice_loss, metrics=[dice_loss])\n", "batch_size = 16\n", "epochs=2\n", "model.fit_generator(generator=input_generator(df_train_split,batch_size),\n", "                    steps_per_epoch=np.ceil(float(len(df_train_split)) / float(batch_size)),\n", "                    epochs=epochs,\n", "                    verbose=1,\n", "                    workers=1,\n", "                    max_queue_size=2*batch_size,\n", "                    validation_data=input_generator(df_valid_split,batch_size),\n", "                    validation_steps=np.ceil(float(len(df_valid_split)) / float(batch_size)))\n"]}, {"cell_type": "markdown", "metadata": {"_uuid": "11e5deaaad6fa90a0e4e8ab41527d5c8314e69df", "_cell_guid": "e45b2747-2867-4457-aa28-a6cd618e3c1d"}, "source": ["# Show some predictions"]}, {"cell_type": "code", "metadata": {"_uuid": "294aee263f331a719c77339d98b0679365970aaf", "_cell_guid": "9cef8e15-7455-4568-a91c-7d8af01e3a6f"}, "execution_count": null, "outputs": [], "source": ["import matplotlib.pylab as plt\n", "plt.figure(figsize=(20, 20))\n", "\n", "for i,batch in enumerate(input_generator(df_valid_split,1)):\n", "    if i >= 9:\n", "        break\n", "    id=df_valid_split.index[i]   \n", "    x_batch, y_true = batch\n", "    y_batch = model.predict(x_batch)\n", "\n", "    plt.subplot(9,2,2*i+1)\n", "    plt.title('%s true'%id)\n", "    plt.axis('off')\n", "    plt.imshow(y_true[0,:,:,0])\n", "    plt.subplot(9,2,2*i+2)\n", "    plt.title('%s predicted'%id)\n", "    plt.axis('off')\n", "    plt.imshow(y_batch[0,:,:,0])    "]}]}