{"cells":[{"metadata":{"_cell_guid":"c332549b-8d23-4bb5-8497-e7a8eb8b21d2","_uuid":"5c38504af3a84bee68c66d3cde74443c58df422f","trusted":true},"cell_type":"code","source":"import os\nimport sys\nimport random\nimport warnings\n\nimport numpy as np\nimport pandas as pd\n\nimport matplotlib.pyplot as plt\n\nfrom tqdm import tqdm\nfrom itertools import chain\nfrom skimage.io import imread, imshow, imread_collection, concatenate_images\nfrom skimage.transform import resize\nfrom skimage.morphology import label\n\nfrom keras.models import Model, load_model\nfrom keras.layers import Input\nfrom keras.layers.core import Lambda\nfrom keras.layers.convolutional import Conv2D, Conv2DTranspose\nfrom keras.layers.pooling import MaxPooling2D\nfrom keras.layers.merge import concatenate\nfrom keras.callbacks import EarlyStopping, ModelCheckpoint\nfrom keras import backend as K\n\nimport tensorflow as tf\n\n# Set some parameters\nIMG_WIDTH = 128\nIMG_HEIGHT = 128\nIMG_CHANNELS = 3\nTRAIN_PATH = '../input/data-science-bowl-2018/stage1_train/'\nTEST_PATH = '../input/data-science-bowl-2018/stage1_test/'\n\nwarnings.filterwarnings('ignore', category=UserWarning, module='skimage')\nseed = 42\nrandom.seed = seed\nnp.random.seed = seed","execution_count":1,"outputs":[]},{"metadata":{"_cell_guid":"ffa0caf0-2d1b-40f2-865b-8e6db88526b6","_uuid":"3fb9d6530fbbd0e22e41fc4fd9fd9fc0bff027ac","collapsed":true,"trusted":true},"cell_type":"code","source":"# Get train and test IDs\ntrain_ids = next(os.walk(TRAIN_PATH))[1]\ntest_ids = next(os.walk(TEST_PATH))[1]","execution_count":2,"outputs":[]},{"metadata":{"_cell_guid":"ca0cc34b-c26f-41ee-88d7-975aebdb634e","_uuid":"9e389ba8bdb5b6fc03b231b6a6c84a8bde634053","trusted":true},"cell_type":"code","source":"# Get and resize train images and masks\nX_train = np.zeros((len(train_ids), IMG_HEIGHT, IMG_WIDTH, IMG_CHANNELS), dtype=np.uint8)\nY_train = np.zeros((len(train_ids), IMG_HEIGHT, IMG_WIDTH, 1), dtype=np.bool)\nprint('Getting and resizing train images and masks ... ')\nsys.stdout.flush()\nfor n, id_ in tqdm(enumerate(train_ids), total=len(train_ids)):\n    path = TRAIN_PATH + id_\n    img = imread(path + '/images/' + id_ + '.png')[:,:,:IMG_CHANNELS]\n    img = resize(img, (IMG_HEIGHT, IMG_WIDTH), mode='constant', preserve_range=True)\n    X_train[n] = img\n    mask = np.zeros((IMG_HEIGHT, IMG_WIDTH, 1), dtype=np.bool)\n    for mask_file in next(os.walk(path + '/masks/'))[2]:\n        mask_ = imread(path + '/masks/' + mask_file)\n        mask_ = np.expand_dims(resize(mask_, (IMG_HEIGHT, IMG_WIDTH), mode='constant', \n                                      preserve_range=True), axis=-1)\n        mask = np.maximum(mask, mask_)\n    Y_train[n] = mask\n\n# Get and resize test images\nX_test = np.zeros((len(test_ids), IMG_HEIGHT, IMG_WIDTH, IMG_CHANNELS), dtype=np.uint8)\nsizes_test = []\nprint('Getting and resizing test images ... ')\nsys.stdout.flush()\nfor n, id_ in tqdm(enumerate(test_ids), total=len(test_ids)):\n    path = TEST_PATH + id_\n    img = imread(path + '/images/' + id_ + '.png')[:,:,:IMG_CHANNELS]\n    sizes_test.append([img.shape[0], img.shape[1]])\n    img = resize(img, (IMG_HEIGHT, IMG_WIDTH), mode='constant', preserve_range=True)\n    X_test[n] = img\n\nprint('Done!')","execution_count":3,"outputs":[]},{"metadata":{"_cell_guid":"88829b53-50ce-45d9-9540-77dd7384ad4c","_uuid":"283af26f0860b7069bdfd133c746e5d20971542c","trusted":true},"cell_type":"code","source":"# Check if training data looks all right\nix = random.randint(0, len(train_ids))\nimshow(X_train[ix])\nplt.show()\nimshow(np.squeeze(Y_train[ix]))\nplt.show()\nlen(train_ids)","execution_count":4,"outputs":[]},{"metadata":{"_cell_guid":"c1df6f3a-d58f-434b-9216-ef7be38637d4","_uuid":"5abd38950ae99b60f8afec7656eb654a48d449fe","collapsed":true,"trusted":true},"cell_type":"code","source":"# Define IoU metric\ndef mean_iou(y_true, y_pred):\n    '''\n    prec = []\n    for t in np.arange(0.5, 1.0, 0.05):\n        y_pred_ = tf.to_int32(y_pred > t)\n        score, up_opt = tf.metrics.mean_iou(y_true, y_pred_, 2)\n        K.get_session().run(tf.local_variables_initializer())\n        with tf.control_dependencies([up_opt]):\n            score = tf.identity(score)\n        prec.append(score)\n    return K.mean(K.stack(prec), axis=0)\n    '''\n    prec = []\n    for t in np.arange(0.5, 1.0, 0.05):\n        y_pred_ = tf.to_int32(y_pred > t)\n        score, up_opt = tf.metrics.mean_iou(y_true, y_pred_, 2, y_true)\n        K.get_session().run(tf.local_variables_initializer())\n        with tf.control_dependencies([up_opt]):\n            score = tf.identity(score)\n        prec.append(score)\n    return K.mean(K.stack(prec), axis=0)","execution_count":5,"outputs":[]},{"metadata":{"_cell_guid":"c1dbc57c-b497-4ccb-b077-2053203ab7ed","_uuid":"0aa97d66c29f45dfac9b0f45fcf74ba0e778ba5d","scrolled":true,"trusted":true},"cell_type":"code","source":"# Build U-Net model\nfrom keras.applications import VGG16, DenseNet201\nvgg16_fl = \"../input/vgg16/vgg16_weights_tf_dim_ordering_tf_kernels_notop.h5\"\nvgg16 = VGG16(weights=vgg16_fl,#'imagenet',\n                      include_top=False,\n                      input_shape=(IMG_HEIGHT, IMG_WIDTH, IMG_CHANNELS))\n\ninputs = Input((IMG_HEIGHT, IMG_WIDTH, IMG_CHANNELS))\ns = Lambda(lambda x: x / 255) (inputs)\n\n#trick to use the layers for reconstruction\nll = {'in': s}\nlast = 'in'\nuse = ['block2_conv2', '']\nfor layer in vgg16.layers:\n    if layer.name != 'input_23':\n        ll[layer.name] = vgg16.get_layer(layer.name)(ll[last])\n        last = layer.name\n        print(layer.name)\n\nc1 = Conv2D(8, (3, 3), activation='elu', padding='same') (s)\nc1 = Conv2D(8, (3, 3), activation='elu', padding='same') (c1)\np1 = MaxPooling2D((2, 2)) (c1)#32\n\nc2 = Conv2D(16, (3, 3), activation='elu', padding='same') (p1)\nc2 = Conv2D(16, (3, 3), activation='elu', padding='same') (c2)\np2 = MaxPooling2D((2, 2)) (c2)\n\nc3 = Conv2D(32, (3, 3), activation='elu', padding='same') (p2)\nc3 = Conv2D(32, (3, 3), activation='elu', padding='same') (c3)\np3 = MaxPooling2D((2, 2)) (c3)\n\nc4 = Conv2D(64, (3, 3), activation='elu', padding='same') (p3)\nc4 = Conv2D(64, (3, 3), activation='elu', padding='same') (c4)\np4 = MaxPooling2D(pool_size=(2, 2)) (c4)\n\nc5 = Conv2D(128, (3, 3), activation='relu', padding='same') (p4)\nc5 = Conv2D(128, (3, 3), activation='relu', padding='same') (c5)\n\nu6 = Conv2DTranspose(64, (2, 2), strides=(2, 2), padding='same') (c5)\nu6 = concatenate([u6, c4, ll['block4_conv3']])\nc6 = Conv2D(64, (3, 3), activation='elu', padding='same') (u6)\nc6 = Conv2D(64, (3, 3), activation='elu', padding='same') (c6)\n\nu7 = Conv2DTranspose(32, (2, 2), strides=(2, 2), padding='same') (c6)\nu7 = concatenate([u7, c3,  ll['block3_conv3']])\nc7 = Conv2D(32, (3, 3), activation='elu', padding='same') (u7)\nc7 = Conv2D(32, (3, 3), activation='elu', padding='same') (c7)\n\nu8 = Conv2DTranspose(16, (2, 2), strides=(2, 2), padding='same') (c7)\nu8 = concatenate([u8, c2,  ll['block2_conv2']])\nc8 = Conv2D(16, (3, 3), activation='elu', padding='same') (u8)\nc8 = Conv2D(16, (3, 3), activation='elu', padding='same') (c8)\n\nu9 = Conv2DTranspose(8, (2, 2), strides=(2, 2), padding='same') (c8)\nu9 = concatenate([u9, c1, ll['block1_conv2']], axis=3)\nc9 = Conv2D(8, (3, 3), activation='elu', padding='same') (u9)\nc9 = Conv2D(8, (3, 3), activation='elu', padding='same') (c9)\n\noutputs = Conv2D(1, (1, 1), activation='sigmoid') (c9)\n\nmodel = Model(inputs=[inputs], outputs=[outputs])\nmodel.compile(optimizer='adam', loss='binary_crossentropy', metrics=[mean_iou])\nmodel.summary()","execution_count":null,"outputs":[]},{"metadata":{"_cell_guid":"9415b1c4-aa69-41b9-a1e3-d6053dbd4f64","_uuid":"c060db22daa2abf12b28240cd81bbcbf1ce1bf87","trusted":true},"cell_type":"code","source":"# Fit model\nearlystopper = EarlyStopping(patience=5, verbose=1)\ncheckpointer = ModelCheckpoint('model-dsbowl2018-1.h5', verbose=1, save_best_only=True)\nresults = model.fit(X_train, Y_train, validation_split=0.1, batch_size=8, epochs=30, \n                    callbacks=[earlystopper, checkpointer])","execution_count":null,"outputs":[]},{"metadata":{"_cell_guid":"2daa48d5-ac98-4e18-af3f-a582baaa44f0","_uuid":"f841760b4abca1a25cb750822f88268bd79bf2ce","collapsed":true,"trusted":true},"cell_type":"code","source":"# Predict on train, val and test\nmodel.load_weights('model-dsbowl2018-1.h5')#model = load_model('model-dsbowl2018-1.h5', custom_objects={'mean_iou': mean_iou})\npreds_train = model.predict(X_train[:int(X_train.shape[0]*0.9)], verbose=1)\npreds_val = model.predict(X_train[int(X_train.shape[0]*0.9):], verbose=1)\npreds_test = model.predict(X_test, verbose=1)\n\n# Threshold predictions\npreds_train_t = (preds_train > 0.5).astype(np.uint8)\npreds_val_t = (preds_val > 0.5).astype(np.uint8)\npreds_test_t = (preds_test > 0.5).astype(np.uint8)\n\n# Create list of upsampled test masks\npreds_test_upsampled = []\nfor i in range(len(preds_test)):\n    preds_test_upsampled.append(resize(np.squeeze(preds_test[i]), \n                                       (sizes_test[i][0], sizes_test[i][1]), \n                                       mode='constant', preserve_range=True))","execution_count":null,"outputs":[]},{"metadata":{"_cell_guid":"649248cd-a1fb-4da6-ade2-4bebad44bcab","_uuid":"7e06242a50870e07a080064a4912b761775990fa","collapsed":true,"trusted":true},"cell_type":"code","source":"# Perform a sanity check on some random training samples\nix = random.randint(0, len(preds_train_t))\nimshow(X_train[ix])\nplt.show()\nimshow(np.squeeze(Y_train[ix]))\nplt.show()\nimshow(np.squeeze(preds_train_t[ix]))\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{"_cell_guid":"4f66b75c-c694-41a1-8c91-34bb6595837b","_uuid":"d4ccbb559375bc2777ffb692a20adc313159f2cc","collapsed":true,"trusted":true},"cell_type":"code","source":"# Perform a sanity check on some random validation samples\nix = random.randint(0, len(preds_val_t))\nimshow(X_train[int(X_train.shape[0]*0.9):][ix])\nplt.show()\nimshow(np.squeeze(Y_train[int(Y_train.shape[0]*0.9):][ix]))\nplt.show()\nimshow(np.squeeze(preds_val_t[ix]))\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{"_cell_guid":"59a0af60-a7d7-41ef-a6fe-9e3c72defa07","_uuid":"4f99c1bf852e82b60bd4f982ca0df293f712cdf0","collapsed":true,"trusted":true},"cell_type":"code","source":"# Run-length encoding stolen from https://www.kaggle.com/rakhlin/fast-run-length-encoding-python\ndef rle_encoding(x):\n    dots = np.where(x.T.flatten() == 1)[0]\n    run_lengths = []\n    prev = -2\n    for b in dots:\n        if (b>prev+1): run_lengths.extend((b + 1, 0))\n        run_lengths[-1] += 1\n        prev = b\n    return run_lengths\n\ndef prob_to_rles(x, cutoff=0.5):\n    lab_img = label(x > cutoff)\n    for i in range(1, lab_img.max() + 1):\n        yield rle_encoding(lab_img == i)","execution_count":null,"outputs":[]},{"metadata":{"_cell_guid":"22fe24a1-7659-4cc9-9d23-211f38e5b99f","_uuid":"089587843ed6a3955fdcb9b23a6ec3bf5d703688","collapsed":true,"trusted":true},"cell_type":"code","source":"new_test_ids = []\nrles = []\nfor n, id_ in enumerate(test_ids):\n    rle = list(prob_to_rles(preds_test_upsampled[n]))\n    rles.extend(rle)\n    new_test_ids.extend([id_] * len(rle))","execution_count":null,"outputs":[]},{"metadata":{"_cell_guid":"1ba0ee3a-cca0-4349-83f6-09a1ac6fcb44","_uuid":"ba589f56f5be1e6886bc88f5bf9e7d0a408e4048","collapsed":true,"trusted":true},"cell_type":"code","source":"# Create submission DataFrame\nsub = pd.DataFrame()\nsub['ImageId'] = new_test_ids\nsub['EncodedPixels'] = pd.Series(rles).apply(lambda x: ' '.join(str(y) for y in x))\nsub.to_csv('sub-dsbowl2018-1.csv', index=False)","execution_count":null,"outputs":[]},{"metadata":{"_cell_guid":"3f5e5a47-6133-4870-976a-a8e4fa7bf46c","_uuid":"2a83eab66bf55194f300953bea5534b6a043130f","collapsed":true,"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]}],"metadata":{"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.4"}},"nbformat":4,"nbformat_minor":1}