{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.13","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"gpu","dataSources":[{"sourceId":9988,"databundleVersionId":868324,"sourceType":"competition"}],"dockerImageVersionId":30747,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import tensorflow as tf\n# Enable mixed precision if supported\ntf.keras.mixed_precision.set_global_policy('mixed_float16')\n\n# Set custom configurations\ngpu_devices = tf.config.experimental.list_physical_devices('GPU')\nfor device in gpu_devices:\n    tf.config.experimental.set_memory_growth(device, True)\n\n# Set environment variables to manage cuDNN behavior\nimport os\nos.environ['TF_CUDNN_DETERMINISTIC'] = '1'\nos.environ['TF_FORCE_GPU_ALLOW_GROWTH'] = 'true'\n\n# Define data paths\ncsv_file = \"/kaggle/input/airbus-ship-detection/train_ship_segmentations_v2.csv\"\nroot_dir = \"/kaggle/input/airbus-ship-detection/train_v2/\"","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2024-07-30T08:13:32.790107Z","iopub.execute_input":"2024-07-30T08:13:32.790490Z","iopub.status.idle":"2024-07-30T08:13:45.704168Z","shell.execute_reply.started":"2024-07-30T08:13:32.790459Z","shell.execute_reply":"2024-07-30T08:13:45.703340Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import numpy as np\nimport pandas as pd\nimport os\nfrom tensorflow.keras.utils import Sequence\nfrom tensorflow.keras.preprocessing.image import load_img, img_to_array\n\ndef rle_decode(mask_rle, target_size=(768, 768)):\n    if pd.isna(mask_rle) or mask_rle == '':\n        return np.zeros(target_size, dtype=np.uint8)\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(np.prod(target_size), dtype=np.uint8)\n    for lo, hi in zip(starts, ends):\n        img[lo:hi] = 1\n    return img.reshape(target_size, order='F')\n\nclass CustomDataGenerator(Sequence):\n    def __init__(self, csv_file, root_dir, batch_size=4, original_size=(768, 768), target_size=(256, 256), ship_ratio=0.95, shuffle=True, indices=None, **kwargs):\n        super().__init__(**kwargs)\n        \n        self.data = pd.read_csv(csv_file)\n        self.root_dir = root_dir\n        self.batch_size = batch_size\n        self.original_size = original_size\n        self.target_size = target_size\n        self.ship_ratio = ship_ratio\n        self.shuffle = shuffle\n        \n        if indices is not None:\n            self.data = self.data.iloc[indices].reset_index(drop=True)\n        \n        images_with_ship = self.data[self.data['EncodedPixels'].notnull()]\n        num_images_with_ship = len(images_with_ship)\n        \n        num_images_without_ship = int(num_images_with_ship * (1 - ship_ratio) / ship_ratio)\n        num_images_without_ship = max(num_images_without_ship, 1)\n        \n        images_without_ship = self.data[self.data['EncodedPixels'].isnull()].sample(\n            n=num_images_without_ship, random_state=42, replace=False)\n        \n        self.data = pd.concat([images_with_ship, images_without_ship], ignore_index=True)\n        \n        self.indexes = np.arange(len(self.data))\n        if self.shuffle:\n            np.random.shuffle(self.indexes)\n\n    def __len__(self):\n        return int(np.ceil(len(self.data) / self.batch_size))\n\n    def __getitem__(self, index):\n        batch_indexes = self.indexes[index * self.batch_size:(index + 1) * self.batch_size]\n        batch_data = self.data.iloc[batch_indexes]\n        \n        images = np.zeros((len(batch_data), *self.target_size, 3), dtype=np.float32)\n        masks = np.zeros((len(batch_data), *self.target_size, 1), dtype=np.uint8)\n        \n        for i, (_, row) in enumerate(batch_data.iterrows()):\n            img_name = os.path.join(self.root_dir, row['ImageId'])\n            image = load_img(img_name, target_size=self.original_size)\n            image = img_to_array(image) / 255.0\n            \n            mask_str = row['EncodedPixels']\n            mask = rle_decode(mask_str, target_size=self.original_size)\n            mask = np.expand_dims(mask, axis=-1)\n            \n            # Resize images and masks\n            image = tf.image.resize(image, self.target_size).numpy()\n            mask = tf.image.resize(mask, self.target_size, method=tf.image.ResizeMethod.NEAREST_NEIGHBOR).numpy()\n            \n            images[i] = image\n            masks[i] = mask\n        \n        return images, masks\n    \n    def on_epoch_end(self):\n        if self.shuffle:\n            np.random.shuffle(self.indexes)\n","metadata":{"execution":{"iopub.status.busy":"2024-07-30T08:13:45.706144Z","iopub.execute_input":"2024-07-30T08:13:45.706955Z","iopub.status.idle":"2024-07-30T08:13:45.732884Z","shell.execute_reply.started":"2024-07-30T08:13:45.706919Z","shell.execute_reply":"2024-07-30T08:13:45.731716Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Create data generators\nfull_data_generator = CustomDataGenerator(csv_file, root_dir, target_size=(256, 256))\n\n# Split data\nnum_samples = len(full_data_generator.data)\nindices = np.arange(num_samples)\nnp.random.shuffle(indices)\nsplit_index = int(num_samples * 0.9)\n\ntrain_indices = indices[:split_index]\nval_indices = indices[split_index:]\n\n# Create train and validation generators with the split indices\ntrain_generator = CustomDataGenerator(csv_file=csv_file, root_dir=root_dir, batch_size=16, target_size=(256, 256), ship_ratio=0.8, shuffle=True, indices=train_indices)\nval_generator = CustomDataGenerator(csv_file=csv_file, root_dir=root_dir, batch_size=16, target_size=(256, 256), ship_ratio=0.8, shuffle=True, indices=val_indices)","metadata":{"execution":{"iopub.status.busy":"2024-07-30T08:13:45.734321Z","iopub.execute_input":"2024-07-30T08:13:45.734681Z","iopub.status.idle":"2024-07-30T08:13:48.356584Z","shell.execute_reply.started":"2024-07-30T08:13:45.734650Z","shell.execute_reply":"2024-07-30T08:13:48.355590Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from tensorflow.keras.models import Model\nfrom tensorflow.keras.layers import Input, Conv2D, MaxPooling2D, Dropout, concatenate, Conv2DTranspose, BatchNormalization\n\ndef UNet(input_shape=(256, 256, 3)):\n    inputs = Input(input_shape)\n    \n    # Downsampling path\n    conv1 = Conv2D(16, (3, 3), activation='relu', padding='same')(inputs)\n    conv1 = BatchNormalization()(conv1)\n    conv1 = Conv2D(16, (3, 3), activation='relu', padding='same')(conv1)\n    conv1 = BatchNormalization()(conv1)\n    pool1 = MaxPooling2D((2, 2))(conv1)\n    \n    conv2 = Conv2D(32, (3, 3), activation='relu', padding='same')(pool1)\n    conv2 = BatchNormalization()(conv2)\n    conv2 = Conv2D(32, (3, 3), activation='relu', padding='same')(conv2)\n    conv2 = BatchNormalization()(conv2)\n    pool2 = MaxPooling2D((2, 2))(conv2)\n    \n    conv3 = Conv2D(64, (3, 3), activation='relu', padding='same')(pool2)\n    conv3 = BatchNormalization()(conv3)\n    conv3 = Conv2D(64, (3, 3), activation='relu', padding='same')(conv3)\n    conv3 = BatchNormalization()(conv3)\n    pool3 = MaxPooling2D((2, 2))(conv3)\n    \n    conv4 = Conv2D(128, (3, 3), activation='relu', padding='same')(pool3)\n    conv4 = BatchNormalization()(conv4)\n    conv4 = Conv2D(128, (3, 3), activation='relu', padding='same')(conv4)\n    conv4 = BatchNormalization()(conv4)\n    drop4 = Dropout(0.5)(conv4)\n    pool4 = MaxPooling2D((2, 2))(drop4)\n    \n    # Upsampling path\n    up5 = Conv2DTranspose(128, (2, 2), strides=(2, 2), padding='same')(pool4)\n    up5 = concatenate([up5, drop4], axis=3)\n    conv5 = Conv2D(128, (3, 3), activation='relu', padding='same')(up5)\n    conv5 = BatchNormalization()(conv5)\n    conv5 = Conv2D(128, (3, 3), activation='relu', padding='same')(conv5)\n    conv5 = BatchNormalization()(conv5)\n    \n    up6 = Conv2DTranspose(64, (2, 2), strides=(2, 2), padding='same')(conv5)\n    up6 = concatenate([up6, conv3], axis=3)\n    conv6 = Conv2D(64, (3, 3), activation='relu', padding='same')(up6)\n    conv6 = BatchNormalization()(conv6)\n    conv6 = Conv2D(64, (3, 3), activation='relu', padding='same')(conv6)\n    conv6 = BatchNormalization()(conv6)\n    \n    up7 = Conv2DTranspose(32, (2, 2), strides=(2, 2), padding='same')(conv6)\n    up7 = concatenate([up7, conv2], axis=3)\n    conv7 = Conv2D(32, (3, 3), activation='relu', padding='same')(up7)\n    conv7 = BatchNormalization()(conv7)\n    conv7 = Conv2D(32, (3, 3), activation='relu', padding='same')(conv7)\n    conv7 = BatchNormalization()(conv7)\n    \n    up8 = Conv2DTranspose(16, (2, 2), strides=(2, 2), padding='same')(conv7)\n    up8 = concatenate([up8, conv1], axis=3)\n    conv8 = Conv2D(16, (3, 3), activation='relu', padding='same')(up8)\n    conv8 = BatchNormalization()(conv8)\n    conv8 = Conv2D(16, (3, 3), activation='relu', padding='same')(conv8)\n    conv8 = BatchNormalization()(conv8)\n    \n    # Final convolutional layer\n    outputs = Conv2D(1, (1, 1), activation='sigmoid')(conv8)\n    \n    model = Model(inputs=[inputs], outputs=[outputs])\n    \n    return model\n\nmodel = UNet()","metadata":{"execution":{"iopub.status.busy":"2024-07-30T08:13:48.359498Z","iopub.execute_input":"2024-07-30T08:13:48.359816Z","iopub.status.idle":"2024-07-30T08:13:48.864976Z","shell.execute_reply.started":"2024-07-30T08:13:48.359788Z","shell.execute_reply":"2024-07-30T08:13:48.863968Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.summary()","metadata":{"execution":{"iopub.status.busy":"2024-07-30T08:13:48.866407Z","iopub.execute_input":"2024-07-30T08:13:48.866991Z","iopub.status.idle":"2024-07-30T08:13:48.951323Z","shell.execute_reply.started":"2024-07-30T08:13:48.866956Z","shell.execute_reply":"2024-07-30T08:13:48.950474Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from tensorflow.keras.optimizers import Adam\nfrom tensorflow.keras.losses import binary_crossentropy\nimport tensorflow.keras.backend as K\n\ndef dice_coef(y_true, y_pred, smooth=1):\n    y_true = tf.cast(y_true, dtype=tf.float32)\n    y_pred = tf.cast(y_pred, dtype=tf.float32)\n    intersection = K.sum(K.abs(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])\n    dice = (2. * intersection + smooth) / (union + smooth)\n    return dice\n\ndef dice_loss(y_true, y_pred):\n    return 1 - dice_coef(y_true, y_pred)\n\ndef binary_crossentropy_with_dice_loss(y_true, y_pred):\n    return K.binary_crossentropy(y_true, y_pred) + (1 - dice_coef(y_true, y_pred))\n","metadata":{"execution":{"iopub.status.busy":"2024-07-30T08:13:48.952676Z","iopub.execute_input":"2024-07-30T08:13:48.952963Z","iopub.status.idle":"2024-07-30T08:13:48.963606Z","shell.execute_reply.started":"2024-07-30T08:13:48.952937Z","shell.execute_reply":"2024-07-30T08:13:48.962477Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"metrics = ['accuracy', dice_coef, dice_loss]\n\nmodel.compile(optimizer=Adam(learning_rate=0.00025), loss=binary_crossentropy_with_dice_loss, metrics=metrics)","metadata":{"execution":{"iopub.status.busy":"2024-07-30T08:13:48.964955Z","iopub.execute_input":"2024-07-30T08:13:48.965245Z","iopub.status.idle":"2024-07-30T08:13:48.986351Z","shell.execute_reply.started":"2024-07-30T08:13:48.965220Z","shell.execute_reply":"2024-07-30T08:13:48.985405Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Training loop\ncallbacks = [\n    tf.keras.callbacks.ModelCheckpoint('/kaggle/working/unet_model_sr08_dc.weights.h5', verbose=1, save_best_only=True, save_weights_only=True),\n    tf.keras.callbacks.TensorBoard(log_dir='/kaggle/working/logs')\n]\n\nhistory = model.fit(\n    train_generator,\n    epochs=10,\n    validation_data=val_generator,\n    callbacks=callbacks\n)","metadata":{"execution":{"iopub.status.busy":"2024-07-30T08:13:48.987936Z","iopub.execute_input":"2024-07-30T08:13:48.988296Z","iopub.status.idle":"2024-07-30T10:28:07.396658Z","shell.execute_reply.started":"2024-07-30T08:13:48.988263Z","shell.execute_reply":"2024-07-30T10:28:07.395303Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import matplotlib.pyplot as plt\n\nplt.figure(figsize=(12, 8))\n\nplt.subplot(1, 2, 1)\nplt.plot(history.history['loss'], label='Training Loss')\nplt.plot(history.history['val_loss'], label='Validation Loss')\nplt.title('Model Loss')\nplt.xlabel('Epoch')\nplt.ylabel('Loss')\nplt.legend(loc='upper right')\n\n# Plot training & validation dice coefficient values\nplt.subplot(1, 2, 2)\nplt.plot(history.history['dice_coef'], label='Training Dice Coefficient')\nplt.plot(history.history['val_dice_coef'], label='Validation Dice Coefficient')\nplt.title('Model Dice Coefficient')\nplt.xlabel('Epoch')\nplt.ylabel('Dice Coefficient')\nplt.legend(loc='lower right')\n\nplt.tight_layout()\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2024-07-30T10:28:07.398357Z","iopub.execute_input":"2024-07-30T10:28:07.398817Z","iopub.status.idle":"2024-07-30T10:28:08.030071Z","shell.execute_reply.started":"2024-07-30T10:28:07.398755Z","shell.execute_reply":"2024-07-30T10:28:08.029174Z"},"trusted":true},"execution_count":null,"outputs":[]}]}