{"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":30892,"databundleVersionId":2715462,"sourceType":"competition"},{"sourceId":6106,"sourceType":"modelInstanceVersion","modelInstanceId":4649,"modelId":2804},{"sourceId":6107,"sourceType":"modelInstanceVersion","modelInstanceId":4650,"modelId":2804},{"sourceId":6108,"sourceType":"modelInstanceVersion","modelInstanceId":4651,"modelId":2804},{"sourceId":6113,"sourceType":"modelInstanceVersion","modelInstanceId":4618,"modelId":2799},{"sourceId":6124,"sourceType":"modelInstanceVersion","modelInstanceId":4599,"modelId":2797},{"sourceId":6125,"sourceType":"modelInstanceVersion","modelInstanceId":4596,"modelId":2797},{"sourceId":6126,"sourceType":"modelInstanceVersion","modelInstanceId":4597,"modelId":2797},{"sourceId":6127,"sourceType":"modelInstanceVersion","modelInstanceId":4598,"modelId":2797}],"dockerImageVersionId":30919,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"!pip install keras-cv;\n!pip install gdown;","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2025-04-19T22:36:42.373751Z","iopub.execute_input":"2025-04-19T22:36:42.374129Z","iopub.status.idle":"2025-04-19T22:36:49.937971Z","shell.execute_reply.started":"2025-04-19T22:36:42.374091Z","shell.execute_reply":"2025-04-19T22:36:49.937113Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import tensorflow as tf\nprint(tf.__version__)\n\ncur_dir = %env PWD\nis_kaggle = cur_dir == '/kaggle/working'\ntry:\n    tpu = 'local' if is_kaggle else ''    \n    resolver = tf.distribute.cluster_resolver.TPUClusterResolver(tpu)\n    tf.config.experimental_connect_to_cluster(resolver)\n    tf.tpu.experimental.initialize_tpu_system(resolver)\n    print('Using TPU')\n    # print(\"TPU devices: \", tf.config.list_logical_devices('TPU'))\n    strategy = tf.distribute.TPUStrategy(resolver)\nexcept:\n    GPU_list = tf.config.list_physical_devices('GPU')\n    GPU_count = len(GPU_list) if type(GPU_list) is list else 0\n    if GPU_count == 0:\n        print('Using CPU')\n        strategy = tf.distribute.get_strategy()\n    else:\n        print('Using GPU')\n        # print(\"GPU devices: \", tf.config.list_logical_devices('GPU'))\n        if len(GPU_list) == 1:\n            strategy = tf.distribute.get_strategy()\n        else:\n            # strategy = tf.distribute.MirroredStrategy() # Швидше, але використовує більше пам'яті GPU\n            strategy = tf.distribute.experimental.CentralStorageStrategy()\n\nprint('DEVICES AVAILABLE:', strategy.num_replicas_in_sync)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-19T22:36:49.939297Z","iopub.execute_input":"2025-04-19T22:36:49.939587Z","iopub.status.idle":"2025-04-19T22:37:02.759057Z","shell.execute_reply.started":"2025-04-19T22:36:49.939557Z","shell.execute_reply":"2025-04-19T22:37:02.758343Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\nimport cv2\nimport numpy as np\nfrom glob import glob\nfrom scipy.io import loadmat\nimport matplotlib.pyplot as plt\nfrom sklearn.model_selection import KFold\nimport keras_cv\nfrom tensorflow import keras\nfrom tensorflow.keras import layers\nfrom IPython.display import display, Image\nimport pandas as pd\nfrom tensorflow.keras import mixed_precision\n\n# print('GPU:', tf.config.list_physical_devices('GPU'))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-19T22:37:02.760615Z","iopub.execute_input":"2025-04-19T22:37:02.760876Z","iopub.status.idle":"2025-04-19T22:37:08.671569Z","shell.execute_reply.started":"2025-04-19T22:37:02.760855Z","shell.execute_reply":"2025-04-19T22:37:08.670851Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"policy = mixed_precision.Policy('mixed_float16')\nmixed_precision.set_global_policy(policy)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-19T22:37:08.672853Z","iopub.execute_input":"2025-04-19T22:37:08.673511Z","iopub.status.idle":"2025-04-19T22:37:08.677427Z","shell.execute_reply.started":"2025-04-19T22:37:08.673480Z","shell.execute_reply":"2025-04-19T22:37:08.676356Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"X_TRAIN_DIR = \"/kaggle/input/bkai-igh-neopolyp/train/train\"\nY_TRAIN_DIR = \"/kaggle/input/bkai-igh-neopolyp/train_gt/train_gt\"","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-19T22:37:08.678285Z","iopub.execute_input":"2025-04-19T22:37:08.678653Z","iopub.status.idle":"2025-04-19T22:37:08.698078Z","shell.execute_reply.started":"2025-04-19T22:37:08.678618Z","shell.execute_reply":"2025-04-19T22:37:08.697383Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"IMAGE_SIZE_X = 512\nIMAGE_SIZE_Y = 512\nNUM_CLASSES = 2\nseed = 42\nAUTOTUNE = tf.data.AUTOTUNE\nBATCH_SIZE = 10 * strategy.num_replicas_in_sync","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-19T22:37:08.698919Z","iopub.execute_input":"2025-04-19T22:37:08.699223Z","iopub.status.idle":"2025-04-19T22:37:08.714182Z","shell.execute_reply.started":"2025-04-19T22:37:08.699195Z","shell.execute_reply":"2025-04-19T22:37:08.713392Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"image_paths = sorted(glob(os.path.join(X_TRAIN_DIR, \"*.jpeg\"), recursive=True))\nmask_paths = sorted(glob(os.path.join(Y_TRAIN_DIR, \"*.jpeg\"), recursive=True))\nassert len(image_paths) == len(mask_paths), \"Image and mask counts do not match\"\nlen(image_paths)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-19T22:37:08.715040Z","iopub.execute_input":"2025-04-19T22:37:08.715289Z","iopub.status.idle":"2025-04-19T22:37:09.045038Z","shell.execute_reply.started":"2025-04-19T22:37:08.715256Z","shell.execute_reply":"2025-04-19T22:37:09.044355Z"},"scrolled":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def build_dataset(image_paths, mask_paths, augment=True):\n    dataset = tf.data.Dataset.from_tensor_slices((image_paths, mask_paths))\n\n    def load_image_mask(image_path, mask_path):\n        image = tf.io.read_file(image_path)\n        image = tf.image.decode_jpeg(image, channels=3)\n        image = tf.image.resize(image, [IMAGE_SIZE_Y, IMAGE_SIZE_X])\n\n        mask = tf.io.read_file(mask_path)\n        mask = tf.image.decode_jpeg(mask, channels=1)\n        mask = tf.image.resize(mask, [IMAGE_SIZE_Y, IMAGE_SIZE_X])\n        mask = tf.where(mask > 10, 255, 0)\n\n        return {\n            \"images\": tf.cast(image, tf.float32) / 255.0,\n            \"segmentation_masks\": tf.cast(mask, tf.float32) / 255.0\n        }\n\n    dataset = dataset.map(load_image_mask, num_parallel_calls=AUTOTUNE)\n\n    if augment:\n        dataset = dataset.map(lambda x: augment_fn(x), num_parallel_calls=AUTOTUNE)\n\n    dataset = dataset.map(unpackage_inputs, num_parallel_calls=AUTOTUNE)\n    return dataset.batch(BATCH_SIZE).prefetch(AUTOTUNE)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-19T22:37:09.047296Z","iopub.execute_input":"2025-04-19T22:37:09.047552Z","iopub.status.idle":"2025-04-19T22:37:09.053577Z","shell.execute_reply.started":"2025-04-19T22:37:09.047531Z","shell.execute_reply":"2025-04-19T22:37:09.052747Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"rescale_images_and_correct_masks = lambda image, mask: {\n    \"images\": tf.cast(image, dtype=tf.float32) / 255.0,\n    \"segmentation_masks\": tf.cast(tf.where(mask > 10, tf.constant(255, dtype=tf.uint8), mask), dtype=tf.float32) / 255,\n}","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-19T22:37:09.054826Z","iopub.execute_input":"2025-04-19T22:37:09.055125Z","iopub.status.idle":"2025-04-19T22:37:09.068015Z","shell.execute_reply.started":"2025-04-19T22:37:09.055096Z","shell.execute_reply":"2025-04-19T22:37:09.067390Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def unpackage_inputs(inputs):\n    images = inputs[\"images\"]\n    segmentation_masks = inputs[\"segmentation_masks\"]\n    return images, segmentation_masks","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-19T22:37:09.068746Z","iopub.execute_input":"2025-04-19T22:37:09.068956Z","iopub.status.idle":"2025-04-19T22:37:09.082358Z","shell.execute_reply.started":"2025-04-19T22:37:09.068939Z","shell.execute_reply":"2025-04-19T22:37:09.081753Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"ROTATION_FACTOR = (-0.05, 0.05)\npreprocess_fn = keras.Sequential(\n    [\n        keras_cv.layers.AutoContrast([0,1]),\n#         keras_cv.layers.Posterization([0,1],bits=6),\n    ]\n)\n\naugment_fn = keras.Sequential(\n    [\n        keras_cv.layers.AutoContrast([0,1]),\n        keras_cv.layers.RandomFlip(),\n        keras_cv.layers.RandomRotation(factor=ROTATION_FACTOR,\n                                       segmentation_classes=NUM_CLASSES),\n        keras_cv.layers.RandomSharpness(factor=0.5, value_range=[0,1], seed=seed),\n#         keras_cv.layers.GridMask(ratio_factor=(0, 0.5),rotation_factor=0.15, seed=seed),\n#         keras_cv.layers.RandomZoom(height_factor=(-0.3,-0.5),width_factor=(-0.2,-0.4),seed=seed),\n    ]\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-19T22:37:09.083130Z","iopub.execute_input":"2025-04-19T22:37:09.083335Z","iopub.status.idle":"2025-04-19T22:37:09.150184Z","shell.execute_reply.started":"2025-04-19T22:37:09.083296Z","shell.execute_reply":"2025-04-19T22:37:09.149605Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_index = [1,2,3,4,5]","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-19T22:37:09.150918Z","iopub.execute_input":"2025-04-19T22:37:09.151179Z","iopub.status.idle":"2025-04-19T22:37:09.154697Z","shell.execute_reply.started":"2025-04-19T22:37:09.151159Z","shell.execute_reply":"2025-04-19T22:37:09.153754Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_imgs = [image_paths[i] for i in train_index]\ntrain_masks = [mask_paths[i] for i in train_index]","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-19T22:37:09.155329Z","iopub.execute_input":"2025-04-19T22:37:09.155550Z","iopub.status.idle":"2025-04-19T22:37:09.169357Z","shell.execute_reply.started":"2025-04-19T22:37:09.155532Z","shell.execute_reply":"2025-04-19T22:37:09.168505Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_ds = build_dataset(train_imgs, train_masks, augment=True)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-19T22:37:09.170098Z","iopub.execute_input":"2025-04-19T22:37:09.170408Z","iopub.status.idle":"2025-04-19T22:37:09.619973Z","shell.execute_reply.started":"2025-04-19T22:37:09.170388Z","shell.execute_reply":"2025-04-19T22:37:09.619099Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"images, segmentation_masks = next(iter(train_ds))\n\nkeras_cv.visualization.plot_segmentation_mask_gallery(\n   images,\n   value_range=(0, 1),\n   num_classes=2,\n   y_true=segmentation_masks,\n   scale=8,\n   rows=1,\n   cols=1,\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-19T22:37:09.620839Z","iopub.execute_input":"2025-04-19T22:37:09.621073Z","iopub.status.idle":"2025-04-19T22:37:11.162973Z","shell.execute_reply.started":"2025-04-19T22:37:09.621052Z","shell.execute_reply":"2025-04-19T22:37:11.162178Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"kf = KFold(n_splits=5, shuffle=True, random_state=42)\nglobal_history = []\nfold_metrics = []","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-19T22:37:11.163654Z","iopub.execute_input":"2025-04-19T22:37:11.163941Z","iopub.status.idle":"2025-04-19T22:37:11.168958Z","shell.execute_reply.started":"2025-04-19T22:37:11.163916Z","shell.execute_reply":"2025-04-19T22:37:11.167652Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"for fold, (train_index, val_index) in enumerate(kf.split(image_paths)):\n    print(f\"Fold {fold + 1}\")\n\n    train_imgs = [image_paths[i] for i in train_index]\n    train_masks = [mask_paths[i] for i in train_index]\n    val_imgs = [image_paths[i] for i in val_index]\n    val_masks = [mask_paths[i] for i in val_index]\n\n    train_ds = build_dataset(train_imgs, train_masks, augment=True)\n    val_ds = build_dataset(val_imgs, val_masks, augment=False)\n\n    with strategy.scope():\n        model = keras_cv.models.DeepLabV3Plus.from_preset(\n            \"mobilenet_v3_large_imagenet\", load_weights=True,\n            num_classes=NUM_CLASSES, input_shape=[IMAGE_SIZE_Y, IMAGE_SIZE_X, 3]\n        )\n        model.compile(\n            optimizer=keras.optimizers.AdamW(learning_rate=0.0001),\n            loss=keras.losses.SparseCategoricalCrossentropy(from_logits=False),\n            metrics=[keras.metrics.MeanIoU(num_classes=NUM_CLASSES, sparse_y_pred=False, name=\"mean_iou\")],\n        )\n    early_stop = tf.keras.callbacks.EarlyStopping(monitor='val_mean_iou', patience=10, restore_best_weights=True, mode='max',start_from_epoch=5)\n    reduce_lr = keras.callbacks.ReduceLROnPlateau(monitor='val_loss', factor=0.2, patience=5)\n    \n    history = model.fit(train_ds,\n                        validation_data=val_ds,\n                        epochs=350,\n                        callbacks=[early_stop, reduce_lr])\n    \n    global_history.append(history)\n    final_mean_iou = history.history['val_mean_iou'][-1]\n    fold_metrics.append(final_mean_iou)\n    # Optional: Save model per fold\n    model.save(f\"model_fold_{fold+1}.keras\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-19T22:43:53.140373Z","iopub.execute_input":"2025-04-19T22:43:53.140673Z","iopub.status.idle":"2025-04-19T22:50:06.171675Z","shell.execute_reply.started":"2025-04-19T22:43:53.140651Z","shell.execute_reply":"2025-04-19T22:50:06.170448Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"fold_metrics = np.array(fold_metrics)\nprint(\"Mean IoU across 5 folds: \", fold_metrics.mean())\nprint(\"Std deviation of IoU: \", fold_metrics.std())","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"all_histories_df = pd.DataFrame()\n\nfor fold_idx, hist in enumerate(global_history):\n    fold_df = pd.DataFrame(hist.history)\n    fold_df[\"epoch\"] = fold_df.index\n    fold_df[\"fold\"] = fold_idx + 1\n    all_histories_df = pd.concat([all_histories_df, fold_df], ignore_index=True)","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"all_histories_df.to_csv(\"crossval_training_history.csv\", index=False)","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}