{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.14","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"colab":{"provenance":[],"collapsed_sections":["EvxPB-mqmFrW","wATcP3FVmFre","75TVsB85mFre","U0tL3mZemFrj"]},"kaggle":{"accelerator":"none","dataSources":[{"sourceId":9988,"databundleVersionId":868324,"sourceType":"competition"}],"dockerImageVersionId":30761,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import warnings\nwarnings.filterwarnings('ignore')\n\nimport os\nimport numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\nimport seaborn as sns\n\nfrom skimage.io import imread\nfrom skimage.segmentation import mark_boundaries\nfrom skimage.util import montage\nfrom skimage.morphology import label\n\nimport gc\ngc.enable()","metadata":{"id":"duMa5oo7mFrI","execution":{"iopub.status.busy":"2024-09-10T04:10:55.205456Z","iopub.execute_input":"2024-09-10T04:10:55.206483Z","iopub.status.idle":"2024-09-10T04:10:58.197210Z","shell.execute_reply.started":"2024-09-10T04:10:55.206417Z","shell.execute_reply":"2024-09-10T04:10:58.196007Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Exploring the data <a class=\"anchor\"  id=\"h3\"></a>","metadata":{"id":"crJdN2a9mFrO"}},{"cell_type":"code","source":"# Train and test directories\ntrain_image_dir = '../input/airbus-ship-detection/train_v2'\ntest_image_dir = \"../input/airbus-ship-detection/test_v2\"","metadata":{"id":"q1XfqoRvmFrP","execution":{"iopub.status.busy":"2024-09-10T04:11:36.041632Z","iopub.execute_input":"2024-09-10T04:11:36.042256Z","iopub.status.idle":"2024-09-10T04:11:36.048048Z","shell.execute_reply.started":"2024-09-10T04:11:36.042211Z","shell.execute_reply":"2024-09-10T04:11:36.046530Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Getting into train directory\ntrain_images = os.listdir(train_image_dir)\ntrain_images.sort()\nprint(f\"Total of {len(train_images)} images in train directory.\\nHere is how first five train_images looks like:- {train_images[:5]}\")","metadata":{"id":"_v7uprIWmFrP","outputId":"2a11ea28-c293-408e-acf2-7b4cc2fe319a","execution":{"iopub.status.busy":"2024-09-10T04:11:38.977630Z","iopub.execute_input":"2024-09-10T04:11:38.978035Z","iopub.status.idle":"2024-09-10T04:11:40.693247Z","shell.execute_reply.started":"2024-09-10T04:11:38.977998Z","shell.execute_reply":"2024-09-10T04:11:40.691538Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Using for loop to generate different images to understand how data looks like\nplt.figure(figsize=(15,15))\nplt.suptitle('TRAIN IMAGES\\n', weight = 'bold', fontsize = 15, color = 'r')\nfor i in range(16):\n    plt.subplot(4, 4, i+1)\n    plt.imshow(imread(train_image_dir + \"/\" + train_images[i]))\n    plt.title(f\"{train_images[i]}\", weight = 'bold')\n    plt.axis('off')\nplt.tight_layout()","metadata":{"id":"2IfuQJbDmFrQ","outputId":"4594231b-4728-4b56-fb79-57f85b7541a5","execution":{"iopub.status.busy":"2024-09-10T04:11:42.634168Z","iopub.execute_input":"2024-09-10T04:11:42.634648Z","iopub.status.idle":"2024-09-10T04:11:47.984798Z","shell.execute_reply.started":"2024-09-10T04:11:42.634570Z","shell.execute_reply":"2024-09-10T04:11:47.983533Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"- So there are many images here that has no ships and few that does have one or multiple ships.","metadata":{"id":"6IUkSmz-mFrR"}},{"cell_type":"code","source":"# Train ships segmented masks\nmasks = pd.read_csv(\"../input/airbus-ship-detection/train_ship_segmentations_v2.csv\")\nmasks.head(10)","metadata":{"id":"zoIy1ed2mFrR","outputId":"58dfddd8-5ac8-417a-e644-e4424d88a4ae","execution":{"iopub.status.busy":"2024-09-10T04:12:04.509727Z","iopub.execute_input":"2024-09-10T04:12:04.510198Z","iopub.status.idle":"2024-09-10T04:12:05.729809Z","shell.execute_reply.started":"2024-09-10T04:12:04.510154Z","shell.execute_reply":"2024-09-10T04:12:05.728537Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"row_rle = ['10 1', \n           '4 1 2 0 4 1', \n           '3 1 4 0 3 1', \n           '2 1 6 0 2 1',\n           '1 1 2 0 1 1 2 0 1 1 2 0 1 1', \n           '1 1 8 0 1 1', \n           '3 1 1 0 2 1 1 0 3 1', \n           '2 1 1 0 1 1 2 0 1 1 1 0 2 1', \n           '1 1 1 0 1 1 1 0 2 1 1 0 1 1 1 0 1 1', \n           '10 1',\n           'Total']\n\npixels = [len(row.split(\" \")) for row in row_rle if row != 'Total']\nsum_pixels = np.array(pixels).sum()\npixels.append(sum_pixels)\n\ndata = {\n    'Row - RLE' : row_rle,\n    'Pixels' : pixels\n}\n\nrle_df = pd.DataFrame(data)\nrle_df.index+=1\nrle_df\n","metadata":{"id":"96TekMv2mFrS","outputId":"ea74af11-f7e3-4383-f9fd-8a790e118f79","execution":{"iopub.status.busy":"2024-09-10T04:12:12.926083Z","iopub.execute_input":"2024-09-10T04:12:12.926967Z","iopub.status.idle":"2024-09-10T04:12:12.941135Z","shell.execute_reply.started":"2024-09-10T04:12:12.926919Z","shell.execute_reply":"2024-09-10T04:12:12.939695Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Let us now see how it works for Image id:- 0005d01c8.jpg we have in the mask data frame\n\n# Original image from training set\nimg_arr = imread(train_image_dir + '/' + '0005d01c8.jpg')\nplt.figure(figsize=(15,8))\nplt.imshow(img_arr)\nplt.show()","metadata":{"id":"ZqlG5qDbmFrS","outputId":"36b8e417-8250-4876-e940-61981f73d79b","execution":{"iopub.status.busy":"2024-09-10T04:12:17.659807Z","iopub.execute_input":"2024-09-10T04:12:17.660225Z","iopub.status.idle":"2024-09-10T04:12:18.075056Z","shell.execute_reply.started":"2024-09-10T04:12:17.660189Z","shell.execute_reply":"2024-09-10T04:12:18.073948Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"img_arr.shape","metadata":{"id":"IJhFOljtmFrT","outputId":"3d10f1b8-5828-4635-e7ee-c6c581ddb464","execution":{"iopub.status.busy":"2024-09-10T04:12:22.748813Z","iopub.execute_input":"2024-09-10T04:12:22.749746Z","iopub.status.idle":"2024-09-10T04:12:22.757050Z","shell.execute_reply.started":"2024-09-10T04:12:22.749695Z","shell.execute_reply":"2024-09-10T04:12:22.755713Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Filter out all 0005d01c8.jpg image ids and respective encoded data \n# 2 ships means 2 same image ids will be there!\nrle_0 = masks.query('ImageId==\"0005d01c8.jpg\"')['EncodedPixels']\nrle_0","metadata":{"id":"dz6on9OLmFrT","outputId":"98fcaf86-a88e-43e4-9f66-8ed365bb0f25","execution":{"iopub.status.busy":"2024-09-10T04:12:25.804320Z","iopub.execute_input":"2024-09-10T04:12:25.804785Z","iopub.status.idle":"2024-09-10T04:12:25.838482Z","shell.execute_reply.started":"2024-09-10T04:12:25.804742Z","shell.execute_reply":"2024-09-10T04:12:25.837249Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Make a list of each mask shown above also visualise whats happening!\nmask_lst, ct = [], 1\nfor mask in rle_0:\n    print(f\"Mask {ct} -\\n{mask}\\n\\n\")\n    mask_lst.append(mask)\n    ct+=1","metadata":{"id":"0ccDO-J0mFrT","outputId":"a262b896-b911-4abd-b8ab-f68d70fc603d","execution":{"iopub.status.busy":"2024-09-10T04:12:29.047550Z","iopub.execute_input":"2024-09-10T04:12:29.048388Z","iopub.status.idle":"2024-09-10T04:12:29.054537Z","shell.execute_reply.started":"2024-09-10T04:12:29.048342Z","shell.execute_reply":"2024-09-10T04:12:29.053456Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Split and Display how the first mask in the list looks like\nsplit = mask_lst[0].split()\nprint(split)","metadata":{"id":"JcXAQabMmFrU","outputId":"8f589ee8-5bd6-4878-cc8b-659f04dcf323","execution":{"iopub.status.busy":"2024-09-10T04:12:35.791631Z","iopub.execute_input":"2024-09-10T04:12:35.792305Z","iopub.status.idle":"2024-09-10T04:12:35.798818Z","shell.execute_reply.started":"2024-09-10T04:12:35.792249Z","shell.execute_reply":"2024-09-10T04:12:35.797491Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"- This data shows start_pixels and lenghts where we can think ship to exist in the original image.\n- For example, 56777 3 shows that pixels 56777, 56778, 56779 contributes to the ship.\n- Our target is to create an image with these pixels labeled as 1 and remaining as 0.\n- This is how we can produce a mask for respective image.","metadata":{"id":"0lTvIaOMmFrU"}},{"cell_type":"code","source":"# Grab all the starting pixels and lenghts and convert it into integers using numpy \nstarts, lengths = [np.array(x, dtype = int) for x in (split[::2], split[1::2])]\nstarts, lengths","metadata":{"id":"JYxNhVTemFrU","outputId":"c8faed91-d89e-4384-eb49-3d80f3f7df95","execution":{"iopub.status.busy":"2024-09-10T04:12:41.647708Z","iopub.execute_input":"2024-09-10T04:12:41.648177Z","iopub.status.idle":"2024-09-10T04:12:41.658459Z","shell.execute_reply.started":"2024-09-10T04:12:41.648137Z","shell.execute_reply":"2024-09-10T04:12:41.657098Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Get the ending pixels. \n'''Examples:- \n56010 1 ---> Starts at 56010 and ends at 56010\n56777 3 ---> Starts at 56777 and ends at 56779\n57544 6 ---> Starts at 57544 and ends at 57549'''\nends = starts + lengths - 1\npd.DataFrame({\n    'Starts' : starts,\n    'Lengths' : lengths,\n    'Ends' : ends\n}).head(10)","metadata":{"id":"m_jYpfHymFrU","outputId":"7eebca8d-5238-4a94-90bb-4866838f67b3","execution":{"iopub.status.busy":"2024-09-10T04:12:45.253480Z","iopub.execute_input":"2024-09-10T04:12:45.253920Z","iopub.status.idle":"2024-09-10T04:12:45.266844Z","shell.execute_reply.started":"2024-09-10T04:12:45.253881Z","shell.execute_reply":"2024-09-10T04:12:45.265615Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Create 1s in place of these pixels and rest should be 0\nimg = np.zeros(768*768, dtype = np.uint8)\nfor start, end in zip(starts, ends):\n    img[start:end+1] = 1","metadata":{"id":"5gXIUsCOmFrV","execution":{"iopub.status.busy":"2024-09-10T04:12:58.169407Z","iopub.execute_input":"2024-09-10T04:12:58.169876Z","iopub.status.idle":"2024-09-10T04:12:58.176536Z","shell.execute_reply.started":"2024-09-10T04:12:58.169814Z","shell.execute_reply":"2024-09-10T04:12:58.175308Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Check how output looks\nimg[56776:56781] # Should output 0, 1 , 1, 1 ,0 as we know 56777, 56778, 56779 ---> 1 and 5676, 56780 ---> 0","metadata":{"id":"wyzWtoRnmFrV","outputId":"08a86a66-609a-44d4-f689-b613a1fa92bb","execution":{"iopub.status.busy":"2024-09-10T04:13:00.573409Z","iopub.execute_input":"2024-09-10T04:13:00.573867Z","iopub.status.idle":"2024-09-10T04:13:00.581488Z","shell.execute_reply.started":"2024-09-10T04:13:00.573825Z","shell.execute_reply":"2024-09-10T04:13:00.580212Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Copy-Paste this idea for another ship in the image\nsplit_1 = mask_lst[1].split()                                                                # Split the mask into start_pixels and lengths\nstarts, lengths = [np.array(x, dtype = int) for x in (split_1[0:][::2], split_1[1:][::2])]   # Generate arrays from only starts and lengths\nends = starts + lengths - 1                                                                  # Start pixel to end pixel will be start - 1 + length\nimg1 = np.zeros(768*768, dtype = np.uint8)                                                   # 1D array containing all zeros\nfor start, end in zip(starts, ends):                                                         # For each start to end pair\n    img1[start:end+1] = 1                                                                    # Convert the values from 0 to 1","metadata":{"id":"EzpbR0zNmFrV","execution":{"iopub.status.busy":"2024-09-10T04:13:03.795570Z","iopub.execute_input":"2024-09-10T04:13:03.796005Z","iopub.status.idle":"2024-09-10T04:13:03.804723Z","shell.execute_reply.started":"2024-09-10T04:13:03.795966Z","shell.execute_reply":"2024-09-10T04:13:03.803390Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Reshaping both the ship masks and combining it to form the final mask!\nimg = img.reshape(768, 768)\nimg1 = img1.reshape(768, 768)\nfinal = img+img1\nprint(final, '\\n\\n', final.shape, '\\n\\n', final.ndim)","metadata":{"id":"GaFH_dzQmFrV","outputId":"3bf72b85-38a8-4392-aace-437c46e4a9c3","execution":{"iopub.status.busy":"2024-09-10T04:13:07.419808Z","iopub.execute_input":"2024-09-10T04:13:07.420259Z","iopub.status.idle":"2024-09-10T04:13:07.428037Z","shell.execute_reply.started":"2024-09-10T04:13:07.420216Z","shell.execute_reply":"2024-09-10T04:13:07.426851Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Expand dimension of this array to have only 1 channel in the mask and visualise original and final mask\nfinal = np.expand_dims(final, -1) # -1 means the last available dimenstion, in this case it is 2. Hence, on axis = 2 we will get 1.\noriginal = imread(train_image_dir+'/'+train_images[15])\nplt.figure(figsize=(15, 8))\nplt.subplot(1, 2, 1)\nplt.title(f\"Original - Train Image, {original.shape}\")\nplt.imshow(original)\nplt.subplot(1, 2, 2)\nplt.title(f\"Mask generated from the RLE data for each ship, {final.shape}\")\nplt.imshow(final, cmap = \"gray\")\nplt.tight_layout()\nplt.show()","metadata":{"id":"GQf7ZZ3XmFrW","outputId":"5d90b3bd-4511-4769-9b82-67c79c8fd62a","execution":{"iopub.status.busy":"2024-09-10T04:13:10.775421Z","iopub.execute_input":"2024-09-10T04:13:10.775888Z","iopub.status.idle":"2024-09-10T04:13:11.771031Z","shell.execute_reply.started":"2024-09-10T04:13:10.775846Z","shell.execute_reply":"2024-09-10T04:13:11.769774Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"- Oh, something is off!\n- Our mask needs to be transposed. ","metadata":{"id":"6kZifw3AmFrW"}},{"cell_type":"code","source":"# Copy Paste the code from the prev cell with one change - Transpose!\nimg = img.reshape(768, 768).T     # Transpose the first ship mask\nimg1 = img1.reshape(768, 768).T   # Transpose the second ship mask\nfinal = img+img1                  # Generate the final mask with two ships \nfinal = np.expand_dims(final, -1) \nplt.figure(figsize=(15, 8))\nplt.subplot(1, 2, 1)\nplt.title(f\"Original - Train Image, {original.shape}\")\nplt.imshow(original)\nplt.subplot(1, 2, 2)\nplt.title(f\"Mask generated from the RLE data for each ship, {final.shape}\")\nplt.imshow(final, cmap = \"Blues_r\")\nplt.tight_layout()\nplt.show()","metadata":{"id":"jZrbe3d6mFrW","outputId":"530150c2-e503-401c-8fbf-3653cbd2c77e","execution":{"iopub.status.busy":"2024-09-10T04:13:15.669009Z","iopub.execute_input":"2024-09-10T04:13:15.669467Z","iopub.status.idle":"2024-09-10T04:13:16.665002Z","shell.execute_reply.started":"2024-09-10T04:13:15.669411Z","shell.execute_reply":"2024-09-10T04:13:16.663590Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"- So this is how the EncodedPixels data for one image id looks like!\n- We can build a function that can quickly generate such masks for all the EncodedPixels wrt to its ImageId.","metadata":{"id":"ccK3v3elmFrW"}},{"cell_type":"code","source":"# Define functions to do these tasks for all the training images\ndef rle_decode(mask_rle, shape=(768,768)):\n    '''\n    Input arguments -\n    mask_rle: Mask of one ship in the train image\n    shape: Output shape of the image array\n    '''\n    s = mask_rle.split()                                                               # Split the mask of each ship that is in RLE format\n    starts, lengths = [np.asarray(x, dtype=int) for x in (s[0:][::2], s[1:][::2])]     # Get the start pixels and lengths for which image has ship\n    ends = starts + lengths - 1                                                        # Get the end pixels where we need to stop\n    img = np.zeros(shape[0]*shape[1], dtype=np.uint8)                                  # A 1D vec full of zeros of size = 768*768\n    for lo, hi in zip(starts, ends):                                                   # For each start to end pixels where ship exists\n        img[lo:hi+1] = 1                                                               # Fill those values with 1 in the main 1D vector\n    '''\n    Returns -\n    Transposed array of the mask: Contains 1s and 0s. 1 for ship and 0 for background\n    '''\n    return img.reshape(shape).T                                                       \n\ndef masks_as_image(in_mask_list):\n    '''\n    Input - \n    in_mask_list: List of the masks of each ship in one whole training image\n    '''\n    all_masks = np.zeros((768, 768), dtype = np.int16)                                 # Creating 0s for the background\n    for mask in in_mask_list:                                                          # For each ship rle data in the list of mask rle \n        if isinstance(mask, str):                                                      # If the datatype is string\n            all_masks += rle_decode(mask)                                              # Use rle_decode to create one mask for whole image\n    '''\n    Returns - \n    Full mask of the training image whose RLE data has been passed as an input\n    '''\n    return np.expand_dims(all_masks, -1)","metadata":{"id":"dPjmkwHjmFrW","execution":{"iopub.status.busy":"2024-09-10T04:13:20.667732Z","iopub.execute_input":"2024-09-10T04:13:20.668157Z","iopub.status.idle":"2024-09-10T04:13:20.678987Z","shell.execute_reply.started":"2024-09-10T04:13:20.668118Z","shell.execute_reply":"2024-09-10T04:13:20.677538Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for num in [3, 4, 5, 6]:\n    rle_0 = masks.query(f'ImageId==\"{train_images[num-1]}\"')['EncodedPixels']\n    img_0 = masks_as_image(rle_0)\n    original = imread(train_image_dir+\"/\"+train_images[num-1])\n    plt.figure(figsize=(15, 8))\n    plt.subplot(1, 2, 1)\n    plt.title(f\"Original - Train Image {original.shape}\")\n    plt.imshow(original)\n    plt.subplot(1, 2, 2)\n    plt.title(f\"Mask generated from the RLE data for each ship {final.shape}\")\n    plt.imshow(img_0, cmap = \"Blues_r\")\n    plt.tight_layout()\n    plt.show()","metadata":{"id":"N3JLeU2ps5zG","outputId":"3a33c31e-e02a-4e87-dd62-de750de7707e","execution":{"iopub.status.busy":"2024-09-10T04:13:25.579671Z","iopub.execute_input":"2024-09-10T04:13:25.580116Z","iopub.status.idle":"2024-09-10T04:13:29.841692Z","shell.execute_reply.started":"2024-09-10T04:13:25.580078Z","shell.execute_reply":"2024-09-10T04:13:29.840637Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"- We have succesfully constructed some functions that will take in the rle data and convert it into mask!\n- We can now begin with spliting the data into train and validation.\n\n## Preparing Train and Validation Data <a class=\"anchor\"  id=\"h5\"></a>","metadata":{"id":"EvxPB-mqmFrW"}},{"cell_type":"code","source":"'''Note that NaN values in the EncodedPixels are of float type and everything else is a string type'''   \n\n# Add a new feature to the masks data frame named as ship. If Encoded pixel in any row is a string, there is a ship else there isn't. \nmasks['ships'] = masks['EncodedPixels'].map(lambda c_row: 1 if isinstance(c_row, str) else 0)\nmasks.head(9)","metadata":{"id":"h0BarNjlmFrX","outputId":"f5207375-1076-4703-81c7-b77c4f55f013","execution":{"iopub.status.busy":"2024-09-10T04:13:32.958612Z","iopub.execute_input":"2024-09-10T04:13:32.959066Z","iopub.status.idle":"2024-09-10T04:13:33.087638Z","shell.execute_reply.started":"2024-09-10T04:13:32.959025Z","shell.execute_reply":"2024-09-10T04:13:33.086499Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Making a new data frame with unique image ids where we are summing up the ship counts\nunique_img_ids = masks.groupby('ImageId').agg({'ships': 'sum'}).reset_index() \nunique_img_ids.index+=1 # Incrimenting all the index by 1\nunique_img_ids.head()","metadata":{"id":"iW_hlCevmFrX","outputId":"5c2f0605-a7f1-4018-c2db-e231138a817c","execution":{"iopub.status.busy":"2024-09-10T04:13:37.656747Z","iopub.execute_input":"2024-09-10T04:13:37.657319Z","iopub.status.idle":"2024-09-10T04:13:37.844063Z","shell.execute_reply.started":"2024-09-10T04:13:37.657267Z","shell.execute_reply":"2024-09-10T04:13:37.842746Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Adding two new features to unique_img_ids data frame. If ship exists in image, val is 1 else 0. And it's vec form\nunique_img_ids['has_ship'] = unique_img_ids['ships'].map(lambda x: 1.0 if x>0 else 0.0)\nunique_img_ids.head()","metadata":{"id":"aPaLVit8mFrX","outputId":"76a04e17-fa8c-4a27-fbdf-42f63a6fd876","execution":{"iopub.status.busy":"2024-09-10T04:13:41.266737Z","iopub.execute_input":"2024-09-10T04:13:41.267160Z","iopub.status.idle":"2024-09-10T04:13:41.331131Z","shell.execute_reply.started":"2024-09-10T04:13:41.267117Z","shell.execute_reply":"2024-09-10T04:13:41.329936Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Check the size of the files. Will take some time to run as there are loads of files!!!\nunique_img_ids['file_size_kb'] = unique_img_ids['ImageId'].map(lambda c_img_id: os.stat(os.path.join(train_image_dir, c_img_id)).st_size/1024)\n'''os.stat is used to get status of the specified path. Here, st_size represents size of the file in bytes. Converting it into kB!'''","metadata":{"id":"ETbI2Byss5zG","outputId":"ed08ef0c-db14-46ed-8fab-30af19a35c3b","execution":{"iopub.status.busy":"2024-09-10T04:13:45.809400Z","iopub.execute_input":"2024-09-10T04:13:45.809883Z","iopub.status.idle":"2024-09-10T04:17:45.257820Z","shell.execute_reply.started":"2024-09-10T04:13:45.809838Z","shell.execute_reply":"2024-09-10T04:17:45.256459Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# We can get rid of any images whose size is less than 35 Kb. As some of the files are corrupted! \nunique_img_ids[unique_img_ids.file_size_kb<35].head()","metadata":{"id":"dh7Z40aIs5zH","outputId":"c86e02f4-f0af-4561-d8de-e9d827cbd48b","execution":{"iopub.status.busy":"2024-09-10T04:21:02.449952Z","iopub.execute_input":"2024-09-10T04:21:02.450478Z","iopub.status.idle":"2024-09-10T04:21:02.470273Z","shell.execute_reply.started":"2024-09-10T04:21:02.450417Z","shell.execute_reply":"2024-09-10T04:21:02.468944Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Keep the files whose size > 35 kB\nunique_img_ids = unique_img_ids[unique_img_ids.file_size_kb > 35]\nunique_img_ids.head()","metadata":{"id":"Vcom6VhkmFrY","outputId":"022411aa-a97c-4e5d-a31d-02ea013dd24b","execution":{"iopub.status.busy":"2024-09-10T04:21:07.387718Z","iopub.execute_input":"2024-09-10T04:21:07.388303Z","iopub.status.idle":"2024-09-10T04:21:07.415277Z","shell.execute_reply.started":"2024-09-10T04:21:07.388248Z","shell.execute_reply":"2024-09-10T04:21:07.413887Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Also, retrive the old masks data frame\nmasks.drop(['ships'], axis=1, inplace=True)\nmasks.index+=1 \nmasks.head()","metadata":{"id":"DfJCvsCHmFrY","outputId":"43d5f845-b7a9-4c85-861d-4eb5dd059880","execution":{"iopub.status.busy":"2024-09-10T04:21:21.904680Z","iopub.execute_input":"2024-09-10T04:21:21.905100Z","iopub.status.idle":"2024-09-10T04:21:21.933201Z","shell.execute_reply.started":"2024-09-10T04:21:21.905064Z","shell.execute_reply":"2024-09-10T04:21:21.931914Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"- Now, its the time to use the train_test_split.\n- Stratify to split the dataset into train and test sets in a way that preserves the same proportions of examples in each class as observed in the original dataset.","metadata":{"id":"zCJ9sHZgmFrY"}},{"cell_type":"code","source":"# Train - Test split\nfrom sklearn.model_selection import train_test_split                   \ntrain_ids, valid_ids = train_test_split(unique_img_ids, test_size = 0.3, stratify = unique_img_ids['ships'])","metadata":{"id":"bbQHbyzxmFrY","execution":{"iopub.status.busy":"2024-09-10T04:21:27.014654Z","iopub.execute_input":"2024-09-10T04:21:27.015058Z","iopub.status.idle":"2024-09-10T04:21:27.533848Z","shell.execute_reply.started":"2024-09-10T04:21:27.015024Z","shell.execute_reply":"2024-09-10T04:21:27.532255Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Create train data frame\ntrain_df = pd.merge(masks, train_ids)\n\n# Create test data frame\nvalid_df = pd.merge(masks, valid_ids)","metadata":{"id":"mObH089jmFrZ","execution":{"iopub.status.busy":"2024-09-10T04:21:30.422600Z","iopub.execute_input":"2024-09-10T04:21:30.423102Z","iopub.status.idle":"2024-09-10T04:21:30.733041Z","shell.execute_reply.started":"2024-09-10T04:21:30.423056Z","shell.execute_reply":"2024-09-10T04:21:30.731595Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(\"There are ~\")\nprint(train_df.shape[0], 'training masks,')\nprint(valid_df.shape[0], 'validation masks.')","metadata":{"id":"5Po1UEcGmFrZ","outputId":"0bbb1cb4-603c-43d2-97a6-a2647072d42a","execution":{"iopub.status.busy":"2024-09-10T04:21:37.015326Z","iopub.execute_input":"2024-09-10T04:21:37.015788Z","iopub.status.idle":"2024-09-10T04:21:37.022738Z","shell.execute_reply.started":"2024-09-10T04:21:37.015746Z","shell.execute_reply":"2024-09-10T04:21:37.021323Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"'''\n# Visualise the ship counts\nplt.figure(figsize=(10, 6))\nsns.countplot(train_df.ships)\nplt.show()\n'''\n","metadata":{"execution":{"iopub.status.busy":"2024-09-10T04:21:39.455797Z","iopub.execute_input":"2024-09-10T04:21:39.456238Z","iopub.status.idle":"2024-09-10T04:21:39.463679Z","shell.execute_reply.started":"2024-09-10T04:21:39.456198Z","shell.execute_reply":"2024-09-10T04:21:39.462485Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Import necessary libraries\nimport matplotlib.pyplot as plt\nimport seaborn as sns\n\n# Visualise the ship counts\nplt.figure(figsize=(10, 6))\nsns.countplot(data=train_df, x='ships')\nplt.title('Ship Counts')\nplt.xlabel('Number of Ships')\nplt.ylabel('Count')\nplt.xticks(rotation=0)\nplt.show()","metadata":{"id":"hGt5Qns4mFrZ","outputId":"19bbeba3-2baf-450e-d908-3770ea8b439f","execution":{"iopub.status.busy":"2024-09-10T04:21:44.608696Z","iopub.execute_input":"2024-09-10T04:21:44.609186Z","iopub.status.idle":"2024-09-10T04:21:44.982804Z","shell.execute_reply.started":"2024-09-10T04:21:44.609143Z","shell.execute_reply":"2024-09-10T04:21:44.981002Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"- Oh!! Very huge imbalance in the data...\n- We need to have a better balanced data!!!","metadata":{"id":"gISXjCmZmFrd"}},{"cell_type":"markdown","source":"## Random Undersampling to generate a better balanced data to work with","metadata":{"id":"wATcP3FVmFre"}},{"cell_type":"code","source":"# Clipping the max value of grouped_ship_count to be 7, minimum to be 0\ndata = train_df\n#train_df['grouped_ship_count'] = train_df.ships.map(lambda x: (x+1)//2).clip(0,7)\ndata['grouped_ship_count'] = train_df.ships.map(lambda x: (x+1)//2).clip(0,7)","metadata":{"id":"GW1DYwrfmFre","execution":{"iopub.status.busy":"2024-09-10T04:21:52.515625Z","iopub.execute_input":"2024-09-10T04:21:52.517498Z","iopub.status.idle":"2024-09-10T04:21:52.616246Z","shell.execute_reply.started":"2024-09-10T04:21:52.517415Z","shell.execute_reply":"2024-09-10T04:21:52.614927Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Check\n#train_df.grouped_ship_count.value_counts()\ndata.grouped_ship_count.value_counts()","metadata":{"id":"QHic4kjdmFre","outputId":"900177b5-aff2-4aba-ab08-fc1124e93356","execution":{"iopub.status.busy":"2024-09-10T04:21:56.359378Z","iopub.execute_input":"2024-09-10T04:21:56.360387Z","iopub.status.idle":"2024-09-10T04:21:56.371098Z","shell.execute_reply.started":"2024-09-10T04:21:56.360343Z","shell.execute_reply":"2024-09-10T04:21:56.369849Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#### Difference between head(n) and sample(n) in pandas\n- df.head(n) returns only top n data from the df\n- df.sample(n) returns random n data from the df","metadata":{"execution":{"iopub.status.busy":"2022-10-07T10:50:30.915451Z","iopub.execute_input":"2022-10-07T10:50:30.916382Z","iopub.status.idle":"2022-10-07T10:50:30.941993Z","shell.execute_reply.started":"2022-10-07T10:50:30.916340Z","shell.execute_reply":"2022-10-07T10:50:30.940812Z"},"id":"75TVsB85mFre"}},{"cell_type":"code","source":"# Top 10 data\n#train_df.head(10)\ndata.head(10)","metadata":{"id":"pnr2H5_WmFre","outputId":"c657d012-f519-44f4-ae97-e46928698014","execution":{"iopub.status.busy":"2024-09-10T04:22:02.647275Z","iopub.execute_input":"2024-09-10T04:22:02.648175Z","iopub.status.idle":"2024-09-10T04:22:02.663312Z","shell.execute_reply.started":"2024-09-10T04:22:02.648124Z","shell.execute_reply":"2024-09-10T04:22:02.661918Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Random 10 data\n#train_df.sample(10)\ndata.sample(10)","metadata":{"id":"lHfspu_7mFre","outputId":"8da9cdfb-1932-472d-c844-78a5e427dbba","execution":{"iopub.status.busy":"2024-09-10T04:22:06.332890Z","iopub.execute_input":"2024-09-10T04:22:06.333342Z","iopub.status.idle":"2024-09-10T04:22:06.354392Z","shell.execute_reply.started":"2024-09-10T04:22:06.333301Z","shell.execute_reply":"2024-09-10T04:22:06.353184Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Random Under-Sampling ships\ndef sample_ships(in_df, base_rep_val=1500):\n    '''\n    Input Args:\n    in_df - dataframe we want to apply this function\n    base_val - random sample of this value to be taken from the data frame\n    '''\n    if in_df['ships'].values[0]==0:                                                 \n        return in_df.sample(base_rep_val//3)  # Random 1500//3 = 500 samples taken whose ship count is 0 in an image \n    else:                                 \n        return in_df.sample(base_rep_val)    # Random 1500 samples taken whose ship count is not 0 in an image","metadata":{"id":"yvk146BImFre","execution":{"iopub.status.busy":"2024-09-10T04:22:10.297941Z","iopub.execute_input":"2024-09-10T04:22:10.298400Z","iopub.status.idle":"2024-09-10T04:22:10.305577Z","shell.execute_reply.started":"2024-09-10T04:22:10.298356Z","shell.execute_reply":"2024-09-10T04:22:10.303844Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Creating groups of ship counts and applying the sample_ships functions to randomly undersample the ships\n#balanced_train_df = train_df.groupby('grouped_ship_count').apply(sample_ships)\nbalanced_train_df = data.groupby('grouped_ship_count').apply(sample_ships)\nbalanced_train_df.grouped_ship_count.value_counts() # In each group we have total of 1500 ships except 0 as we have decreased it even more to 500","metadata":{"id":"Sh2SgP5lmFrf","outputId":"52adb1b2-7c42-4e5a-9275-dc61f8aee600","execution":{"iopub.status.busy":"2024-09-10T04:22:14.331202Z","iopub.execute_input":"2024-09-10T04:22:14.331684Z","iopub.status.idle":"2024-09-10T04:22:14.382444Z","shell.execute_reply.started":"2024-09-10T04:22:14.331638Z","shell.execute_reply":"2024-09-10T04:22:14.381112Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Explaining what we just did if still not clear\nfor i in range(8):\n    df_val_counts = balanced_train_df[balanced_train_df.grouped_ship_count==i].ships.value_counts()\n    print(f\"Data frame for grouped ship count = {i}:-\\n{df_val_counts}\\nSum of Values:- {df_val_counts.values.sum()}\\n\\n\")\n","metadata":{"id":"6SERf32pmFrf","outputId":"612c6483-a49f-4cf1-d6c2-cd3a5486bfb6","execution":{"iopub.status.busy":"2024-09-10T04:22:18.679169Z","iopub.execute_input":"2024-09-10T04:22:18.679641Z","iopub.status.idle":"2024-09-10T04:22:18.704349Z","shell.execute_reply.started":"2024-09-10T04:22:18.679596Z","shell.execute_reply":"2024-09-10T04:22:18.703024Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(balanced_train_df.ships.isnull().sum())\nprint(balanced_train_df.ships.unique())\n","metadata":{"execution":{"iopub.status.busy":"2024-09-10T04:22:24.688159Z","iopub.execute_input":"2024-09-10T04:22:24.688622Z","iopub.status.idle":"2024-09-10T04:22:24.696489Z","shell.execute_reply.started":"2024-09-10T04:22:24.688576Z","shell.execute_reply":"2024-09-10T04:22:24.695022Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"balanced_train_df = balanced_train_df.dropna(subset=['ships'])\n# or\n#balanced_train_df['ships'] = balanced_train_df['ships'].fillna(value)","metadata":{"execution":{"iopub.status.busy":"2024-09-10T04:22:28.161649Z","iopub.execute_input":"2024-09-10T04:22:28.162070Z","iopub.status.idle":"2024-09-10T04:22:28.173788Z","shell.execute_reply.started":"2024-09-10T04:22:28.162033Z","shell.execute_reply":"2024-09-10T04:22:28.172461Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"balanced_train_df['ships'] = balanced_train_df['ships'].astype(int)\n","metadata":{"execution":{"iopub.status.busy":"2024-09-10T04:22:38.143534Z","iopub.execute_input":"2024-09-10T04:22:38.144006Z","iopub.status.idle":"2024-09-10T04:22:38.150259Z","shell.execute_reply.started":"2024-09-10T04:22:38.143964Z","shell.execute_reply":"2024-09-10T04:22:38.148837Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"'''\nplt.figure(figsize = (15, 5))\nplt.suptitle(\"Train Data\", fontsize = 18, color = 'r', weight = 'bold')\nplt.subplot(1, 2, 1)\nimport seaborn as sns\nsns.countplot(train_df.ships, palette = 'Set2')\nplt.title(\"Ship Counts - Before Balancing\", color = 'm', fontsize = 15)\nplt.ylabel(\"Count\", color = 'tab:pink', fontsize = 13)\nplt.xlabel(\"# Ships in an image\", color = 'tab:pink', fontsize = 13)\nplt.subplot(1, 2, 2)\nsns.countplot(balanced_train_df.ships, palette = 'Set2')\nplt.title(\"Ship Counts - After Balancing\", color = 'm', fontsize = 15)\nplt.xlabel(\"# Ships in an image\", color = 'tab:pink', fontsize = 13)\nplt.tight_layout()\n'''","metadata":{"id":"XnLI4bdHmFrf","outputId":"42aba9de-7844-4989-9059-d1b688d8b0cb","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Import necessary libraries\nimport matplotlib.pyplot as plt\nimport seaborn as sns\n\n# Ensure train_df and balanced_train_df have the 'ships' column and contain data\nif 'ships' not in train_df.columns:\n    raise ValueError(\"The 'ships' column is missing from train_df.\")\nif 'ships' not in balanced_train_df.columns:\n    raise ValueError(\"The 'ships' column is missing from balanced_train_df.\")\n\n# Visualize the ship counts before and after balancing\nplt.figure(figsize=(15, 5))\nplt.suptitle(\"Train Data\", fontsize=18, color='r', weight='bold')\n\nplt.subplot(1, 2, 1)\nsns.countplot(data=train_df, x='ships')\nplt.title(\"Ship Counts - Before Balancing\", color='m', fontsize=15)\nplt.ylabel(\"Count\", color='tab:blue', fontsize=13)\nplt.xlabel(\"# Ships in an image\", color='tab:pink', fontsize=13)\n\nplt.subplot(1, 2, 2)\nsns.countplot(data=balanced_train_df, x='ships', palette='Set2')\nplt.title(\"Ship Counts - After Balancing\", color='m', fontsize=15)\nplt.xlabel(\"# Ships in an image\", color='tab:blue', fontsize=13)\n\nplt.tight_layout()\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2024-09-10T04:22:44.549938Z","iopub.execute_input":"2024-09-10T04:22:44.550382Z","iopub.status.idle":"2024-09-10T04:22:45.241558Z","shell.execute_reply.started":"2024-09-10T04:22:44.550342Z","shell.execute_reply":"2024-09-10T04:22:45.239928Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Parameters\nBATCH_SIZE = 4                 # Train batch size\nEDGE_CROP = 16                 # While building the model\nNB_EPOCHS = 2                  # Training epochs\nGAUSSIAN_NOISE = 0.1           # To be used in a layer in the model\nUPSAMPLE_MODE = 'SIMPLE'       # SIMPLE ==> UpSampling2D, else Conv2DTranspose\nNET_SCALING = None             # Downsampling inside the network                        \nIMG_SCALING = (1, 1)           # Downsampling in preprocessing\nVALID_IMG_COUNT = 400          # Valid batch size\nMAX_TRAIN_STEPS = 10         # Maximum number of steps_per_epoch in training","metadata":{"id":"YnVyTCqUmFrf","execution":{"iopub.status.busy":"2024-09-10T04:23:09.116698Z","iopub.execute_input":"2024-09-10T04:23:09.117164Z","iopub.status.idle":"2024-09-10T04:23:09.125106Z","shell.execute_reply.started":"2024-09-10T04:23:09.117122Z","shell.execute_reply":"2024-09-10T04:23:09.122996Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Image and Mask Generator\ndef make_image_gen(in_df, batch_size = BATCH_SIZE):\n    '''\n    Inputs -\n    in_df - data frame on which the function will be applied\n    batch_size - number of training examples in one iteration\n    '''\n    all_batches = list(in_df.groupby('ImageId'))                             # Group ImageIds and create list of that dataframe\n    out_rgb = []                                                             # Image list\n    out_mask = []                                                            # Mask list\n    while True:                                                              # Loop for every data\n        np.random.shuffle(all_batches)                                       # Shuffling the data\n        for c_img_id, c_masks in all_batches:                                # For img_id and msk_rle in all_batches\n            rgb_path = os.path.join(train_image_dir, c_img_id)               # Get the img path\n            c_img = imread(rgb_path)                                         # img array\n            c_mask = masks_as_image(c_masks['EncodedPixels'].values)         # Create mask of rle data for each ship in an img\n            out_rgb += [c_img]                                               # Append the current img in the out_rgb / img list\n            out_mask += [c_mask]                                             # Append the current mask in the out_mask / mask list\n            if len(out_rgb)>=batch_size:                                     # If length of list is more or equal to batch size then\n                yield np.stack(out_rgb)/255.0, np.stack(out_mask)            # Yeild the scaled img array (b/w 0 and 1) and mask array (0 for bg and 1 for ship)\n                out_rgb, out_mask=[], []                                     # Empty the lists to create another batch","metadata":{"id":"_l69s0W_mFrf","execution":{"iopub.status.busy":"2024-09-10T04:23:13.614950Z","iopub.execute_input":"2024-09-10T04:23:13.615380Z","iopub.status.idle":"2024-09-10T04:23:13.624157Z","shell.execute_reply.started":"2024-09-10T04:23:13.615344Z","shell.execute_reply":"2024-09-10T04:23:13.622770Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Generate train data \ntrain_gen = make_image_gen(balanced_train_df)\n\n# Image and Mask\ntrain_x, train_y = next(train_gen)\n\n# Print the summary\nprint(f\"train_x ~\\nShape: {train_x.shape}\\nMin value: {train_x.min()}\\nMax value: {train_x.max()}\")\nprint(f\"\\ntrain_y ~\\nShape: {train_y.shape}\\nMin value: {train_y.min()}\\nMax value: {train_y.max()}\")","metadata":{"id":"LrGDDsHvmFrf","outputId":"df2fec31-16f5-4777-ade6-c3e79a8eabf6","execution":{"iopub.status.busy":"2024-09-10T04:23:18.652342Z","iopub.execute_input":"2024-09-10T04:23:18.653527Z","iopub.status.idle":"2024-09-10T04:23:19.513223Z","shell.execute_reply.started":"2024-09-10T04:23:18.653461Z","shell.execute_reply":"2024-09-10T04:23:19.511848Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Visulaising train batch\nmontage_rgb = lambda x: np.stack([montage(x[:, :, :, i]) for i in range(x.shape[3])], -1)\nbatch_rgb = montage_rgb(train_x)                                                   # Create montage of img\nbatch_seg = montage(train_y[:, :, :, 0])                                           # Create montafe of msk\nbatch_overlap = mark_boundaries(batch_rgb, batch_seg.astype(int))                  # Create bounding box around ships in img\ntitles = [\"Images\", \"Segmentations\", \"Bounding Boxes on ships in Images\"]          # Titles for subplot\ncolors = ['g', 'm', 'b']                                                           # Colors to be used for title\ndisplay = [batch_rgb, batch_seg, batch_overlap]                                    # What to display in subplot\nplt.figure(figsize=(25,10))                                                        # Generate figure \nfor i in range(3):                                                                 # For i = 0, 1, 2, 3                           \n    plt.subplot(1, 3, i+1)                                                         # Create subplot\n    plt.imshow(display[i])                                                         # Display \n    plt.title(titles[i], fontsize = 18, color = colors[i])                         # Title \n    plt.axis('off')                                                                # Turn off the axis\nplt.suptitle(\"Batch Visualizations\", fontsize = 20, color = 'r', weight = 'bold')  # Add suptitle\nplt.tight_layout()                                                                 # Layout for subplot","metadata":{"id":"YeeCgg_PmFrf","outputId":"dca020dc-5290-4100-b206-6f277a1e0506","execution":{"iopub.status.busy":"2024-09-10T04:23:23.156371Z","iopub.execute_input":"2024-09-10T04:23:23.157139Z","iopub.status.idle":"2024-09-10T04:23:27.067367Z","shell.execute_reply.started":"2024-09-10T04:23:23.157095Z","shell.execute_reply":"2024-09-10T04:23:27.066012Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Prepare validation data\nvalid_x, valid_y = next(make_image_gen(valid_df, VALID_IMG_COUNT))\nprint(f\"valid_x ~\\nShape: {valid_x.shape}\\nMin value: {valid_x.min()}\\nMax value: {valid_x.max()}\")\nprint(f\"\\nvalid_y ~\\nShape: {valid_y.shape}\\nMin value: {valid_y.min()}\\nMax value: {valid_y.max()}\")","metadata":{"id":"aUXAhwWKmFrg","outputId":"4c4f0973-9452-495c-b696-b0dbe07debcd","execution":{"iopub.status.busy":"2024-09-10T04:23:45.430408Z","iopub.execute_input":"2024-09-10T04:23:45.431515Z","iopub.status.idle":"2024-09-10T04:24:01.247052Z","shell.execute_reply.started":"2024-09-10T04:23:45.431447Z","shell.execute_reply":"2024-09-10T04:24:01.245644Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#MY EXTRA CODE\nprint(f\"valid_x ~\\nShape: {valid_x.shape}\\nType: {valid_x.dtype}\\nMin value: {valid_x.min()}\\nMax value: {valid_x.max()}\")\nprint(f\"\\nvalid_y ~\\nShape: {valid_y.shape}\\nType: {valid_y.dtype}\\nMin value: {valid_y.min()}\\nMax value: {valid_y.max()}\")\nvalid_x = valid_x.astype('float32')\nvalid_y = valid_y.astype('float32')\nprint(f\"valid_x ~\\nShape: {valid_x.shape}\\nType: {valid_x.dtype}\\nMin value: {valid_x.min()}\\nMax value: {valid_x.max()}\")\nprint(f\"\\nvalid_y ~\\nShape: {valid_y.shape}\\nType: {valid_y.dtype}\\nMin value: {valid_y.min()}\\nMax value: {valid_y.max()}\")\n","metadata":{"execution":{"iopub.status.busy":"2024-09-10T04:24:07.399746Z","iopub.execute_input":"2024-09-10T04:24:07.400218Z","iopub.status.idle":"2024-09-10T04:24:10.931052Z","shell.execute_reply.started":"2024-09-10T04:24:07.400166Z","shell.execute_reply":"2024-09-10T04:24:10.929630Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Augmenting Data using ImageDataGenerator\nfrom tensorflow.keras.preprocessing.image import ImageDataGenerator\n\n# Preparing image data generator arguments\ndg_args = dict(rotation_range = 15,            # Degree range for random rotations\n               horizontal_flip = True,         # Randomly flips the inputs horizontally\n               vertical_flip = True,           # Randomly flips the inputs vertically\n               data_format = 'channels_last')  # channels_last refer to (batch, height, width, channels)","metadata":{"id":"Ru71AFFwmFrg","execution":{"iopub.status.busy":"2024-09-10T04:24:44.245611Z","iopub.execute_input":"2024-09-10T04:24:44.246399Z","iopub.status.idle":"2024-09-10T04:24:44.252790Z","shell.execute_reply.started":"2024-09-10T04:24:44.246352Z","shell.execute_reply":"2024-09-10T04:24:44.251498Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"image_gen = ImageDataGenerator(**dg_args)\nlabel_gen = ImageDataGenerator(**dg_args)\n\ndef create_aug_gen(in_gen, seed = None):\n    '''\n    Takes in -\n    in_gen - train data generator, seed value\n    '''\n    np.random.seed(seed if seed is not None else np.random.choice(range(9999)))  # Randomly assign seed value if not provided\n    for in_x, in_y in in_gen:                                                    # For imgs and msks in train data generator\n        seed = 12                                                                # Seed value for imgs and msks must be same else augmentation won't be same\n        \n        # Create augmented imgs\n        g_x = image_gen.flow(255*in_x,                                           # Inverse scaling on imgs for augmentation                                       \n                             batch_size = in_x.shape[0],                         # batch_size = 3\n                             seed = seed,                                        # Seed\n                             shuffle=True)                                       # Shuffle the data\n        \n        # Create augmented masks\n        g_y = label_gen.flow(in_y,\n                             batch_size = in_x.shape[0],                       \n                             seed = seed,                                         \n                             shuffle=True)                                       \n        \n        '''Yeilds - augmented scaled imgs and msks array'''\n        yield next(g_x)/255.0, next(g_y)\n    \n\n","metadata":{"id":"HQvlfWvjmFrg","execution":{"iopub.status.busy":"2024-09-10T04:24:54.214457Z","iopub.execute_input":"2024-09-10T04:24:54.214901Z","iopub.status.idle":"2024-09-10T04:24:54.223934Z","shell.execute_reply.started":"2024-09-10T04:24:54.214860Z","shell.execute_reply":"2024-09-10T04:24:54.222389Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#EXTRA CODE MINE\n\n# Assuming aug_gen is created from create_aug_gen function\naug_gen = create_aug_gen(make_image_gen(balanced_train_df))\n\n# Now, let's iterate over aug_gen to check the types and dtypes\nfor data in aug_gen:\n    print(type(data[0]), type(data[1]))  # This should print <class 'numpy.ndarray'> for both\n    print(data[0].dtype, data[1].dtype)  # This should print 'float32' for images and 'float32' or 'int32' for masks\n    break  # We break after one iteration just for checking\n","metadata":{"execution":{"iopub.status.busy":"2024-09-10T04:24:58.191478Z","iopub.execute_input":"2024-09-10T04:24:58.191937Z","iopub.status.idle":"2024-09-10T04:25:00.192660Z","shell.execute_reply.started":"2024-09-10T04:24:58.191895Z","shell.execute_reply":"2024-09-10T04:25:00.191164Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for imgs, masks in aug_gen:\n    print(f\"Images batch - type: {imgs.dtype}, shape: {imgs.shape}\")\n    print(f\"Masks batch - type: {masks.dtype}, shape: {masks.shape}\")\n    break  # Just check one batch\n","metadata":{"execution":{"iopub.status.busy":"2024-09-10T04:25:05.434640Z","iopub.execute_input":"2024-09-10T04:25:05.435118Z","iopub.status.idle":"2024-09-10T04:25:06.328974Z","shell.execute_reply.started":"2024-09-10T04:25:05.435076Z","shell.execute_reply":"2024-09-10T04:25:06.327560Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Augment the train data\ncur_gen = create_aug_gen(train_gen, seed = 42)\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())","metadata":{"id":"YChZ_zOqmFrg","outputId":"a941718e-7822-48f5-ee72-d37771ecec6a","execution":{"iopub.status.busy":"2024-09-10T04:25:10.092083Z","iopub.execute_input":"2024-09-10T04:25:10.092537Z","iopub.status.idle":"2024-09-10T04:25:10.983151Z","shell.execute_reply.started":"2024-09-10T04:25:10.092495Z","shell.execute_reply":"2024-09-10T04:25:10.981614Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Final display before passing data into model\nfig, (ax1, ax2, ax3) = plt.subplots(1, 3, figsize = (25, 10))\nax1.imshow(montage_rgb(t_x), cmap='gray')\nax1.set_title('Images', fontsize = 18, color = 'g')\nax1.axis('off')\nax2.imshow(montage(t_y[:, :, :, 0]), cmap='Blues_r')\nax2.set_title('Masks', fontsize = 18, color = 'r')\nax2.axis('off')\nax3.imshow(mark_boundaries(montage_rgb(t_x), montage(t_y[:, :, :, 0].astype(int))))\nax3.set_title('Bounding Box', fontsize = 18, color = 'b')\nax3.axis('off')\nplt.tight_layout()","metadata":{"id":"Tg7MNJdOmFrg","outputId":"c8c40493-674e-49d1-e9fa-bd281b33470c","execution":{"iopub.status.busy":"2024-09-10T04:25:14.915844Z","iopub.execute_input":"2024-09-10T04:25:14.916299Z","iopub.status.idle":"2024-09-10T04:25:17.930173Z","shell.execute_reply.started":"2024-09-10T04:25:14.916257Z","shell.execute_reply":"2024-09-10T04:25:17.928967Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"gc.collect() # Block all the garbage that has been generated","metadata":{"id":"H2GlhnR-mFrh","outputId":"0a87d09b-5b3a-45d2-fa71-7afdf43b8721","execution":{"iopub.status.busy":"2024-09-10T04:25:29.806658Z","iopub.execute_input":"2024-09-10T04:25:29.807107Z","iopub.status.idle":"2024-09-10T04:25:30.251783Z","shell.execute_reply.started":"2024-09-10T04:25:29.807067Z","shell.execute_reply":"2024-09-10T04:25:30.250313Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Build U-Net model\nfrom keras import models, layers\n\n# Conv2DTranspose upsampling\ndef upsample_conv(filters, kernel_size, strides, padding):\n    return layers.Conv2DTranspose(filters, kernel_size, strides=strides, padding=padding)\n# Upsampling without Conv2DTranspose\ndef upsample_simple(filters, kernel_size, strides, padding):\n    return layers.UpSampling2D(strides)\n\n# Upsampling method choice\nif UPSAMPLE_MODE=='DECONV':\n    upsample=upsample_conv\nelse:\n    upsample=upsample_simple\n\n# Building the layers of UNET\ninput_img = layers.Input(t_x.shape[1:], name = 'RGB_Input')\npp_in_layer = input_img\n\n# If NET_SCALING is defined then do the next step else continue ahead\nif NET_SCALING is not None:\n    pp_in_layer = layers.AvgPool2D(NET_SCALING)(pp_in_layer)\n\n# To avoid overfitting and fastening the process of training\npp_in_layer = layers.GaussianNoise(GAUSSIAN_NOISE)(pp_in_layer)                       # Useful to mitigate overfitting\npp_in_layer = layers.BatchNormalization()(pp_in_layer)                                # Allows using higher learning rate without causing problems with gradients\n\n\n## Downsample (C-->C-->MP)\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\n## Upsample (U --> Concat --> C --> C)\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.Cropping2D((EDGE_CROP, EDGE_CROP))(d)\nd = layers.ZeroPadding2D((EDGE_CROP, EDGE_CROP))(d)\n\nif NET_SCALING is not None:\n    d = layers.UpSampling2D(NET_SCALING)(d)\n\nseg_model = models.Model(inputs=[input_img], outputs=[d])\n\nseg_model.summary()","metadata":{"execution":{"iopub.status.busy":"2024-09-10T04:27:05.366569Z","iopub.execute_input":"2024-09-10T04:27:05.367484Z","iopub.status.idle":"2024-09-10T04:27:05.694704Z","shell.execute_reply.started":"2024-09-10T04:27:05.367426Z","shell.execute_reply":"2024-09-10T04:27:05.693548Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"\nimport tensorflow as tf\nfrom tensorflow.keras import backend as K\nfrom tensorflow.keras.optimizers import Adam\nfrom tensorflow.keras.callbacks import ModelCheckpoint, EarlyStopping\n\n# Define MeanIoU metric globally\nmean_iou_metric = tf.metrics.MeanIoU(num_classes=2)\n\n# Custom metric function\ndef mean_iou(y_true, y_pred):\n    y_pred = K.cast(y_pred > 0.5, 'float32')  # Threshold at 0.5\n    mean_iou_metric.update_state(y_true, y_pred)\n    return mean_iou_metric.result()\n\n# Compile the model\nseg_model.compile(optimizer=Adam(learning_rate=1e-4), \n                  loss='binary_crossentropy', \n                  metrics=[mean_iou])\n\n# Define model checkpoint\ncheckpoint = ModelCheckpoint('model.keras', save_best_only=True, monitor='val_loss', mode='min')\n\n# Define early stopping\nearly_stopping = EarlyStopping(patience=10, monitor='val_loss', mode='min')\n\n# Train the model\nhistory = seg_model.fit(train_gen, \n                        steps_per_epoch=MAX_TRAIN_STEPS, \n                        epochs=NB_EPOCHS, \n                        validation_data=(valid_x, valid_y), \n                        callbacks=[checkpoint, early_stopping])\n\n# Save the trained model\nseg_model.save('unet_ship_segmentation.keras')\n\n# Reset the metric state before use\nmean_iou_metric.reset_state()\n\n# Plotting training history\nimport matplotlib.pyplot as plt\n\nplt.figure(figsize=(12, 6))\n\n# Plot training & validation loss values\nplt.subplot(1, 2, 1)\nplt.plot(history.history['loss'])\nplt.plot(history.history['val_loss'])\nplt.title('Model loss')\nplt.ylabel('Loss')\nplt.xlabel('Epoch')\nplt.legend(['Train', 'Validation'], loc='upper right')\n\n# Plot training & validation IoU values\nplt.subplot(1, 2, 2)\nplt.plot(history.history['mean_iou'])\nplt.plot(history.history['val_mean_iou'])\nplt.title('Model IoU')\nplt.ylabel('IoU')\nplt.xlabel('Epoch')\nplt.legend(['Train', 'Validation'], loc='upper left')\n\nplt.tight_layout()\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2024-09-10T04:27:41.730416Z","iopub.execute_input":"2024-09-10T04:27:41.730936Z","iopub.status.idle":"2024-09-10T04:35:44.805160Z","shell.execute_reply.started":"2024-09-10T04:27:41.730893Z","shell.execute_reply":"2024-09-10T04:35:44.803513Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#this the CODEE is hidden\nimport tensorflow as tf\nfrom tensorflow.keras import backend as K\nfrom tensorflow.keras.optimizers import Adam\nfrom tensorflow.keras.callbacks import ModelCheckpoint, EarlyStopping\nfrom tensorflow.keras.mixed_precision import set_global_policy\n\n#Enable mixed precision\nset_global_policy('mixed_float16')\n\n#Define MeanIoU metric globally\nmean_iou_metric = tf.metrics.MeanIoU(num_classes=2)\n\n#Custom metric function\ndef mean_iou(y_true, y_pred):\n    y_pred = K.cast(y_pred > 0.5, 'float32')  # Threshold at 0.5\n    mean_iou_metric.update_state(y_true, y_pred)\n    return mean_iou_metric.result()\n\n#Compile the model\nseg_model.compile(optimizer=Adam(learning_rate=1e-4), \n                  loss='binary_crossentropy', \n                  metrics=[mean_iou])\n\n#Define model checkpoint\ncheckpoint = ModelCheckpoint('model.keras', save_best_only=True, monitor='val_loss', mode='min')\n\n#Define early stopping\nearly_stopping = EarlyStopping(patience=10, monitor='val_loss', mode='min')\n\n#Prepare data pipeline\ndef preprocess(image, mask):\n    image = tf.cast(image, tf.float32) / 255.0\n    mask = tf.cast(mask, tf.float32) / 255.0\n    return image, mask\n\ndef generator_wrapper():\n    for (image, mask) in train_gen:\n        yield image, mask\n\nBATCH_SIZE = 4  # Example batch size, set according to your needs\n\ntrain_dataset = tf.data.Dataset.from_generator(\n    generator_wrapper, \n    output_signature=(\n        tf.TensorSpec(shape=(BATCH_SIZE, 768, 768, 3), dtype=tf.float32),\n        tf.TensorSpec(shape=(BATCH_SIZE, 768, 768, 1), dtype=tf.float32)\n    )\n).prefetch(tf.data.AUTOTUNE)\n\nval_dataset = tf.data.Dataset.from_tensor_slices((valid_x, valid_y))\nval_dataset = val_dataset.map(preprocess).batch(BATCH_SIZE).prefetch(tf.data.AUTOTUNE)\n\n#Train the model\nhistory = seg_model.fit(train_dataset, \n                        steps_per_epoch=MAX_TRAIN_STEPS, \n                        epochs=NB_EPOCHS, \n                        validation_data=val_dataset, \n                        callbacks=[checkpoint, early_stopping])\n\n#Save the trained model\nseg_model.save('unet_ship_segmentation.keras')\n\n#Reset the metric state before use\n#mean_iou_metric.reset_states()\n\n#Plotting training history\nimport matplotlib.pyplot as plt\n\nplt.figure(figsize=(12, 6))\n\n#Plot training & validation loss values\nplt.subplot(1, 2, 1)\nplt.plot(history.history['loss'])\nplt.plot(history.history['val_loss'])\nplt.title('Model loss')\nplt.ylabel('Loss')\nplt.xlabel('Epoch')\nplt.legend(['Train', 'Validation'], loc='upper right')\n\n#Plot training & validation IoU values\nplt.subplot(1, 2, 2)\nplt.plot(history.history['mean_iou'])\nplt.plot(history.history['val_mean_iou'])\nplt.title('Model IoU')\nplt.ylabel('IoU')\nplt.xlabel('Epoch')\nplt.legend(['Train', 'Validation'], loc='upper left')\n\nplt.tight_layout()\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2024-09-10T04:49:04.308993Z","iopub.execute_input":"2024-09-10T04:49:04.309553Z","iopub.status.idle":"2024-09-10T04:56:53.756232Z","shell.execute_reply.started":"2024-09-10T04:49:04.309506Z","shell.execute_reply":"2024-09-10T04:56:53.754729Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Visualizing predictions on validation set\nvalid_pred = seg_model.predict(valid_x)\n\n# Function to plot original image, ground truth, and predicted mask\ndef plot_predictions(images, masks, predictions, index):\n    plt.figure(figsize=(15, 5))\n    plt.subplot(1, 3, 1)\n    plt.imshow(images[index])\n    plt.title('Original Image')\n    plt.axis('off')\n\n    plt.subplot(1, 3, 2)\n    plt.imshow(masks[index].squeeze(), cmap='gray')\n    plt.title('Ground Truth Mask')\n    plt.axis('off')\n\n# Plotting a \n#few example predictions\nfor i in range(5):\n    plot_predictions(valid_x, valid_y, valid_pred, i)","metadata":{"execution":{"iopub.status.busy":"2024-09-10T04:36:54.643640Z","iopub.execute_input":"2024-09-10T04:36:54.644178Z","iopub.status.idle":"2024-09-10T04:39:35.854648Z","shell.execute_reply.started":"2024-09-10T04:36:54.644135Z","shell.execute_reply":"2024-09-10T04:39:35.853251Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import matplotlib.pyplot as plt\n\n# Assuming valid_x, valid_y, valid_pred are already defined\n# valid_x: array of original images\n# valid_y: array of ground truth masks\n# valid_pred: array of predicted masks\n\n# Function to plot original image, ground truth, and predicted mask\ndef plot_predictions(images, masks, predictions, index):\n    plt.figure(figsize=(15, 5))\n    \n    # Original Image\n    plt.subplot(1, 3, 1)\n    plt.imshow(images[index])\n    plt.title('Original Image')\n    plt.axis('off')\n\n    # Ground Truth Mask\n    plt.subplot(1, 3, 2)\n    plt.imshow(masks[index].squeeze(), cmap='gray')\n    plt.title('Ground Truth Mask')\n    plt.axis('off')\n\n# Assuming valid_x, valid_y, valid_pred have been defined\n# Now, let's filter images that contain ships\nimages_with_ships = []\nfor i in range(len(valid_x)):\n    # Assuming valid_y contains the ground truth masks\n    if valid_y[i].sum() > 0:  # Check if there are any ship pixels in the ground truth mask\n        images_with_ships.append(i)\n\n# Plotting a few example predictions for images that contain ships\nnum_examples = min(5, len(images_with_ships))  # Plot up to 5 examples or fewer if there are less than 5 images with ships\nfor i in range(num_examples):\n    plot_predictions(valid_x, valid_y, valid_pred, images_with_ships[i])\n\nplt.show()\n","metadata":{"execution":{"iopub.status.busy":"2024-09-10T04:42:35.696282Z","iopub.execute_input":"2024-09-10T04:42:35.696840Z","iopub.status.idle":"2024-09-10T04:42:38.120266Z","shell.execute_reply.started":"2024-09-10T04:42:35.696797Z","shell.execute_reply":"2024-09-10T04:42:38.119087Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# RESULT ","metadata":{}},{"cell_type":"code","source":"import numpy as np\nimport matplotlib.pyplot as plt\n\n# Function to determine if a ship is detected based on ground truth mask\ndef is_ship_detected(ground_truth_mask):\n    # Check if any pixel in the ground truth mask is 1\n    return np.any(ground_truth_mask > 0.5)\n\n# Function to plot original image, ground truth, and predicted mask\ndef plot_predictions(images, ground_truth_masks, predicted_masks, index):\n    plt.figure(figsize=(15, 5))\n    \n    # Original Image\n    plt.subplot(1, 3, 1)\n    plt.imshow(images[index])\n    plt.title('Original Image')\n    plt.axis('off')\n\n    # Ground Truth Mask\n    plt.subplot(1, 3, 2)\n    plt.imshow(ground_truth_masks[index].squeeze(), cmap='gray')\n    plt.title('Ground Truth Mask')\n    plt.axis('off')\n\n    # Predicted Mask\n    plt.subplot(1, 3, 3)\n    plt.imshow(predicted_masks[index].squeeze(), cmap='gray')\n    \n    # Check if ship is detected in ground truth mask\n    if is_ship_detected(ground_truth_masks[index]):\n        plt.title('Predicted Mask - Ship Detected')\n    else:\n        plt.title('Predicted Mask - No Ship Detected')\n        \n    plt.axis('off')\n    \n    plt.show()\n\n# Example usage assuming valid_x, valid_y, and valid_pred are defined\n# Plotting a few example predictions\nfor i in range(10):\n    plot_predictions(valid_x, valid_y, valid_pred, i)\n","metadata":{"execution":{"iopub.status.busy":"2024-09-10T04:42:49.605112Z","iopub.execute_input":"2024-09-10T04:42:49.605616Z","iopub.status.idle":"2024-09-10T04:42:56.543059Z","shell.execute_reply.started":"2024-09-10T04:42:49.605571Z","shell.execute_reply":"2024-09-10T04:42:56.541656Z"},"trusted":true},"execution_count":null,"outputs":[]}]}