{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.12","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":30588,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import numpy as np \nimport pandas as pd\nimport tensorflow as tf\nimport tensorflow.keras as tfk\nimport tensorflow.keras.layers as tfl\nimport matplotlib.pyplot as plt\nimport tensorflow.keras.backend as K\nfrom sklearn.model_selection import train_test_split","metadata":{"execution":{"iopub.status.busy":"2024-07-15T17:36:28.560560Z","iopub.execute_input":"2024-07-15T17:36:28.560851Z","iopub.status.idle":"2024-07-15T17:36:28.568505Z","shell.execute_reply.started":"2024-07-15T17:36:28.560824Z","shell.execute_reply":"2024-07-15T17:36:28.567458Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"SIZE_FULL = 768 # original dataset's images size\nSIZE = 256 #size used for using in model (3x3 squares to make original image)","metadata":{"execution":{"iopub.status.busy":"2024-07-15T17:36:28.572895Z","iopub.execute_input":"2024-07-15T17:36:28.573215Z","iopub.status.idle":"2024-07-15T17:36:28.939103Z","shell.execute_reply.started":"2024-07-15T17:36:28.573179Z","shell.execute_reply":"2024-07-15T17:36:28.938023Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def crop3x3(img, i):\n    \"\"\"img: np.ndarray - original image 768x768\n       i: int 0-8 - image index from crop: 0 1 2\n                                           3 4 5\n                                           6 7 8\n       returns: image 256x256 \n    \"\"\"\n    return img[(i//3)*SIZE: ((i//3)+1)*SIZE,(i%3)*SIZE: (i%3+1)*SIZE]\n\n\ndef crop3x3_mask(img):\n    \"\"\"Returns crop image, crop index with maximum ships area\"\"\"\n    i = K.argmax((\n        K.sum(crop3x3(img, 0)),\n        K.sum(crop3x3(img, 1)),\n        K.sum(crop3x3(img, 2)),\n        K.sum(crop3x3(img, 3)),\n        K.sum(crop3x3(img, 4)),\n        K.sum(crop3x3(img, 5)),\n        K.sum(crop3x3(img, 6)),\n        K.sum(crop3x3(img, 7)),\n        K.sum(crop3x3(img, 8)),\n    ))\n    return (crop3x3(img, i), i)","metadata":{"execution":{"iopub.status.busy":"2024-07-15T17:36:28.941274Z","iopub.execute_input":"2024-07-15T17:36:28.942131Z","iopub.status.idle":"2024-07-15T17:36:28.951433Z","shell.execute_reply.started":"2024-07-15T17:36:28.942091Z","shell.execute_reply":"2024-07-15T17:36:28.950406Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# https://www.kaggle.com/code/stainsby/fast-tested-rle/notebook\ndef decode(mask_rle):\n    '''\n    mask_rle: run-length as string formated (start length)\n    shape: (height,width) of array to return \n    Returns numpy array, 1 - mask, 0 - background\n    '''\n    img=np.zeros(SIZE_FULL*SIZE_FULL, dtype=np.float32)\n    for mask in mask_rle:\n        s = mask.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        for (lo, hi) in zip(starts, ends):\n            img[lo:hi] = 1.0\n    return img.reshape((SIZE_FULL, SIZE_FULL)).T","metadata":{"execution":{"iopub.status.busy":"2024-07-15T17:36:28.952922Z","iopub.execute_input":"2024-07-15T17:36:28.953676Z","iopub.status.idle":"2024-07-15T17:36:28.961665Z","shell.execute_reply.started":"2024-07-15T17:36:28.953635Z","shell.execute_reply":"2024-07-15T17:36:28.960621Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def get_rle_dict(data):\n    rle_dict: dict = {}\n    for _, (image_id, rle_str) in data.iterrows():\n        if isinstance(rle_str, float):\n            rle_dict[image_id] = []\n        elif image_id in rle_dict:\n            rle_dict[image_id].append(rle_str)\n        else:\n            rle_dict[image_id] = [rle_str]\n    return rle_dict","metadata":{"execution":{"iopub.status.busy":"2024-07-15T17:36:28.964518Z","iopub.execute_input":"2024-07-15T17:36:28.964871Z","iopub.status.idle":"2024-07-15T17:36:28.971528Z","shell.execute_reply.started":"2024-07-15T17:36:28.964836Z","shell.execute_reply":"2024-07-15T17:36:28.970695Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class TrainDataGenerator(tfk.utils.Sequence):\n\n    def __init__(self, datapath ,batch_size, df_mask: pd.DataFrame):\n        self.datapath = datapath\n        self.batch_size = batch_size\n        self.df =  df_mask.sample(frac=1)\n        self.l = len(self.df)//batch_size\n\n    def __len__(self):\n        return self.l\n\n    def on_epoch_end(self):\n        pass\n#         self.df.sample(frac=1, replace=True)\n\n    def __getitem__(self, index):\n        mask = np.empty((self.batch_size, SIZE , SIZE), np.float32)\n        image = np.empty((self.batch_size, SIZE, SIZE, 3), np.float32)\n        \n        for b in range(self.batch_size):\n            temp = tfk.preprocessing.image.load_img(self.datapath + '/' + self.df.iloc[index*self.batch_size+b]['ImageId'])\n            temp = tfk.preprocessing.image.img_to_array(temp)/255\n        \n            mask[b], i = crop3x3_mask( # decoding mask from run-length format, and cropping part with maximum ship's area(№ i)\n                decode(\n                    self.df.iloc[index*self.batch_size+b]['EncodedPixels']\n                )\n            ) \n            image[b] = crop3x3(temp, i) # using corresponding to mask crop of image (№ i)\n            \n        return image, mask\n    \n    def getitem(self, index):\n        return self.__getitem__(index)\n    \n\ndef get_datagenerator(datapath ,batch_size, df_mask):\n    d = TrainDataGenerator(datapath, df_mask=df_mask, batch_size=1)\n    def _():\n        for i in range(len(d)):\n            x, y =  d.getitem(i)\n            yield x[0], y[0]\n    return tf.data.Dataset.from_generator(\n        _, output_signature=(\n            tf.TensorSpec(shape=(SIZE, SIZE, 3), dtype=tf.float32),\n            tf.TensorSpec(shape=(SIZE, SIZE), dtype=tf.float32),\n        ), \n    )","metadata":{"execution":{"iopub.status.busy":"2024-07-15T17:36:28.972455Z","iopub.execute_input":"2024-07-15T17:36:28.972707Z","iopub.status.idle":"2024-07-15T17:36:28.987706Z","shell.execute_reply.started":"2024-07-15T17:36:28.972685Z","shell.execute_reply":"2024-07-15T17:36:28.986821Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## UNET","metadata":{"execution":{"iopub.status.busy":"2023-12-06T16:18:20.447699Z","iopub.execute_input":"2023-12-06T16:18:20.448239Z","iopub.status.idle":"2023-12-06T16:18:20.454876Z","shell.execute_reply.started":"2023-12-06T16:18:20.448197Z","shell.execute_reply":"2023-12-06T16:18:20.453681Z"}}},{"cell_type":"code","source":"# dropout = 0.2\ndropout = 0.2\n\nk =2\ndef dconv(prev, filters, kernel_size=3):\n    prev = tfl.BatchNormalization()(prev)\n    prev = tfl.Conv2D(filters, kernel_size, padding=\"same\", activation=\"elu\", kernel_initializer= 'he_normal')(prev)\n    prev = tfl.Dropout(dropout)(prev)\n    prev = tfl.Conv2D(filters, kernel_size, padding=\"same\", activation=\"elu\", kernel_initializer= 'he_normal')(prev)\n    return prev\n    \n\n\ndef down(prev, filters, kernel_size=3): \n    skip = dconv(prev, filters, kernel_size)\n    prev = tfl.MaxPool2D(strides=2, padding='valid')(skip)\n    return prev, skip\n\n\ndef bridge(prev, filters,kernel_size=3):  \n    prev = dconv(prev, filters, kernel_size)\n    prev = tfl.Conv2DTranspose(filters // 2, 2, strides=(2, 2))(prev)\n    return prev\n\n\ndef up(prev, skip, filters, kernel_size=3):  \n    prev = tfl.concatenate([prev, skip], axis=3) \n    prev = tfl.Dropout(dropout)(prev)\n    prev = dconv(prev, filters, kernel_size)\n    prev = tfl.Conv2DTranspose(filters // 2, 2, strides=(2, 2))(prev)\n    return prev\n\n\ndef last(prev, skip, filters,kernels_size=(3,3)):\n    prev = tfl.concatenate([prev, skip], axis=3)\n    prev = tfl.Dropout(dropout)(prev)\n    prev = tfl.Conv2D(filters, kernels_size[0], padding=\"same\",activation=\"elu\", kernel_initializer= 'he_normal')(prev)\n    prev = tfl.Conv2D(filters, kernels_size[1], padding=\"same\",activation=\"elu\", kernel_initializer= 'he_normal')(prev)\n    prev = tfl.Conv2D(filters=1, kernel_size=1,padding=\"same\", activation=\"sigmoid\")(prev)\n    return prev\n\n\ndef unet_model(input_shape):\n    inp = tfk.Input(shape=input_shape)\n    inp = tfl.BatchNormalization()(inp)\n    out, skip_1 = down(inp, k*16)\n    out, skip_2 = down(out, k*32)\n    out, skip_3 = down(out, k*64)\n    out, skip_4 = down(out, k*128)\n    out = bridge(out, k*256)\n    out = up(out, skip_4, k*128)\n    out = up(out, skip_3, k*64)\n    out = up(out, skip_2, k*32)\n    out = last(out, skip_1, k*16)\n\n    model = tfk.Model(inputs=inp, outputs=out)\n    return model","metadata":{"execution":{"iopub.status.busy":"2024-07-15T17:36:44.050594Z","iopub.execute_input":"2024-07-15T17:36:44.050882Z","iopub.status.idle":"2024-07-15T17:36:44.067476Z","shell.execute_reply.started":"2024-07-15T17:36:44.050857Z","shell.execute_reply":"2024-07-15T17:36:44.066390Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Losses","metadata":{}},{"cell_type":"code","source":"import keras.backend as K\n\ndef dice_score(y_true, y_pred):\n    return (2.0*K.sum(y_pred * y_true)+0.0001) / (K.sum(y_true)+ K.sum(y_pred)+0.0001)\n\ndef BFCE_dice(y_true, y_pred):\n    return  K.binary_focal_crossentropy(y_true, y_pred)+  (1-dice_score(y_true, y_pred))*0.1\n\ndef BCE_dice(y_true, y_pred):\n    return  K.binary_crossentropy(y_true, y_pred)+  (1-dice_score(y_true, y_pred))","metadata":{"execution":{"iopub.status.busy":"2024-07-15T17:36:44.071664Z","iopub.execute_input":"2024-07-15T17:36:44.072124Z","iopub.status.idle":"2024-07-15T17:36:44.082087Z","shell.execute_reply.started":"2024-07-15T17:36:44.072085Z","shell.execute_reply":"2024-07-15T17:36:44.081106Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Train","metadata":{}},{"cell_type":"code","source":"empty, has_ships = 1000, 9000\ndf = pd.read_csv(\"/kaggle/input/airbus-ship-detection/train_ship_segmentations_v2.csv\")","metadata":{"execution":{"iopub.status.busy":"2024-07-15T18:12:32.684883Z","iopub.execute_input":"2024-07-15T18:12:32.685342Z","iopub.status.idle":"2024-07-15T18:12:33.272537Z","shell.execute_reply.started":"2024-07-15T18:12:32.685307Z","shell.execute_reply":"2024-07-15T18:12:33.271546Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df = pd.DataFrame(get_rle_dict(df).items(), columns=['ImageId', \"EncodedPixels\"])","metadata":{"execution":{"iopub.status.busy":"2024-07-15T18:12:33.273879Z","iopub.execute_input":"2024-07-15T18:12:33.274327Z","iopub.status.idle":"2024-07-15T18:12:47.243063Z","shell.execute_reply.started":"2024-07-15T18:12:33.274274Z","shell.execute_reply":"2024-07-15T18:12:47.242212Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df = pd.concat([df[df[\"EncodedPixels\"].isin([[]])].sample(empty), df[~df[\"EncodedPixels\"].isin([[]])].sample(has_ships)])","metadata":{"execution":{"iopub.status.busy":"2024-07-15T18:12:47.244178Z","iopub.execute_input":"2024-07-15T18:12:47.244452Z","iopub.status.idle":"2024-07-15T18:12:47.397759Z","shell.execute_reply.started":"2024-07-15T18:12:47.244429Z","shell.execute_reply":"2024-07-15T18:12:47.396771Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"batch_size = 32\ntrain_df, valid_df = train_test_split(df, test_size=0.2)\ntrain = get_datagenerator(\"/kaggle/input/airbus-ship-detection/train_v2\", 1, train_df)\nvalid = get_datagenerator(\"/kaggle/input/airbus-ship-detection/train_v2\", 1, valid_df)\nmodel = unet_model((SIZE, SIZE, 3))","metadata":{"execution":{"iopub.status.busy":"2024-07-15T17:36:44.083305Z","iopub.execute_input":"2024-07-15T17:36:44.083684Z","iopub.status.idle":"2024-07-15T17:36:45.614661Z","shell.execute_reply.started":"2024-07-15T17:36:44.083650Z","shell.execute_reply":"2024-07-15T17:36:45.613876Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train = train.cache().batch(batch_size).prefetch(1)\nvalid = valid.cache().batch(batch_size).prefetch(1)","metadata":{"execution":{"iopub.status.busy":"2024-07-15T17:36:45.615848Z","iopub.execute_input":"2024-07-15T17:36:45.616220Z","iopub.status.idle":"2024-07-15T17:36:45.634122Z","shell.execute_reply.started":"2024-07-15T17:36:45.616187Z","shell.execute_reply":"2024-07-15T17:36:45.633249Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"callback = tfk.callbacks.ModelCheckpoint(\"./models/model.{epoch:02d}-{val_loss:.4f}-dice:{val_dice_score:.4f}.h5\", \"val_loss\", save_best_only=True, save_weights_only=True)","metadata":{"execution":{"iopub.status.busy":"2024-07-15T17:36:45.635107Z","iopub.execute_input":"2024-07-15T17:36:45.635372Z","iopub.status.idle":"2024-07-15T17:36:45.640299Z","shell.execute_reply.started":"2024-07-15T17:36:45.635349Z","shell.execute_reply":"2024-07-15T17:36:45.638674Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.compile(tf.keras.optimizers.Adam(0.001) , BCE_dice  , dice_score)\nhistory = model.fit(train, validation_data=valid, batch_size = batch_size,epochs=8, verbose=1, callbacks=[callback], shuffle=True)","metadata":{"execution":{"iopub.status.busy":"2024-07-15T17:36:45.641712Z","iopub.execute_input":"2024-07-15T17:36:45.642100Z","iopub.status.idle":"2024-07-15T17:57:33.736266Z","shell.execute_reply.started":"2024-07-15T17:36:45.642044Z","shell.execute_reply":"2024-07-15T17:57:33.734979Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.compile(tf.keras.optimizers.Adam(0.0005) , BCE_dice  , dice_score)\nhistory2 = model.fit(train, validation_data=valid, batch_size = batch_size,epochs=8,verbose=1, callbacks=[callback], shuffle=True)","metadata":{"execution":{"iopub.status.busy":"2024-07-15T17:57:33.737804Z","iopub.execute_input":"2024-07-15T17:57:33.738218Z","iopub.status.idle":"2024-07-15T18:12:32.043893Z","shell.execute_reply.started":"2024-07-15T17:57:33.738187Z","shell.execute_reply":"2024-07-15T18:12:32.043088Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.compile(tf.keras.optimizers.Adam(0.0001) , BCE_dice  , dice_score)\nhistory3 = model.fit(train, validation_data=valid, batch_size = batch_size,epochs=8,verbose=1, callbacks=[callback], shuffle=True)","metadata":{"execution":{"iopub.status.busy":"2024-07-15T18:13:48.021358Z","iopub.execute_input":"2024-07-15T18:13:48.021715Z","iopub.status.idle":"2024-07-15T18:28:37.514764Z","shell.execute_reply.started":"2024-07-15T18:13:48.021685Z","shell.execute_reply":"2024-07-15T18:28:37.513565Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.compile(tf.keras.optimizers.Adam(0.00001) , BCE_dice  , dice_score)\nhistory4 = model.fit(train, validation_data=valid, batch_size = batch_size,epochs=8,verbose=1, callbacks=[callback], shuffle=True)","metadata":{"execution":{"iopub.status.busy":"2024-07-15T18:32:16.717851Z","iopub.execute_input":"2024-07-15T18:32:16.719102Z","iopub.status.idle":"2024-07-15T18:47:07.424931Z","shell.execute_reply.started":"2024-07-15T18:32:16.719037Z","shell.execute_reply":"2024-07-15T18:47:07.424073Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.save(\"final_model_val_dice_score=0.8627.keras\", )","metadata":{"execution":{"iopub.status.busy":"2024-07-15T18:50:37.814864Z","iopub.execute_input":"2024-07-15T18:50:37.815721Z","iopub.status.idle":"2024-07-15T18:50:38.387622Z","shell.execute_reply.started":"2024-07-15T18:50:37.815684Z","shell.execute_reply":"2024-07-15T18:50:38.386517Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"L = []\nL.extend(history.history['loss'])\nL.extend(history2.history['loss'])\nL.extend(history3.history['loss'])\nL.extend(history4.history['loss'])\n\nLV=[]\nLV.extend(history.history['val_loss'])\nLV.extend(history2.history['val_loss'])\nLV.extend(history3.history['val_loss'])\nLV.extend(history4.history['val_loss'])\n\n\nS = []\nS.extend(history.history['dice_score'])\nS.extend(history2.history['dice_score'])\nS.extend(history3.history['dice_score'])\nS.extend(history4.history['dice_score'])\n\n\nV = []\nV.extend(history.history['val_dice_score'])\nV.extend(history2.history['val_dice_score'])\nV.extend(history3.history['val_dice_score'])\nV.extend(history4.history['val_dice_score'])\n\n\nplt.plot(L, label=\"loss\")\nplt.plot(LV, label=\"val_loss\")\nplt.plot(S, label=\"dice_score\")\nplt.plot(V, label=\"val_dice_score\")\nplt.legend()","metadata":{"execution":{"iopub.status.busy":"2024-07-15T18:53:40.139983Z","iopub.execute_input":"2024-07-15T18:53:40.140366Z","iopub.status.idle":"2024-07-15T18:53:40.526627Z","shell.execute_reply.started":"2024-07-15T18:53:40.140336Z","shell.execute_reply":"2024-07-15T18:53:40.525582Z"},"trusted":true},"execution_count":null,"outputs":[]}]}