{"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_minor":4,"nbformat":4,"cells":[{"cell_type":"code","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\n\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n\n# Input data files are available in the read-only \"../input/\" directory\n# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory\n\nimport os\nfor dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n        print(os.path.join(dirname, filename))\n\n# You can write up to 20GB to the current directory (/kaggle/working/) that gets preserved as output when you create a version using \"Save & Run All\" \n# You can also write temporary files to /kaggle/temp/, but they won't be saved outside of the current session","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import os\nimport tensorflow as tf\nimport pandas as pd\nimport numpy as np\nimport matplotlib.pyplot as plt\nfrom matplotlib.pyplot import imread\n\nimport tensorflow as tf\nfrom tensorflow import keras\nfrom tensorflow.keras import Model, Sequential","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Data Preparation","metadata":{}},{"cell_type":"code","source":"from pathlib import Path\nimport zipfile\n\ntrain_zip_path = '../input/carvana-image-masking-challenge/train.zip'\nmasks_zip_path = '../input/carvana-image-masking-challenge/train_masks.zip'\ntest_zip_path = '../input/carvana-image-masking-challenge/test.zip'\n\nif not Path('/kaggle/working/train').exists():\n    with zipfile.ZipFile(train_zip_path,'r') as z:\n        z.extractall('/kaggle/working')\nif not Path('/kaggle/working/train_masks').exists():\n    with zipfile.ZipFile(masks_zip_path,'r') as z:\n        z.extractall('/kaggle/working')\nif not Path('/kaggle/working/test').exists():\n    pass\n    # with zipfile.ZipFile(test_zip_path,'r') as z:\n    #    z.extractall('/kaggle/working')","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(\"train set:  \", len(os.listdir(\"/kaggle/working/train\")))\nprint(\"train masks:\", len(os.listdir(\"/kaggle/working/train_masks\")))","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from glob import glob\n\nroot_dir = \"/kaggle/working\"\ntrain_path = os.path.join(root_dir, \"train\")\ntrain_masks_path = os.path.join(root_dir, \"train_masks\")\n#test_path = os.path.join(root_dir, \"test\")\n\ntrain_filepaths = glob(os.path.join(train_path, \"*.jpg\"))\ntrain_masks_filepaths = glob(os.path.join(train_masks_path, \"*.gif\"))\n#test_filepaths = glob(os.path.join(test_path, \"*.jpg\"))\n\n# Get unique ids of images\ndef get_root_name(filepaths):\n    file_names = [os.path.basename(filepath) for filepath in filepaths]\n    root_name = [name.split(\"_\")[0] for name in file_names]\n    return root_name\n\nall_train_ids = set(get_root_name(train_filepaths))\nall_train_masks_ids = set(get_root_name(train_masks_filepaths))\n#all_test_ids = set(get_root_name(test_filepaths))","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def display_images():\n    plt.figure(figsize=(15, 25))\n    title = ['Input Image', 'Mask']\n\n    for i in range(0, 4, 2):\n        plt.subplot(5, 2, i+1)\n        plt.title(title[0])\n        path_img = root_dir + \"/train/\" + list(all_train_ids)[i] + f\"_0{i+1}.jpg\"\n        plt.imshow(imread(path_img))\n        plt.axis(\"off\")\n\n        plt.subplot(5, 2, i+2)\n        plt.title(title[1])\n        path_mask_img = root_dir + \"/train_masks/\" + list(all_train_ids)[i] + f\"_0{i+1}_mask.gif\"\n        plt.imshow(imread(path_mask_img))\n        plt.axis(\"off\")\n    plt.show()\n\ndisplay_images()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def get_image_id(path):\n    return os.path.splitext(os.path.basename(path))[0]\n\ndf = pd.DataFrame(dict(image_path=train_filepaths))\ndf['image_id'] = df['image_path'].map(lambda path: get_image_id(path))\ndf['mask_path'] = df['image_path'].map(\n    lambda x: x.replace('train', 'train_masks').replace('.jpg', '_mask.gif'))\ndf['car_id'] = df['image_id'].map(lambda img_id: img_id.split('_')[0])","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from sklearn.model_selection import train_test_split\n\ndef split_data(ids, col=\"car_id\"):\n    train_ids, valid_ids = train_test_split(ids, random_state=42, test_size=.2)\n    valid_ids, test_ids = train_test_split(valid_ids, random_state=42, test_size=.5)\n    train_df = df[df[col].isin(train_ids)]\n    valid_df = df[df[col].isin(valid_ids)]\n    test_df = df[df[col].isin(test_ids)]\n    return train_df, valid_df, test_df\n\ntrain_df, valid_df, test_df = split_data(list(all_train_ids))\nprint(\"train_df: \", train_df.shape[0])\nprint(\"valid_df: \", valid_df.shape[0])\nprint(\"test_df:  \", test_df.shape[0])","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from tensorflow.image import stateless_random_crop, stateless_random_brightness\n\nIMG_SIZE = [512, 512]\nrng = tf.random.Generator.from_seed(1)\n\ndef decode(path):\n    img = tf.io.read_file(path) \n    img = tf.image.decode_jpeg(img, channels=3)\n    img = tf.image.resize(img, IMG_SIZE)\n    img = img / 255.0\n    return img\n\n@tf.function\ndef preprocess(image_path, mask_path):\n    image = decode(image_path)\n    mask = decode(mask_path)\n    mask = mask[:, :, :1] # take one channel\n    return image, mask\n\n@tf.function\ndef data_augmentation(image, mask):\n    if rng.uniform(()) > 0.5: \n        image = tf.image.flip_left_right(image)\n        mask = tf.image.flip_left_right(mask)\n\n    seed = rng.make_seeds(2)[0]\n    image = stateless_random_brightness(image, max_delta=0.1, seed=seed)\n    return image, mask\n\ndef make_dataset(df, shuffle=False, augment=False, batch_size=16, buffer_size=1000):\n    ds = tf.data.Dataset.from_tensor_slices((df[\"image_path\"].values, df[\"mask_path\"].values))\n    ds = ds.map(preprocess, num_parallel_calls=5)\n    if shuffle:\n        ds = ds.shuffle(buffer_size)\n    if augment:\n        ds = ds.map(data_augmentation, num_parallel_calls=tf.data.AUTOTUNE)\n    ds = ds.batch(batch_size)\n    return ds.prefetch(1)\n\ntrain_data = make_dataset(train_df, shuffle=True, augment=True)\nvalid_data = make_dataset(valid_df)\ntest_data = make_dataset(test_df)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_data","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**Deleting unused dataframe to free memory**","metadata":{}},{"cell_type":"code","source":"del df\ndel train_df\ndel valid_df\ndel test_df","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import tensorflow as tf","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"IMG_SIZE = [512, 512]","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Building Model ","metadata":{}},{"cell_type":"code","source":"def upsample(filters, size, strides):\n    \"\"\"Upsample the input\"\"\"\n\n    initializer = tf.random_normal_initializer(0., 0.02)\n\n    result = Sequential()\n    result.add(tf.keras.layers.Conv2DTranspose(filters, size, strides=strides,\n                                      padding=\"same\",\n                                      kernel_initializer=initializer,\n                                      use_bias=False))\n    result.add(tf.keras.layers.BatchNormalization())\n   \n    result.add(tf.keras.layers.ReLU())\n    return result","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from tensorflow.keras.applications import VGG19\n\nbase_model = VGG19(input_shape=IMG_SIZE + [3], include_top=False, weights=\"imagenet\")\n\nlayers_names = [\n    \"block2_conv1\",    # 256x256\n    \"block2_conv2\",    # 256x256\n    \"block3_conv1\",    # 128x128\n    \"block3_conv2\",    # 128x128\n    \"block4_conv1\",    # 64x64\n    \"block4_conv2\",    # 64x64\n    \"block5_conv1\",    # 32x32\n]\n\nlayers = [base_model.get_layer(name).output for name in layers_names]\ndown_stack = tf.keras.Model(inputs=base_model.input, outputs=layers)\ndown_stack.trainable = False\n\n\nup_stack = [\n    upsample(512, 3, 1),   # 32x32 -> 32x32\n    upsample(512, 3, 2),   # 32x32 -> 64x64\n    upsample(256, 3, 1),   # 64x64 -> 64x64 \n    upsample(256, 3, 2),   # 64x64 -> 128x128\n    upsample(128, 3, 1),   # 128x128 -> 128x128\n    upsample(128, 3, 2),   # 128x128 -> 256x256\n]     ","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def unet_generator(output_channels=1):\n    inputs = tf.keras.layers.Input(shape=IMG_SIZE + [3])\n    x = inputs\n\n    initializer = tf.random_normal_initializer(0., 0.02)\n    output = tf.keras.layers.Conv2DTranspose(\n        output_channels, 3, strides=2, activation='sigmoid',\n        padding=\"same\", kernel_initializer=initializer\n    )\n    \n    concat = tf.keras.layers.Concatenate()\n\n    # Downsampling \n    skips = down_stack(x)\n    x = skips[-1]\n    skips = reversed(skips[:-1])\n\n    # Upsampling and establishing the skip connection\n    for up, skip in zip (up_stack, skips):\n        x = up(x)\n        if up.layers[0].strides == (2, 2):\n            concat = tf.keras.layers.Concatenate()\n            x = concat([x, skip])\n\n    x = output(x)\n    \n    return tf.keras.Model(inputs=inputs, outputs=x)\n\nmodel = unet_generator()\n","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"tf.keras.utils.plot_model(model, show_shapes=True)\n","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**Model output before Before training**","metadata":{}},{"cell_type":"code","source":"for images, masks in train_data.take(2):\n    for img, mask in zip(images, masks):\n        sample_image = img\n        sample_mask = mask\n        break","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def visualize(display_list):\n    plt.figure(figsize=(15, 15))\n    title = ['Input Image', 'True Mask', 'Predicted Mask']\n    for i in range(len(display_list)):\n        plt.subplot(1, len(display_list), i+1)\n        plt.title(title[i])\n        plt.imshow(tf.keras.preprocessing.image.array_to_img(display_list[i]))\n        plt.axis('off')\n    plt.show()\n\ndef show_predictions(sample_image, sample_mask):\n    pred_mask = model.predict(sample_image[tf.newaxis, ...])\n    pred_mask = pred_mask.reshape(IMG_SIZE[0],IMG_SIZE[1],1)\n    visualize([sample_image, sample_mask, pred_mask])\n    \nshow_predictions(sample_image, sample_mask)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"early_stopping_cb = tf.keras.callbacks.EarlyStopping(patience=5,\n                                                    restore_best_weights=True)\n\n\nepochs = 1\n\nclass DisplayCallback(tf.keras.callbacks.Callback):\n    def on_epoch_begin(self, epoch, logs=None):\n        if (epoch + 1) % 3 == 0:\n            show_predictions(sample_image, sample_mask)\n    \nmodel.compile(optimizer='adam',\n              loss=tf.keras.losses.BinaryCrossentropy(),\n              metrics=['accuracy'])\nmodel_history = model.fit(train_data, epochs=epochs,\n                          validation_data=valid_data,\n                          callbacks=[DisplayCallback(), early_stopping_cb])","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"loss = model_history.history['loss']\nval_loss = model_history.history['val_loss']\n\nacc = model_history.history['accuracy']\nval_acc = model_history.history['val_accuracy']\n\nplt.figure(figsize=(20, 5))\nplt.subplot(1, 2, 1)\nplt.plot(acc, label='Training Accuracy')\nplt.plot(val_acc, label='Validation Accuracy')\nplt.xlabel('Epoch')\nplt.ylabel('Accuracy')\nplt.legend()\n\nplt.subplot(1, 2, 2)\nplt.plot(loss, label='Training Loss')\nplt.plot(val_loss, label='Validation Loss')\nplt.xlabel('Epoch')\nplt.ylabel('Binary Cross Entropy')\nplt.legend()\nplt.show()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for images, masks in test_data.take(1):\n    for img, mask in zip(images, masks):\n        show_predictions(img, mask)","metadata":{"trusted":true},"execution_count":null,"outputs":[]}]}