{"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":[{"sourceType":"competition","sourceId":61446,"databundleVersionId":6962461},{"sourceType":"modelInstanceVersion","sourceId":6191,"databundleVersionId":7430053,"modelInstanceId":4655}],"dockerImageVersionId":30648,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"!pip install -q --upgrade keras-cv tensorflow\n!pip install -q --upgrade keras\n!pip install -q --upgrade tensorflow-io","metadata":{"execution":{"iopub.status.busy":"2024-03-05T16:09:40.958455Z","iopub.execute_input":"2024-03-05T16:09:40.959155Z","iopub.status.idle":"2024-03-05T16:11:11.444961Z","shell.execute_reply.started":"2024-03-05T16:09:40.959120Z","shell.execute_reply":"2024-03-05T16:11:11.443856Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import os\nos.environ[\"KERAS_BACKEND\"] = \"jax\"\n\nimport keras\nimport keras_cv\nimport tensorflow as tf \nimport tensorflow_io as tfio \n\nimport cv2\nimport pandas as pd\nimport numpy as np\nfrom glob import glob\nfrom tqdm.notebook import tqdm\n\nimport matplotlib.pyplot as plt \n\nimport warnings\nwarnings.filterwarnings(\"ignore\")","metadata":{"execution":{"iopub.status.busy":"2024-03-05T16:11:11.447217Z","iopub.execute_input":"2024-03-05T16:11:11.447520Z","iopub.status.idle":"2024-03-05T16:11:21.622439Z","shell.execute_reply.started":"2024-03-05T16:11:11.447492Z","shell.execute_reply":"2024-03-05T16:11:21.621663Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(\"TensorFlow:\", tf.__version__)\nprint(\"Keras:\", keras.__version__)\nprint(\"KerasCV:\", keras_cv.__version__)","metadata":{"execution":{"iopub.status.busy":"2024-03-05T16:11:21.623460Z","iopub.execute_input":"2024-03-05T16:11:21.623965Z","iopub.status.idle":"2024-03-05T16:11:21.629205Z","shell.execute_reply.started":"2024-03-05T16:11:21.623939Z","shell.execute_reply":"2024-03-05T16:11:21.628312Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class config:\n    verbose = 1  \n    seed = 42  \n    preset = \"deeplab_v3_plus_resnet50_pascalvoc\" \n    image_size = [384, 384] \n    epochs = 15 \n    batch_size = 12 \n    drop_remainder = True  \n    num_classes = 1 \n    cache = True ","metadata":{"execution":{"iopub.status.busy":"2024-03-05T16:11:21.630484Z","iopub.execute_input":"2024-03-05T16:11:21.630891Z","iopub.status.idle":"2024-03-05T16:11:21.702862Z","shell.execute_reply.started":"2024-03-05T16:11:21.630861Z","shell.execute_reply":"2024-03-05T16:11:21.702072Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"keras.utils.set_random_seed(config.seed)","metadata":{"execution":{"iopub.status.busy":"2024-03-05T16:11:21.705219Z","iopub.execute_input":"2024-03-05T16:11:21.705480Z","iopub.status.idle":"2024-03-05T16:11:21.714420Z","shell.execute_reply.started":"2024-03-05T16:11:21.705458Z","shell.execute_reply":"2024-03-05T16:11:21.713643Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"BASE_PATH = \"/kaggle/input/blood-vessel-segmentation\"","metadata":{"execution":{"iopub.status.busy":"2024-03-05T16:11:21.715335Z","iopub.execute_input":"2024-03-05T16:11:21.715580Z","iopub.status.idle":"2024-03-05T16:11:21.724188Z","shell.execute_reply.started":"2024-03-05T16:11:21.715558Z","shell.execute_reply":"2024-03-05T16:11:21.723372Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"mask_paths = sorted(glob(f\"{BASE_PATH}/train/*/labels/*tif\"))\ndf = pd.DataFrame({\"mask_path\":mask_paths})\ndf['dataset'] = df.mask_path.map(lambda x: x.split('/')[-3])\ndf['slice'] = df.mask_path.map(lambda x: x.split('/')[-1].replace(\".tif\",\"\"))\n\ndf = df[~df.dataset.str.contains(\"kidney_3_sparse\")]\ndf['image_path'] = df.mask_path.str.replace(\"label\",\"image\")\ndf['image_path'] = df.image_path.str.replace(\"kidney_3_dense\",\"kidney_3_sparse\")\ndf.head()","metadata":{"execution":{"iopub.status.busy":"2024-03-05T16:11:21.725188Z","iopub.execute_input":"2024-03-05T16:11:21.725464Z","iopub.status.idle":"2024-03-05T16:11:23.511257Z","shell.execute_reply.started":"2024-03-05T16:11:21.725442Z","shell.execute_reply":"2024-03-05T16:11:23.510339Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"CHANNELS = 3 \nSTRIDE = 3 \n\nfor i in range(CHANNELS):\n    df[f'image_path_{i:02}'] = df.groupby(['dataset'])['image_path'].shift(-i*STRIDE).ffill()\ndf['image_paths'] = df[[f'image_path_{i:02d}' for i in range(CHANNELS)]].values.tolist()\ndf.image_paths[0]","metadata":{"execution":{"iopub.status.busy":"2024-03-05T16:11:23.512825Z","iopub.execute_input":"2024-03-05T16:11:23.513232Z","iopub.status.idle":"2024-03-05T16:11:23.547097Z","shell.execute_reply.started":"2024-03-05T16:11:23.513200Z","shell.execute_reply":"2024-03-05T16:11:23.546293Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def build_decoder(with_labels=True, target_size=config.image_size, augment=False):\n    def decode_image(paths):\n        img_array = tf.TensorArray(dtype=tf.uint8, size=len(paths))\n        for i in range(len(paths)):\n            file_bytes = tf.io.read_file(paths[i])\n            img0 = tfio.experimental.image.decode_tiff(file_bytes)[..., 0:1]\n            img_array = img_array.write(i, img0[...,0])\n        img = tf.transpose(img_array.stack(), perm=(1, 2, 0))\n        img = tf.cast(img, tf.float32)\n        img -= tf.reduce_min(img)\n        img /= tf.reduce_max(img) + 0.001\n        del img_array\n        return img\n    \n    def decode_mask(mask_path):\n        file_bytes = tf.io.read_file(mask_path)\n        msk = tfio.experimental.image.decode_tiff(file_bytes)[...,0:1]\n        msk = tf.cast(msk, tf.float32) / 255.0\n        return msk\n\n    def decode_without_labels(img_path):\n        img = decode_image(img_path)\n        img = tf.reshape(img, [*target_size, 3])\n        return img\n    \n    def decode_with_labels(img_path, msk_path):\n        img_msk = tf.concat([decode_image(img_path), decode_mask(msk_path)], axis=-1)\n        img_msk = tf.image.random_crop(img_msk, [*target_size, 4])\n        if augment:\n            img_msk = apply_augmentations(img_msk)\n        img = tf.reshape(img_msk[...,0:3], [*target_size, 3])\n        msk = tf.reshape(img_msk[...,3:4], [*target_size, 1])\n        return (img, msk)\n    \n    def apply_augmentations(img):\n        img = tf.image.random_flip_left_right(img)\n        img = tf.image.random_flip_up_down(img)\n        img = tf.image.rot90(img, k=np.random.randint(-3, 3))\n        return img\n    \n    return decode_with_labels if with_labels else decode_without_labels\n\n\ndef build_dataset(img_paths, msk_paths=None, batch_size=32, cache=True,\n                  decode_fn=None, augment_fn=None,\n                  augment=True, repeat=True, shuffle=1024, \n                  cache_dir=\"\", drop_remainder=False):\n    if cache_dir != \"\" and cache is True:\n        os.makedirs(cache_dir, exist_ok=True)\n    \n    if decode_fn is None:\n        decode_fn = build_decoder(msk_paths is not None, augment=augment)\n    \n    AUTO = tf.data.experimental.AUTOTUNE\n    slices = img_paths if msk_paths is None else (img_paths, msk_paths)\n    \n    ds = tf.data.Dataset.from_tensor_slices(slices)\n    ds = ds.map(decode_fn, num_parallel_calls=AUTO)\n    ds = ds.cache(cache_dir) if cache else ds\n    ds = ds.repeat() if repeat else ds\n    if shuffle: \n        ds = ds.shuffle(shuffle, seed=config.seed)\n        opt = tf.data.Options()\n        opt.experimental_deterministic = False\n        ds = ds.with_options(opt)\n    ds = ds.batch(batch_size, drop_remainder=drop_remainder)\n    ds = ds.prefetch(AUTO)\n    return ds","metadata":{"execution":{"iopub.status.busy":"2024-03-05T16:11:23.548482Z","iopub.execute_input":"2024-03-05T16:11:23.548778Z","iopub.status.idle":"2024-03-05T16:11:23.565461Z","shell.execute_reply.started":"2024-03-05T16:11:23.548754Z","shell.execute_reply":"2024-03-05T16:11:23.564584Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_df = df[~df.dataset.str.contains('kidney_3')]\nvalid_df = df[df.dataset.str.contains('kidney_3')]\nprint('Num Train:', len(train_df), '| Num Valid:', len(valid_df))","metadata":{"execution":{"iopub.status.busy":"2024-03-05T16:11:23.566956Z","iopub.execute_input":"2024-03-05T16:11:23.567262Z","iopub.status.idle":"2024-03-05T16:11:23.588298Z","shell.execute_reply.started":"2024-03-05T16:11:23.567237Z","shell.execute_reply":"2024-03-05T16:11:23.587248Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_image_paths = train_df.image_paths.tolist()\ntrain_mask_paths = train_df.mask_path.tolist()\ntrain_ds = build_dataset(train_image_paths, train_mask_paths, batch_size=config.batch_size,\n                         cache=config.cache, augment=True)\n\nvalid_image_paths = valid_df.image_paths.tolist()\nvalid_mask_paths = valid_df.mask_path.tolist()\nvalid_ds = build_dataset(valid_image_paths, valid_mask_paths, batch_size=config.batch_size,\n                         cache=config.cache, repeat=False, shuffle=False, augment=False)","metadata":{"execution":{"iopub.status.busy":"2024-03-05T16:11:23.589463Z","iopub.execute_input":"2024-03-05T16:11:23.589753Z","iopub.status.idle":"2024-03-05T16:11:26.233602Z","shell.execute_reply.started":"2024-03-05T16:11:23.589730Z","shell.execute_reply":"2024-03-05T16:11:26.232597Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"batch = train_ds.take(1).get_single_element()\nkeras_cv.visualization.plot_segmentation_mask_gallery(\n    batch[0],\n    value_range=(0, 1),\n    num_classes=2, \n    y_true=batch[1],\n    scale=3,\n    rows=2,\n    cols=3,\n)","metadata":{"execution":{"iopub.status.busy":"2024-03-05T16:11:26.234779Z","iopub.execute_input":"2024-03-05T16:11:26.235059Z","iopub.status.idle":"2024-03-05T16:12:05.166557Z","shell.execute_reply.started":"2024-03-05T16:11:26.235035Z","shell.execute_reply":"2024-03-05T16:12:05.165637Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from keras import ops\n\nclass DiceLoss(keras.losses.Loss):\n    def __init__(self, smooth=1e-4, name=\"dice_loss\"):\n        super().__init__(name=name)\n        self.smooth = smooth\n\n    def call(self, y_true, y_pred):\n        # Flatten label and prediction tensors\n        y_true = ops.ravel(y_true)\n        y_pred = ops.ravel(y_pred)\n\n        # Compute the intersection & union\n        intersection = ops.sum(y_true * y_pred)\n        union = ops.sum(y_true) + ops.sum(y_pred)\n\n        # Compute the Dice coefficient\n        dice = (2. * intersection + self.smooth) / (union + self.smooth)\n        \n        # Return Dice loss\n        return 1. - dice\n    \nclass DiceCoef(keras.metrics.Metric):\n    def __init__(self, name='dice_coef', smooth=1e-4, threshold=0.5, **kwargs):\n        super().__init__(name=name, **kwargs)\n        self.smooth = smooth\n        self.threshold = threshold\n        self.intersection_sum = self.add_weight(name='intersection_sum', initializer='zeros')\n        self.union_sum = self.add_weight(name='union_sum', initializer='zeros')\n\n    def update_state(self, y_true, y_pred, sample_weight=None):\n        y_pred = ops.cast(y_pred > self.threshold, dtype=\"float32\")\n        y_true = ops.ravel(y_true)\n        y_pred = ops.ravel(y_pred)\n\n        intersection = ops.sum(y_true * y_pred)\n        union = ops.sum(y_true) + ops.sum(y_pred)\n\n        self.intersection_sum.assign_add(intersection)\n        self.union_sum.assign_add(union)\n\n    def result(self):\n        dice = (2 * self.intersection_sum + self.smooth) / (self.union_sum + self.smooth)\n        return dice\n\n    def reset_states(self):\n        self.intersection_sum.assign(0)\n        self.union_sum.assign(0)\n        \n    def get_config(self):\n        config = super().get_config()\n        config.update({'smooth': self.smooth, 'threshold': self.threshold})\n        return config","metadata":{"execution":{"iopub.status.busy":"2024-03-05T16:12:05.167706Z","iopub.execute_input":"2024-03-05T16:12:05.167983Z","iopub.status.idle":"2024-03-05T16:12:05.180917Z","shell.execute_reply.started":"2024-03-05T16:12:05.167959Z","shell.execute_reply":"2024-03-05T16:12:05.179939Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"segmentation_head = keras.Sequential(\n    [\n        keras.layers.Conv2D(\n            filters=32,\n            kernel_size=1,\n            padding=\"same\",\n            use_bias=False,\n        ),\n        keras.layers.BatchNormalization(),\n        keras.layers.ReLU(),\n        keras.layers.UpSampling2D(size=(4, 4), interpolation=\"bilinear\"),\n        keras.layers.Conv2D(\n            filters=config.num_classes,\n            kernel_size=1,\n            use_bias=False,\n            padding=\"same\",\n            activation=\"sigmoid\",\n            dtype=\"float32\",\n        ),\n    ], name=\"segmentation_head\",\n)","metadata":{"execution":{"iopub.status.busy":"2024-03-05T16:12:05.184092Z","iopub.execute_input":"2024-03-05T16:12:05.184378Z","iopub.status.idle":"2024-03-05T16:12:05.202176Z","shell.execute_reply.started":"2024-03-05T16:12:05.184355Z","shell.execute_reply":"2024-03-05T16:12:05.201415Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"backbone = keras_cv.models.DeepLabV3Plus.from_preset(\n    config.preset,\n    input_shape=[*config.image_size, 3],\n)\n\nneck_layer_name = backbone.layers[-2].name\nout = backbone.get_layer(neck_layer_name).output\n\nout = segmentation_head(out)\n\nmodel = keras.models.Model(inputs=backbone.input, outputs=out)\n\nOPTIMIZER = keras.optimizers.Adam(learning_rate=1e-4) # learning_rate)\nMETRICS = [\n    DiceCoef(),\n    keras.metrics.BinaryAccuracy(name=\"accuracy\"),\n]\nLOSS = DiceLoss()  \nmodel.compile(optimizer=OPTIMIZER, loss=LOSS, metrics=METRICS)\n\nmodel.summary()","metadata":{"execution":{"iopub.status.busy":"2024-03-05T16:12:05.203298Z","iopub.execute_input":"2024-03-05T16:12:05.203979Z","iopub.status.idle":"2024-03-05T16:12:15.526837Z","shell.execute_reply.started":"2024-03-05T16:12:05.203945Z","shell.execute_reply":"2024-03-05T16:12:15.525935Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import math\n\ndef get_lr_callback(batch_size=8, mode='cos', epochs=10, plot=False):\n    lr_start, lr_max, lr_min = 5e-5, 3e-5 * batch_size, 1e-5\n    lr_ramp_ep, lr_sus_ep, lr_decay = 3, 0, 0.75\n\n    def lrfn(epoch):  # Learning rate update function\n        if epoch < lr_ramp_ep: lr = (lr_max - lr_start) / lr_ramp_ep * epoch + lr_start\n        elif epoch < lr_ramp_ep + lr_sus_ep: lr = lr_max\n        elif mode == 'exp': lr = (lr_max - lr_min) * lr_decay**(epoch - lr_ramp_ep - lr_sus_ep) + lr_min\n        elif mode == 'step': lr = lr_max * lr_decay**((epoch - lr_ramp_ep - lr_sus_ep) // 2)\n        elif mode == 'cos':\n            decay_total_epochs, decay_epoch_index = epochs - lr_ramp_ep - lr_sus_ep + 3, epoch - lr_ramp_ep - lr_sus_ep\n            phase = math.pi * decay_epoch_index / decay_total_epochs\n            lr = (lr_max - lr_min) * 0.5 * (1 + math.cos(phase)) + lr_min\n        return lr\n\n    if plot:  # Plot lr curve if plot is True\n        plt.figure(figsize=(10, 5))\n        plt.plot(np.arange(epochs), [lrfn(epoch) for epoch in np.arange(epochs)], marker='o')\n        plt.xlabel('epoch'); plt.ylabel('lr')\n        plt.title('LR Scheduler')\n        plt.show()\n\n    return keras.callbacks.LearningRateScheduler(lrfn, verbose=False)  # Create lr callback","metadata":{"execution":{"iopub.status.busy":"2024-03-05T16:12:15.528022Z","iopub.execute_input":"2024-03-05T16:12:15.528302Z","iopub.status.idle":"2024-03-05T16:12:15.538099Z","shell.execute_reply.started":"2024-03-05T16:12:15.528278Z","shell.execute_reply":"2024-03-05T16:12:15.537180Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"lr_cb = get_lr_callback(config.batch_size, plot=True)","metadata":{"execution":{"iopub.status.busy":"2024-03-05T16:12:15.539120Z","iopub.execute_input":"2024-03-05T16:12:15.539400Z","iopub.status.idle":"2024-03-05T16:12:15.760206Z","shell.execute_reply.started":"2024-03-05T16:12:15.539369Z","shell.execute_reply":"2024-03-05T16:12:15.759253Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"ckpt_cb = keras.callbacks.ModelCheckpoint(\"best_model.keras\",\n                                         monitor='val_dice_coef',\n                                         save_best_only=True,\n                                         save_weights_only=False,\n                                         mode='max')","metadata":{"execution":{"iopub.status.busy":"2024-03-05T16:12:15.761395Z","iopub.execute_input":"2024-03-05T16:12:15.761673Z","iopub.status.idle":"2024-03-05T16:12:15.766074Z","shell.execute_reply.started":"2024-03-05T16:12:15.761642Z","shell.execute_reply":"2024-03-05T16:12:15.765145Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"os.environ[\"CUDA_VISIBLE_DEVICES\"] = \"0\" ","metadata":{"execution":{"iopub.status.busy":"2024-03-05T16:12:15.767380Z","iopub.execute_input":"2024-03-05T16:12:15.767764Z","iopub.status.idle":"2024-03-05T16:12:15.775199Z","shell.execute_reply.started":"2024-03-05T16:12:15.767731Z","shell.execute_reply":"2024-03-05T16:12:15.774248Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"history = model.fit(\n    train_ds, \n    epochs=config.epochs,\n    callbacks=[lr_cb, ckpt_cb], \n    steps_per_epoch=len(train_df)//config.batch_size,\n    validation_data=valid_ds, \n    verbose=config.verbose\n)","metadata":{"execution":{"iopub.status.busy":"2024-03-05T16:12:15.776278Z","iopub.execute_input":"2024-03-05T16:12:15.777085Z","iopub.status.idle":"2024-03-05T17:10:11.874215Z","shell.execute_reply.started":"2024-03-05T16:12:15.777049Z","shell.execute_reply":"2024-03-05T17:10:11.872440Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.load_weights(\"best_model.keras\")","metadata":{"execution":{"iopub.status.busy":"2024-03-05T17:10:20.091426Z","iopub.execute_input":"2024-03-05T17:10:20.092171Z","iopub.status.idle":"2024-03-05T17:10:39.589298Z","shell.execute_reply.started":"2024-03-05T17:10:20.092136Z","shell.execute_reply":"2024-03-05T17:10:39.588299Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"thrs = np.linspace(0, 1, 20)\nresults = []\nfor thr in tqdm(thrs, desc=\"Searching best thr \"):\n    dice_coef = DiceCoef(threshold=thr)\n    for (imgs, msks) in valid_ds:\n        imgs = ops.convert_to_tensor(imgs)\n        msks = ops.convert_to_tensor(msks)\n        preds = model(imgs)\n        dice_coef.update_state(msks, preds)\n    results.append(np.array(dice_coef.result()))\nresults = np.array(results)","metadata":{"execution":{"iopub.status.busy":"2024-03-05T17:10:41.936164Z","iopub.execute_input":"2024-03-05T17:10:41.937021Z","iopub.status.idle":"2024-03-05T17:14:24.376668Z","shell.execute_reply.started":"2024-03-05T17:10:41.936990Z","shell.execute_reply":"2024-03-05T17:14:24.375652Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Find the best threshold and best score\nBEST_THR = thrs[np.argmax(results)]\nBEST_SCORE = max(results)\n\n# Create the plot\nplt.figure(figsize=(10, 4))\nplt.plot(thrs, results, marker='o', label='Results',)\nplt.axvline(BEST_THR, color='red', linestyle='--', label=f'Best Threshold = {BEST_THR:.2f}')\n\n# Calculate relative coordinates based on figure size\nx_relative = 0.5  # Adjust as needed\ny_relative = 0.9  # Adjust as needed\n\n# Convert relative coordinates to absolute coordinates\nx_absolute = x_relative * (plt.xlim()[1] - plt.xlim()[0]) + plt.xlim()[0]\ny_absolute = y_relative * (plt.ylim()[1] - plt.ylim()[0]) + plt.ylim()[0]\n\nplt.annotate(f'Best Threshold = {BEST_THR:.2f}\\nBest Score = {BEST_SCORE:.2f}', \n             xy=(BEST_THR, BEST_SCORE), xytext=(x_absolute, y_absolute),\n             arrowprops=dict(arrowstyle='->', color='red'), color='red')\nplt.xlabel('Threshold')\nplt.ylabel('Results')\nplt.legend()\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2024-03-05T17:17:39.745854Z","iopub.execute_input":"2024-03-05T17:17:39.746261Z","iopub.status.idle":"2024-03-05T17:17:40.016336Z","shell.execute_reply.started":"2024-03-05T17:17:39.746226Z","shell.execute_reply":"2024-03-05T17:17:40.015372Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"images, masks = next(iter(valid_ds.take(1)))\nimages = ops.convert_to_tensor(images)\nmasks = ops.convert_to_tensor(masks)\npreds = ops.cast(model(images) > BEST_THR, \"float32\")\n\nkeras_cv.visualization.plot_segmentation_mask_gallery(\n    images,\n    value_range=(0, 1),\n    num_classes=2,\n    y_true=masks,\n    y_pred=preds,\n    scale=5,\n    rows=4,\n    cols=3,)","metadata":{"execution":{"iopub.status.busy":"2024-03-05T17:17:43.885165Z","iopub.execute_input":"2024-03-05T17:17:43.885524Z","iopub.status.idle":"2024-03-05T17:17:46.379396Z","shell.execute_reply.started":"2024-03-05T17:17:43.885494Z","shell.execute_reply":"2024-03-05T17:17:46.378547Z"},"trusted":true},"execution_count":null,"outputs":[]}]}