{"cells":[{"metadata":{},"cell_type":"markdown","source":"# **Overview**\nReferred to the following notebook: https://www.kaggle.com/hmendonca/u-net-model-with-submission"},{"metadata":{"_uuid":"a6cd9d5ad61ffe3b8858769f20a5f9493f024a56"},"cell_type":"markdown","source":"## Model Parameters\nWe might want to adjust these later (or do some hyperparameter optimizations)"},{"metadata":{"trusted":true,"_uuid":"301a5d939c566d1487a049bb2554d09b592b18b1"},"cell_type":"code","source":"BATCH_SIZE = 90\n# number of validation images to use\nVALID_IMG_COUNT = 900\n# maximum number of steps_per_epoch in training\nMAX_TRAIN_STEPS = 9\n# maximum number of epochs for training\nMAX_TRAIN_EPOCHS = 30","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"import os\nimport cv2\nimport numpy as np \nimport pandas as pd \nfrom skimage.io import imread\nimport matplotlib.pyplot as plt\nfrom matplotlib.cm import get_cmap\nfrom skimage.segmentation import mark_boundaries\nfrom skimage.measure import label, regionprops\nfrom skimage.util import montage\nfrom skimage.morphology import binary_opening, disk, label\nimport gc; gc.enable() # for memory management in Kaggle\n\nmontage_rgb = lambda x: np.stack([montage(x[:, :, :, i]) for i in range(x.shape[3])], -1)\nship_dir = '../input'\ntrain_image_dir = os.path.join(ship_dir, 'train_v2')\ntest_image_dir = os.path.join(ship_dir, 'test_v2')\n\ndef multi_rle_encode(img, **kwargs):\n    '''\n    Encode connected regions as separated masks\n    '''\n    labels = label(img)\n    if img.ndim > 2:\n        return [rle_encode(np.sum(labels==k, axis=2), **kwargs) for k in np.unique(labels[labels>0])]\n    else:\n        return [rle_encode(labels==k, **kwargs) for k in np.unique(labels[labels>0])]\n\ndef rle_encode(img, min_max_threshold=1e-3, max_mean_threshold=None):\n    '''\n    img: numpy array, 1 - mask, 0 - background\n    Returns run length as string formated\n    '''\n    if np.max(img) < min_max_threshold:\n        return '' \n    if max_mean_threshold and np.mean(img) > max_mean_threshold:\n        return '' \n    pixels = img.T.flatten()\n    pixels = np.concatenate([[0], pixels, [0]])\n    runs = np.where(pixels[1:] != pixels[:-1])[0] + 1\n    runs[1::2] -= runs[::2]\n    return ' '.join(str(x) for x in runs)\n\ndef rle_decode(mask_rle, shape=(768, 768)):\n    '''\n    mask_rle: run-length as string formated (start length)\n    shape: (height,width) of array to return \n    Returns numpy array, 1 - mask, 0 - background\n    '''\n    s = mask_rle.split()\n    starts, lengths = [np.asarray(x, dtype=int) for x in (s[0:][::2], s[1:][::2])]\n    starts -= 1\n    ends = starts + lengths\n    img = np.zeros(shape[0]*shape[1], dtype=np.uint8)\n    for lo, hi in zip(starts, ends):\n        img[lo:hi] = 1\n    return img.reshape(shape).T         # Needed to align to RLE direction\n\ndef masks_as_image(in_mask_list):\n    # Take the individual ship masks and create a single mask array for all ships\n    all_masks = np.zeros((768, 768), dtype = np.uint8)\n    for mask in in_mask_list:\n        if isinstance(mask, str):\n            all_masks |= rle_decode(mask)\n    return all_masks\n\ndef masks_as_color(in_mask_list):\n    # Take the individual ship masks and create a color mask array for each ships\n    all_masks = np.zeros((768, 768), dtype = np.float)\n    scale = lambda x: (len(in_mask_list)+x+1) / (len(in_mask_list)*2) ## scale the heatmap image to shift \n    for i,mask in enumerate(in_mask_list):\n        if isinstance(mask, str):\n            all_masks[:,:] += scale(i) * rle_decode(mask)\n    return all_masks","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"3ca7119188fbb4c6540d9df55f5833b55435287e"},"cell_type":"code","source":"masks = pd.read_csv(os.path.join('../input/', 'train_ship_segmentations_v2.csv'))\nnot_empty = pd.notna(masks.EncodedPixels)\nprint(not_empty.sum(), 'masks in', masks[not_empty].ImageId.nunique(), 'images')\nprint((~not_empty).sum(), 'empty images in', masks.ImageId.nunique(), 'total images')\nmasks.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"0081fd6f387abd7c05eb35f29575a2ee6ddc2236"},"cell_type":"code","source":"fig, (ax1, ax2, ax3, ax4) = plt.subplots(1, 4, figsize = (16, 5))\nrle_0 = masks.query('ImageId==\"00021ddc3.jpg\"')['EncodedPixels']\nimg_0 = masks_as_image(rle_0)\nax1.imshow(img_0)\nax1.set_title('Mask as image')\nrle_1 = multi_rle_encode(img_0)\nimg_1 = masks_as_image(rle_1)\nax2.imshow(img_1)\nax2.set_title('Re-encoded')\nimg_c = masks_as_color(rle_0)\nax3.imshow(img_c)\nax3.set_title('Masks in colors')\nimg_c = masks_as_color(rle_1)\nax4.imshow(img_c)\nax4.set_title('Re-encoded in colors')\nprint('Check Decoding->Encoding',\n      'RLE_0:', len(rle_0), '->',\n      'RLE_1:', len(rle_1))\nprint(np.sum(img_0 - img_1), 'error')","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"40cb72e241c0c3d8bc245b4e3c663b4a835b0011"},"cell_type":"markdown","source":"# Split into training and validation groups\nWe stratify by the number of boats appearing so we have nice balances in each set"},{"metadata":{"trusted":true,"_uuid":"c4f008bf6898518fd371de013418f936edaa09f8"},"cell_type":"code","source":"masks['ships'] = masks['EncodedPixels'].map(lambda c_row: 1 if isinstance(c_row, str) else 0)\nunique_img_ids = masks.groupby('ImageId').agg({'ships': 'sum'}).reset_index()\nunique_img_ids['has_ship'] = unique_img_ids['ships'].map(lambda x: 1.0 if x>0 else 0.0)\nunique_img_ids['has_ship_vec'] = unique_img_ids['has_ship'].map(lambda x: [x])\n# some files are too small/corrupt\nunique_img_ids['file_size_kb'] = unique_img_ids['ImageId'].map(lambda c_img_id: \n                                                               os.stat(os.path.join(train_image_dir, \n                                                                                    c_img_id)).st_size/1024)\nunique_img_ids = unique_img_ids[unique_img_ids['file_size_kb'] > 50] # image files less than 50kb will be corrupt  \nunique_img_ids['file_size_kb'].hist()\nmasks.drop(['ships'], axis=1, inplace=True)\nunique_img_ids.sample(7)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"c21d5bff04bf9180463969ac120379345745ed03"},"cell_type":"markdown","source":"### Examine Number of Ship Images\nHere we examine how often ships appear and replace the ones without any ships with 0"},{"metadata":{"trusted":true,"_uuid":"2612fa47c7e9fdcaa7aa720c4e15fc86fd65d69a"},"cell_type":"code","source":"unique_img_ids['ships'].hist(bins=unique_img_ids['ships'].max())","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"ef8115a80749ac47f295e9a70217a5553970c2b3"},"cell_type":"markdown","source":"# Undersample Empty Images\nHere we undersample the empty images to get a better balanced group with more ships to try and segment"},{"metadata":{"trusted":true,"_uuid":"0cf0bb261eda957cb0a12a330260e1390c57c8c9"},"cell_type":"code","source":"SAMPLES_PER_GROUP = 2000\nbalanced_train_df = unique_img_ids.groupby('ships').apply(lambda x: x.sample(SAMPLES_PER_GROUP) if len(x) > SAMPLES_PER_GROUP else x)\nbalanced_train_df['ships'].hist(bins=balanced_train_df['ships'].max()+1)\nprint(balanced_train_df.shape[0], 'masks')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"a26cd030942c2cd763c6fcd08b370f886c93ecdf"},"cell_type":"code","source":"from sklearn.model_selection import train_test_split\ntrain_ids, valid_ids = train_test_split(balanced_train_df, \n                 test_size = 0.2, \n                 stratify = balanced_train_df['ships'])\ntrain_df = pd.merge(masks, train_ids)\nvalid_df = pd.merge(masks, valid_ids)\nprint(train_df.shape[0], 'training masks')\nprint(valid_df.shape[0], 'validation masks')","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"a3fb9fe33d81374c7bd836f5bc86a1df89190805"},"cell_type":"markdown","source":"# Decode all the RLEs into Images\nWe make a generator to produce batches of images"},{"metadata":{"trusted":true,"_uuid":"6181ac51577e5636995e38a9e29311cf47f513ca"},"cell_type":"code","source":"def make_image_gen(in_df, batch_size = BATCH_SIZE):\n    all_batches = list(in_df.groupby('ImageId'))\n    out_rgb = []\n    out_mask = []\n    while True:\n        np.random.shuffle(all_batches)\n        for c_img_id, c_masks in all_batches:\n            rgb_path = os.path.join(train_image_dir, c_img_id)\n            c_img = imread(rgb_path)\n            c_mask = np.expand_dims(masks_as_image(c_masks['EncodedPixels'].values), -1)\n            c_img = c_img[::3, ::3]\n            c_mask = c_mask[::3, ::3]\n            out_rgb += [c_img]\n            out_mask += [c_mask]\n            if len(out_rgb)>=batch_size:\n                yield np.stack(out_rgb, 0)/255.0, np.stack(out_mask, 0)\n                out_rgb, out_mask=[], []","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"1983738da75b031f2bec8ba36db01c095e7c5d59"},"cell_type":"code","source":"train_gen = make_image_gen(train_df)\ntrain_x, train_y = next(train_gen)\nprint('x', train_x.shape, train_x.min(), train_x.max())\nprint('y', train_y.shape, train_y.min(), train_y.max())","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"b4396cd28ddd2e4c8076fcb165e9b61e3baeeeb7"},"cell_type":"code","source":"fig, (ax1, ax2, ax3) = plt.subplots(1, 3, figsize = (30, 10))\nbatch_rgb = montage_rgb(train_x)\nbatch_seg = montage(train_y[:, :, :, 0])\nax1.imshow(batch_rgb)\nax1.set_title('Images')\nax2.imshow(batch_seg)\nax2.set_title('Segmentations')\nax3.imshow(mark_boundaries(batch_rgb, \n                           batch_seg.astype(int)))\nax3.set_title('Outlined Ships')\nfig.savefig('overview.png')","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"8f47639c987a10ebcb53e51f55aa8a11c98fa860"},"cell_type":"markdown","source":"# Make the Validation Set"},{"metadata":{"trusted":true,"_uuid":"30cb02a2a7103a9d66e90f701991199de1e5b73e"},"cell_type":"code","source":"%%time\nvalid_x, valid_y = next(make_image_gen(valid_df, VALID_IMG_COUNT))\nprint(valid_x.shape, valid_y.shape)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"a8f65e7942816fb75b687a549dc1d5cc48d00e21"},"cell_type":"markdown","source":"# Augment Data"},{"metadata":{"_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","trusted":true},"cell_type":"code","source":"from keras.preprocessing.image import ImageDataGenerator\ndg_args = dict(featurewise_center = False, \n                  samplewise_center = False,\n                  rotation_range = 45, \n                  width_shift_range = 0.1, \n                  height_shift_range = 0.1, \n                  shear_range = 0.01,\n                  zoom_range = [0.9, 1.25],  \n                  horizontal_flip = True, \n                  vertical_flip = True,\n                  fill_mode = 'reflect',\n                   data_format = 'channels_last')\n\nimage_gen = ImageDataGenerator(**dg_args)\nlabel_gen = ImageDataGenerator(**dg_args)\n\ndef create_aug_gen(in_gen, seed = None):\n    np.random.seed(seed if seed is not None else np.random.choice(range(9999)))\n    for in_x, in_y in in_gen:\n        seed = np.random.choice(range(9999))\n        # keep the seeds syncronized otherwise the augmentation to the images is different from the masks\n        g_x = image_gen.flow(255*in_x, \n                             batch_size = in_x.shape[0], \n                             seed = seed, \n                             shuffle=True)\n        g_y = label_gen.flow(in_y, \n                             batch_size = in_x.shape[0], \n                             seed = seed, \n                             shuffle=True)\n\n        yield next(g_x)/255.0, next(g_y)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"6122ccb9e58bfac6fa5e11c86121e78d9e5151b1"},"cell_type":"code","source":"cur_gen = create_aug_gen(train_gen)\nt_x, t_y = next(cur_gen)\nprint('x', t_x.shape, t_x.dtype, t_x.min(), t_x.max())\nprint('y', t_y.shape, t_y.dtype, t_y.min(), t_y.max())\n# only keep first 9 samples to examine in detail\nt_x = t_x[:9]\nt_y = t_y[:9]\nfig, (ax1, ax2) = plt.subplots(1, 2, figsize = (20, 10))\nax1.imshow(montage_rgb(t_x), cmap='gray')\nax1.set_title('images')\nax2.imshow(montage(t_y[:, :, :, 0]), cmap='gray_r')\nax2.set_title('ships')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"33300c4f03b6600da7b418f775d11d7ebf76a35a"},"cell_type":"code","source":"gc.collect()","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"ba08494eb9736ec3556b7c879143cdcdea89febf"},"cell_type":"markdown","source":"# Build a Model\nHere we use a slight deviation on the U-Net standard"},{"metadata":{"trusted":true,"_uuid":"2687377309d3cbbab1197f4eccd2b50ab996f5a6"},"cell_type":"code","source":"from keras import models, layers\n# Build U-Net model\ndef upsample_simple(filters, kernel_size, strides, padding):\n    return layers.UpSampling2D(strides)\n\nupsample=upsample_simple\n    \ninput_img = layers.Input(t_x.shape[1:], name = 'RGB_Input')\npp_in_layer = input_img\n\npp_in_layer = layers.AvgPool2D((1, 1))(pp_in_layer)\n    \npp_in_layer = layers.GaussianNoise(0.1)(pp_in_layer)\npp_in_layer = layers.BatchNormalization()(pp_in_layer)\n\nc1 = layers.Conv2D(8, (3, 3), activation='relu', padding='same') (pp_in_layer)\nc1 = layers.Conv2D(8, (3, 3), activation='relu', padding='same') (c1)\np1 = layers.MaxPooling2D((2, 2)) (c1)\n\nc2 = layers.Conv2D(16, (3, 3), activation='relu', padding='same') (p1)\nc2 = layers.Conv2D(16, (3, 3), activation='relu', padding='same') (c2)\np2 = layers.MaxPooling2D((2, 2)) (c2)\n\nc3 = layers.Conv2D(32, (3, 3), activation='relu', padding='same') (p2)\nc3 = layers.Conv2D(32, (3, 3), activation='relu', padding='same') (c3)\np3 = layers.MaxPooling2D((2, 2)) (c3)\n\nc4 = layers.Conv2D(64, (3, 3), activation='relu', padding='same') (p3)\nc4 = layers.Conv2D(64, (3, 3), activation='relu', padding='same') (c4)\np4 = layers.MaxPooling2D(pool_size=(2, 2)) (c4)\n\n\nc5 = layers.Conv2D(128, (3, 3), activation='relu', padding='same') (p4)\nc5 = layers.Conv2D(128, (3, 3), activation='relu', padding='same') (c5)\n\nu6 = upsample(64, (2, 2), strides=(2, 2), padding='same') (c5)\nu6 = layers.concatenate([u6, c4])\nc6 = layers.Conv2D(64, (3, 3), activation='relu', padding='same') (u6)\nc6 = layers.Conv2D(64, (3, 3), activation='relu', padding='same') (c6)\n\nu7 = upsample(32, (2, 2), strides=(2, 2), padding='same') (c6)\nu7 = layers.concatenate([u7, c3])\nc7 = layers.Conv2D(32, (3, 3), activation='relu', padding='same') (u7)\nc7 = layers.Conv2D(32, (3, 3), activation='relu', padding='same') (c7)\n\nu8 = upsample(16, (2, 2), strides=(2, 2), padding='same') (c7)\nu8 = layers.concatenate([u8, c2])\nc8 = layers.Conv2D(16, (3, 3), activation='relu', padding='same') (u8)\nc8 = layers.Conv2D(16, (3, 3), activation='relu', padding='same') (c8)\n\nu9 = upsample(8, (2, 2), strides=(2, 2), padding='same') (c8)\nu9 = layers.concatenate([u9, c1], axis=3)\nc9 = layers.Conv2D(8, (3, 3), activation='relu', padding='same') (u9)\nc9 = layers.Conv2D(8, (3, 3), activation='relu', padding='same') (c9)\n\nd = layers.Conv2D(1, (1, 1), activation='sigmoid') (c9)\nd = layers.UpSampling2D((1, 1))(d)\n\nseg_model = models.Model(inputs=[input_img], outputs=[d])\nseg_model.summary()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"1678069aa8013510264ba898291c6ae2dce88a76"},"cell_type":"code","source":"import keras.backend as K\nfrom keras.optimizers import Adam\nfrom keras.losses import binary_crossentropy\n\n## intersection over union\ndef IoU(y_true, y_pred, eps=1e-6):\n    if np.max(y_true) == 0.0:\n        return IoU(1-y_true, 1-y_pred)                    ## empty image; calc IoU of zeros\n    intersection = K.sum(y_true * y_pred, axis=[1,2,3])\n    union = K.sum(y_true, axis=[1,2,3]) + K.sum(y_pred, axis=[1,2,3]) - intersection\n    return -K.mean( (intersection + eps) / (union + eps), axis=0)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"7282d18de3aff1cee12ff89b7d511a391702814f"},"cell_type":"code","source":"from keras.callbacks import ModelCheckpoint, EarlyStopping, ReduceLROnPlateau\nweight_path=\"{}_weights.best.hdf5\".format('seg_model')\n\ncheckpoint = ModelCheckpoint(weight_path, monitor='val_loss', verbose=1, save_best_only=True, mode='min', save_weights_only=True)\n\nreduceLROnPlat = ReduceLROnPlateau(monitor='val_loss', factor=0.33,\n                                   patience=1, verbose=1, mode='min',\n                                   min_delta=0.0001, cooldown=0, min_lr=1e-8)\n\nearly = EarlyStopping(monitor=\"val_loss\", mode=\"min\", verbose=2,\n                      patience=10) # since kaggle time is limited, we are limiting the patience to 10\n\ncallbacks_list = [checkpoint, early, reduceLROnPlat]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"5b67d808c0b8c7e28bff41e6d3858ff6f09dd626","scrolled":false},"cell_type":"code","source":"def fit():\n    seg_model.compile(optimizer=Adam(1e-3, decay=1e-6), loss=IoU, metrics=['binary_accuracy'])\n    \n    step_count = min(MAX_TRAIN_STEPS, train_df.shape[0]//BATCH_SIZE)\n    aug_gen = create_aug_gen(make_image_gen(train_df))\n    loss_history = [seg_model.fit_generator(aug_gen,\n                                 steps_per_epoch=step_count,\n                                 epochs=MAX_TRAIN_EPOCHS,\n                                 validation_data=(valid_x, valid_y),\n                                 callbacks=callbacks_list,\n                                workers=1 \n                                           )]\n    return loss_history\n\nloss_history = fit()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"a168c8b1af446b800f6129104906003ededd61c4"},"cell_type":"code","source":"def show_loss(loss_history):\n    epochs = np.concatenate([mh.epoch for mh in loss_history])\n    fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(22, 10))\n    \n    _ = ax1.plot(epochs, np.concatenate([mh.history['loss'] for mh in loss_history]), 'b-',\n                 epochs, np.concatenate([mh.history['val_loss'] for mh in loss_history]), 'r-')\n    ax1.legend(['Training', 'Validation'])\n    ax1.set_title('Loss')\n    \n    _ = ax2.plot(epochs, np.concatenate([mh.history['binary_accuracy'] for mh in loss_history]), 'b-',\n                 epochs, np.concatenate([mh.history['val_binary_accuracy'] for mh in loss_history]), 'r-')\n    ax2.legend(['Training', 'Validation'])\n    ax2.set_title('Binary Accuracy (%)')\n\nshow_loss(loss_history)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"ce1167e9f09200f537e61f93f486168a13be1711"},"cell_type":"code","source":"seg_model.load_weights(weight_path)\nseg_model.save('seg_model.h5')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"275b411dc97a350aacaba46c8562efcf2658b1a7"},"cell_type":"code","source":"pred_y = seg_model.predict(valid_x)\nprint(pred_y.shape, pred_y.min(axis=0).max(), pred_y.max(axis=0).min(), pred_y.mean())","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"0018ab172d18936f8cc2c5df33d2f840dc16bf4f"},"cell_type":"markdown","source":"# Prepare Full Resolution Model\nHere we account for the scaling so everything can happen in the model itself"},{"metadata":{"trusted":true,"_uuid":"17408f0ee8dc16149b8eff0447a1427ab3ed82ba"},"cell_type":"code","source":"fullres_model = models.Sequential()\nfullres_model.add(layers.AvgPool2D((3, 3), input_shape = (None, None, 3)))\nfullres_model.add(seg_model)\nfullres_model.add(layers.UpSampling2D((3, 3)))\nfullres_model.save('fullres_model.h5')","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"17edb177402ae51651692511827a7e9d60646533"},"cell_type":"markdown","source":"# Visualize predictions"},{"metadata":{"trusted":true,"_uuid":"e2c9ede3ab20bd7bfdd89c4fd18f09552cb4f5cb"},"cell_type":"code","source":"def raw_prediction(img, path=test_image_dir):\n    c_img = imread(os.path.join(path, c_img_name))\n    c_img = np.expand_dims(c_img, 0)/255.0\n    cur_seg = fullres_model.predict(c_img)[0]\n    return cur_seg, c_img[0]\n\ndef smooth(cur_seg):\n    return binary_opening(cur_seg>0.99, np.expand_dims(disk(2), -1))\n\ndef predict(img, path=test_image_dir):\n    cur_seg, c_img = raw_prediction(img, path=path)\n    return smooth(cur_seg), c_img\n\n## To \nsamples = valid_df.groupby('ships').apply(lambda x: x.sample(1))\nfig, m_axs = plt.subplots(samples.shape[0], 4, figsize = (15, samples.shape[0]*4))\n[c_ax.axis('off') for c_ax in m_axs.flatten()]\n\nfor (ax1, ax2, ax3, ax4), c_img_name in zip(m_axs, samples.ImageId.values):\n    first_seg, first_img = raw_prediction(c_img_name, train_image_dir)\n    ax1.imshow(first_img)\n    ax1.set_title('Image: ' + c_img_name)\n    ax2.imshow(first_seg[:, :, 0], cmap=get_cmap('jet'))\n    ax2.set_title('Model Prediction')\n    reencoded = masks_as_color(multi_rle_encode(smooth(first_seg)[:, :, 0]))\n    ax3.imshow(reencoded)\n    ax3.set_title('Prediction Masks')\n    ground_truth = masks_as_color(masks.query('ImageId==\"{}\"'.format(c_img_name))['EncodedPixels'])\n    ax4.imshow(ground_truth)\n    ax4.set_title('Ground Truth')\n    \nfig.savefig('validation.png')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"collapsed":true,"_uuid":"11a6c6615131ff8c317f95a5097b46565ef21121"},"cell_type":"markdown","source":"# Predictions"},{"metadata":{"trusted":true,"_uuid":"2671f602b571b70ad2bda613cbfad21c5fa5c160"},"cell_type":"code","source":"test_paths = np.array(os.listdir(test_image_dir))\nprint(len(test_paths), 'test images found')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"11341f4037a3c44391877d35eb6704590c7e914e"},"cell_type":"code","source":"# Predicting masks for the test images\n\nfrom tqdm import tqdm_notebook\n\ndef pred_encode(img, **kwargs):\n    cur_seg, _ = predict(img)\n    cur_rles = multi_rle_encode(cur_seg, **kwargs)\n    return [[img, rle] for rle in cur_rles if rle is not None]\n\nout_pred_rows = []\nfor c_img_name in tqdm_notebook(test_paths): \n    out_pred_rows += pred_encode(c_img_name, min_max_threshold=1.0)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"d569785624983fec2067b77f2d8d1fa1f1ac8da5"},"cell_type":"code","source":"# Encoded Pixels of the test images\n\npred = pd.DataFrame(out_pred_rows)\npred.columns = ['ImageId', 'EncodedPixels']\npred = pred[pred.EncodedPixels.notnull()]\npred.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"4b1be5a92a4fa7c5842757a7702ca1c3543c6f2c"},"cell_type":"code","source":"## Displaying masks of the predicted ships\n\nfig, m_axs = plt.subplots(10, 2, figsize = (9, 50))\n[c_ax.axis('off') for c_ax in m_axs.flatten()]\n\nfor (ax1, ax2), c_img_name in zip(m_axs, pred.ImageId.unique()[:10]):\n    c_img = imread(os.path.join(test_image_dir, c_img_name))\n    c_img = np.expand_dims(c_img, 0)/255.0\n    ax1.imshow(c_img[0])\n    ax1.set_title('Image: ' + c_img_name)\n    ax2.imshow(masks_as_color(pred.query('ImageId==\"{}\"'.format(c_img_name))['EncodedPixels']))\n    ax2.set_title('Prediction')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"pred_with_ship = pred.ImageId[pred.EncodedPixels.isnull()==False]\npred_with_ship = np.unique(pred_with_ship.values)\nprint('There are ' +str(len(pred_with_ship)) + ' image files with masks')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]}],"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat":4,"nbformat_minor":4}