{"metadata": {"kernelspec": {"language": "python", "display_name": "Python 3", "name": "python3"}, "language_info": {"pygments_lexer": "ipython3", "name": "python", "file_extension": ".py", "mimetype": "text/x-python", "version": "3.6.1", "nbconvert_exporter": "python", "codemirror_mode": {"name": "ipython", "version": 3}}}, "cells": [{"metadata": {"trusted": true, "_uuid": "c3210d17b42eb27e71cff461685c1f9ce86aa790", "_cell_guid": "b9a279d5-e493-4c61-bbc4-c7cfa0092bb0"}, "execution_count": null, "cell_type": "code", "source": "import numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\nfrom keras.models import Sequential, Model\nfrom keras.layers import Dense, Conv2D, Input, MaxPool2D, UpSampling2D, Concatenate, Conv2DTranspose\nimport tensorflow as tf\nfrom keras.optimizers import Adam\nfrom scipy.misc import imresize\nfrom tqdm import tqdm\nfrom sklearn.model_selection import train_test_split\nimport os\nfrom keras.preprocessing.image import array_to_img, img_to_array, load_img, ImageDataGenerator\n%matplotlib inline\n\n\nfrom subprocess import check_output\nprint(check_output([\"ls\", \"../input\"]).decode(\"utf8\"))", "outputs": []}, {"metadata": {"_uuid": "7bdaf71ed2c7d1c035c5ac7e184090c18f0571c6"}, "outputs": [], "cell_type": "markdown", "source": "Let's prepare our data so that we can read it into our model. Since the data is super big we need a generator to read it a few at a time into memory.", "execution_count": null}, {"metadata": {"trusted": true, "_uuid": "a11c6e3d97e22a77ace6862cb3001faa14405cc2"}, "execution_count": null, "cell_type": "code", "source": "# set the necessary directories\ndata_dir = \"../input/train/\"\nmask_dir = \"../input/train_masks/\"\nall_images = os.listdir(data_dir)", "outputs": []}, {"metadata": {"trusted": true, "_uuid": "c67562cc573e6e6b0e4f1701556f2e6c25ec73ce"}, "execution_count": null, "cell_type": "code", "source": "# pick which images we will use for testing and which for validation\ntrain_images, validation_images = train_test_split(all_images, train_size=0.8, test_size=0.2)", "outputs": []}, {"metadata": {"trusted": true, "_uuid": "a9f6ed3fcd25fa7878fe353db5ce904cfd1723ea"}, "execution_count": null, "cell_type": "code", "source": "# utility function to convert greyscale images to rgb\ndef grey2rgb(img):\n    new_img = []\n    for i in range(img.shape[0]):\n        for j in range(img.shape[1]):\n            new_img.append(list(img[i][j])*3)\n    new_img = np.array(new_img).reshape(img.shape[0], img.shape[1], 3)\n    return new_img\n\n\n# generator that we will use to read the data from the directory\ndef data_gen_small(data_dir, mask_dir, images, batch_size, dims):\n        \"\"\"\n        data_dir: where the actual images are kept\n        mask_dir: where the actual masks are kept\n        images: the filenames of the images we want to generate batches from\n        batch_size: self explanatory\n        dims: the dimensions in which we want to rescale our images\n        \"\"\"\n        while True:\n            ix = np.random.choice(np.arange(len(images)), batch_size)\n            imgs = []\n            labels = []\n            for i in ix:\n                # images\n                original_img = load_img(data_dir + images[i])\n                resized_img = imresize(original_img, dims+[3])\n                array_img = img_to_array(resized_img)/255\n                imgs.append(array_img)\n                \n                # masks\n                original_mask = load_img(mask_dir + images[i].split(\".\")[0] + '_mask.gif')\n                resized_mask = imresize(original_mask, dims+[3])\n                array_mask = img_to_array(resized_mask)/255\n                labels.append(array_mask[:, :, 0])\n            imgs = np.array(imgs)\n            labels = np.array(labels)\n            yield imgs, labels.reshape(-1, dims[0], dims[1], 1)\n\n# example use\ntrain_gen = data_gen_small(data_dir, mask_dir, train_images, 5, [128, 128])\nimg, msk = next(train_gen)\n\nplt.imshow(img[0])\nplt.imshow(grey2rgb(msk[0]), alpha=0.5)", "outputs": []}, {"metadata": {"_uuid": "526842f3fcdf31f4aae71eaadd8921988d9df1fa"}, "outputs": [], "cell_type": "markdown", "source": "Now let's get started with making our actual network.", "execution_count": null}, {"metadata": {"trusted": true, "_uuid": "30e5b162011bd0ef7e52fc43b1c8995c745f1f0e", "collapsed": true}, "execution_count": null, "cell_type": "code", "source": "# First let's define the two different types of layers that we will be using.\n\ndef down(input_layer, filters, pool=True):\n    conv1 = Conv2D(filters, (3, 3), padding='same', activation='relu')(input_layer)\n    residual = Conv2D(filters, (3, 3), padding='same', activation='relu')(conv1)\n    if pool:\n        max_pool = MaxPool2D()(residual)\n        return max_pool, residual\n    else:\n        return residual\n\ndef up(input_layer, residual, filters):\n    filters=int(filters)\n    upsample = UpSampling2D()(input_layer)\n    upconv = Conv2D(filters, kernel_size=(2, 2), padding=\"same\")(upsample)\n    concat = Concatenate(axis=3)([residual, upconv])\n    conv1 = Conv2D(filters, (3, 3), padding='same', activation='relu')(concat)\n    conv2 = Conv2D(filters, (3, 3), padding='same', activation='relu')(conv1)\n    return conv2", "outputs": []}, {"metadata": {"trusted": true, "_uuid": "9648de8657b1815725b20f6c6873a71ad61b4076"}, "execution_count": null, "cell_type": "code", "source": "# Make a custom U-nets implementation.\nfilters = 64\ninput_layer = Input(shape = [128, 128, 3])\nlayers = [input_layer]\nresiduals = []\n\n# Down 1, 128\nd1, res1 = down(input_layer, filters)\nresiduals.append(res1)\n\nfilters *= 2\n\n# Down 2, 64\nd2, res2 = down(d1, filters)\nresiduals.append(res2)\n\nfilters *= 2\n\n# Down 3, 32\nd3, res3 = down(d2, filters)\nresiduals.append(res3)\n\nfilters *= 2\n\n# Down 4, 16\nd4, res4 = down(d3, filters)\nresiduals.append(res4)\n\nfilters *= 2\n\n# Down 5, 8\nd5 = down(d4, filters, pool=False)\n\n# Up 1, 16\nup1 = up(d5, residual=residuals[-1], filters=filters/2)\n\nfilters /= 2\n\n# Up 2,  32\nup2 = up(up1, residual=residuals[-2], filters=filters/2)\n\nfilters /= 2\n\n# Up 3, 64\nup3 = up(up2, residual=residuals[-3], filters=filters/2)\n\nfilters /= 2\n\n# Up 4, 128\nup4 = up(up3, residual=residuals[-4], filters=filters/2)\n\nout = Conv2D(filters=1, kernel_size=(1, 1), activation=\"sigmoid\")(up4)\n\nmodel = Model(input_layer, out)\n\nmodel.summary()", "outputs": []}, {"metadata": {"trusted": true, "_uuid": "f0c6b27ca90005cf045f4b4928d616a8ba013855", "collapsed": true}, "execution_count": null, "cell_type": "code", "source": "# Now let's use Tensorflow to write our own dice_coeficcient metric\ndef dice_coef(y_true, y_pred):\n    smooth = 1e-5\n    \n    y_true = tf.round(tf.reshape(y_true, [-1]))\n    y_pred = tf.round(tf.reshape(y_pred, [-1]))\n    \n    isct = tf.reduce_sum(y_true * y_pred)\n    \n    return 2 * isct / (tf.reduce_sum(y_true) + tf.reduce_sum(y_pred))", "outputs": []}, {"metadata": {"scrolled": true, "trusted": true, "_uuid": "f320fdc6d0049beed438a896e94b133fa845572a"}, "execution_count": null, "cell_type": "code", "source": "# Training time!\n# probably need to play around a little bit with the learning rate to get it to start learning\nmodel.compile(optimizer=Adam(1e-4), loss='binary_crossentropy', metrics=[dice_coef])\nmodel.fit_generator(train_gen, steps_per_epoch=100, epochs=10)", "outputs": []}, {"metadata": {"_uuid": "e0a6a93f1b246e190359f56ff66b7af5ae153ee4"}, "outputs": [], "cell_type": "markdown", "source": "Thanks for checking this out! Please feel free to leave your comments below if you have any siggestions, observations or you just want to say hi!", "execution_count": null}], "nbformat_minor": 1, "nbformat": 4}