{"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":14774,"databundleVersionId":875431,"sourceType":"competition"},{"sourceId":252073,"sourceType":"modelInstanceVersion","isSourceIdPinned":true,"modelInstanceId":215510,"modelId":237218}],"dockerImageVersionId":30840,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import os\nimport cv2\nimport numpy as np\nimport pandas as pd\nimport random\nfrom tqdm import tqdm\n# import albumentations as A\nfrom tqdm.keras import TqdmCallback\nfrom sklearn.model_selection import train_test_split","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2025-02-07T05:32:47.407863Z","iopub.execute_input":"2025-02-07T05:32:47.408109Z","iopub.status.idle":"2025-02-07T05:32:47.420594Z","shell.execute_reply.started":"2025-02-07T05:32:47.408080Z","shell.execute_reply":"2025-02-07T05:32:47.419747Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import tensorflow as tf\nfrom tensorflow.keras.preprocessing.image import ImageDataGenerator\nfrom tensorflow.keras.applications.inception_resnet_v2 import InceptionResNetV2, preprocess_input\nfrom tensorflow.keras.layers import Dense, GlobalAveragePooling2D, Dropout\nfrom tensorflow.keras.models import Model\nfrom tensorflow.keras.optimizers import Adam\nfrom tensorflow.keras.callbacks import ModelCheckpoint, EarlyStopping, ReduceLROnPlateau","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-02-07T05:32:47.421425Z","iopub.execute_input":"2025-02-07T05:32:47.421771Z","iopub.status.idle":"2025-02-07T05:32:47.436417Z","shell.execute_reply.started":"2025-02-07T05:32:47.421741Z","shell.execute_reply":"2025-02-07T05:32:47.435724Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import warnings\nwarnings.filterwarnings(\"ignore\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-02-07T05:32:47.437018Z","iopub.execute_input":"2025-02-07T05:32:47.437230Z","iopub.status.idle":"2025-02-07T05:32:47.451684Z","shell.execute_reply.started":"2025-02-07T05:32:47.437212Z","shell.execute_reply":"2025-02-07T05:32:47.450968Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"SEED = 42\nnp.random.seed(SEED)\ntf.random.set_seed(SEED)\nrandom.seed(SEED)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-02-07T05:32:48.939513Z","iopub.execute_input":"2025-02-07T05:32:48.939807Z","iopub.status.idle":"2025-02-07T05:32:48.943996Z","shell.execute_reply.started":"2025-02-07T05:32:48.939785Z","shell.execute_reply":"2025-02-07T05:32:48.943232Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"gpus = tf.config.list_physical_devices('GPU')\nif gpus:\n    print(\"GPUs available:\")\n    for gpu in gpus:\n        print(gpu)\nelse:\n    print(\"No GPU available. Using CPU.\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-02-07T05:32:49.740415Z","iopub.execute_input":"2025-02-07T05:32:49.740724Z","iopub.status.idle":"2025-02-07T05:32:49.846744Z","shell.execute_reply.started":"2025-02-07T05:32:49.740698Z","shell.execute_reply":"2025-02-07T05:32:49.845838Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"TRAIN_IMG_DIR = \"../input/aptos2019-blindness-detection/train_images\"\nTEST_IMG_DIR  = \"../input/aptos2019-blindness-detection/test_images\"","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-02-07T05:32:51.044653Z","iopub.execute_input":"2025-02-07T05:32:51.044931Z","iopub.status.idle":"2025-02-07T05:32:51.048785Z","shell.execute_reply.started":"2025-02-07T05:32:51.044911Z","shell.execute_reply":"2025-02-07T05:32:51.047661Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_df = pd.read_csv(\"../input/aptos2019-blindness-detection/train.csv\")\ntest_df = pd.read_csv(\"../input/aptos2019-blindness-detection/test.csv\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-02-07T05:32:51.980552Z","iopub.execute_input":"2025-02-07T05:32:51.980877Z","iopub.status.idle":"2025-02-07T05:32:51.994883Z","shell.execute_reply.started":"2025-02-07T05:32:51.980849Z","shell.execute_reply":"2025-02-07T05:32:51.994049Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def get_image_path(id_code, is_train=True):\n    ext = \".png\"  # Change extension if needed.\n    if is_train:\n        return os.path.join(TRAIN_IMG_DIR, id_code + ext)\n    else:\n        return os.path.join(TEST_IMG_DIR, id_code + ext)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-02-07T05:32:52.793441Z","iopub.execute_input":"2025-02-07T05:32:52.793687Z","iopub.status.idle":"2025-02-07T05:32:52.797818Z","shell.execute_reply.started":"2025-02-07T05:32:52.793667Z","shell.execute_reply":"2025-02-07T05:32:52.796832Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_df[\"filepath\"] = train_df[\"id_code\"].apply(lambda x: get_image_path(x, is_train=True))\ntest_df[\"filepath\"]  = test_df[\"id_code\"].apply(lambda x: get_image_path(x, is_train=False))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-02-07T05:32:53.577741Z","iopub.execute_input":"2025-02-07T05:32:53.578039Z","iopub.status.idle":"2025-02-07T05:32:53.591030Z","shell.execute_reply.started":"2025-02-07T05:32:53.578014Z","shell.execute_reply":"2025-02-07T05:32:53.590109Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# train_transform = A.Compose([\n#     A.HorizontalFlip(p=0.5) if True else A.NoOp(),  # do_mirror=True\n#     A.RandomBrightnessContrast(brightness_limit=20/255, contrast_limit=0.2, p=0.5),\n#     A.HueSaturationValue(hue_shift_limit=10, sat_shift_limit=20, val_shift_limit=0, p=0.5),\n#     A.OneOf([\n#          A.Blur(blur_limit=3, p=0.5),\n#          A.Sharpen(p=0.5)\n#     ], p=0.5) if True else A.NoOp(),  # blur_and_sharpen\n#     A.ShiftScaleRotate(shift_limit=0.2, scale_limit=0.2, rotate_limit=180, \n#                          shear_limit=0.2, border_mode=cv2.BORDER_REFLECT_101, p=0.5)\n# ])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-02-07T05:32:54.090565Z","iopub.execute_input":"2025-02-07T05:32:54.090865Z","iopub.status.idle":"2025-02-07T05:32:54.094311Z","shell.execute_reply.started":"2025-02-07T05:32:54.090840Z","shell.execute_reply":"2025-02-07T05:32:54.093449Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_transform = ImageDataGenerator(\n    horizontal_flip=True,\n    brightness_range=(0.8, 1.2),\n    rotation_range=180,\n    shear_range=20,\n    zoom_range=(0.8, 1.2),\n    width_shift_range=0.2,\n    height_shift_range=0.2,\n    fill_mode='reflect',\n    # If desired, rescale pixel values before augmentations.\n    rescale=1./255\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-02-07T05:32:54.897957Z","iopub.execute_input":"2025-02-07T05:32:54.898291Z","iopub.status.idle":"2025-02-07T05:32:54.902238Z","shell.execute_reply.started":"2025-02-07T05:32:54.898263Z","shell.execute_reply":"2025-02-07T05:32:54.901480Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# valid_transform = A.Compose([])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-02-07T05:32:56.332976Z","iopub.execute_input":"2025-02-07T05:32:56.333307Z","iopub.status.idle":"2025-02-07T05:32:56.336886Z","shell.execute_reply.started":"2025-02-07T05:32:56.333280Z","shell.execute_reply":"2025-02-07T05:32:56.335961Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"valid_transform = ImageDataGenerator()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-02-07T05:32:56.655498Z","iopub.execute_input":"2025-02-07T05:32:56.655753Z","iopub.status.idle":"2025-02-07T05:32:56.658996Z","shell.execute_reply.started":"2025-02-07T05:32:56.655732Z","shell.execute_reply":"2025-02-07T05:32:56.658295Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"IMG_SIZE = 299","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-02-07T05:32:58.433569Z","iopub.execute_input":"2025-02-07T05:32:58.433871Z","iopub.status.idle":"2025-02-07T05:32:58.437393Z","shell.execute_reply.started":"2025-02-07T05:32:58.433847Z","shell.execute_reply":"2025-02-07T05:32:58.436550Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def load_and_preprocess_image(path, transform=None):\n    # Load the image from disk.\n    image = cv2.imread(path)\n    if image is None:\n        raise ValueError(f\"Image not found at path: {path}\")\n    \n    # Convert BGR to RGB and resize.\n    image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)\n    image = cv2.resize(image, (IMG_SIZE, IMG_SIZE))\n    \n    if transform:\n        # Apply a random augmentation.\n        image = transform.random_transform(image)\n        # Optionally, standardize the image using the generator's settings.\n        # For example, if you have set rescale or samplewise normalization in your ImageDataGenerator,\n        # this call will apply that standardization.\n        image = transform.standardize(image)\n    \n    # Convert to float32 and preprocess for InceptionResNetV2.\n    image = image.astype(np.float32)\n    image = preprocess_input(image)\n    return image\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-02-07T05:33:01.924091Z","iopub.execute_input":"2025-02-07T05:33:01.924466Z","iopub.status.idle":"2025-02-07T05:33:01.930064Z","shell.execute_reply.started":"2025-02-07T05:33:01.924438Z","shell.execute_reply":"2025-02-07T05:33:01.929019Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def __getitem__(self, index):\n    batch_indexes = self.indexes[index * self.batch_size:(index + 1) * self.batch_size]\n    batch_df = self.df.iloc[batch_indexes]\n    \n    images = []\n    labels = []\n    for _, row in batch_df.iterrows():\n        image = load_and_preprocess_image(row[\"filepath\"], transform=self.transform)\n        images.append(image)\n        if self.is_train:\n            label = tf.keras.utils.to_categorical(row[\"diagnosis\"], num_classes=self.num_classes)\n            labels.append(label)\n    \n    images = np.stack(images, axis=0)\n    if self.is_train:\n        labels = np.stack(labels, axis=0)\n        return images, labels\n    else:\n        return images","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-02-07T05:33:03.396766Z","iopub.execute_input":"2025-02-07T05:33:03.397058Z","iopub.status.idle":"2025-02-07T05:33:03.402494Z","shell.execute_reply.started":"2025-02-07T05:33:03.397036Z","shell.execute_reply":"2025-02-07T05:33:03.401633Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"class DataGenerator(tf.keras.utils.Sequence):\n    def __init__(self, df, batch_size=32, transform=None, is_train=True, num_classes=5, shuffle=True):\n        self.df = df.copy().reset_index(drop=True)\n        self.batch_size = batch_size\n        self.transform = transform\n        self.is_train = is_train\n        self.num_classes = num_classes\n        self.shuffle = shuffle\n        self.indexes = np.arange(len(self.df))\n        self.on_epoch_end()\n        \n    def __len__(self):\n        return int(np.ceil(len(self.df) / self.batch_size))\n    \n    def on_epoch_end(self):\n        if self.shuffle:\n            np.random.shuffle(self.indexes)\n    \n    def __getitem__(self, index):\n        batch_indexes = self.indexes[index * self.batch_size:(index + 1) * self.batch_size]\n        batch_df = self.df.iloc[batch_indexes]\n        \n        images = []\n        labels = []\n        for _, row in batch_df.iterrows():\n            image = load_and_preprocess_image(row[\"filepath\"], transform=self.transform)\n            images.append(image)\n            if self.is_train:\n                label = tf.keras.utils.to_categorical(row[\"diagnosis\"], num_classes=self.num_classes)\n                labels.append(label)\n        \n        images = np.stack(images, axis=0)\n        if self.is_train:\n            labels = np.stack(labels, axis=0)\n            return images, labels\n        else:\n            return images","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-02-07T05:33:04.432560Z","iopub.execute_input":"2025-02-07T05:33:04.432857Z","iopub.status.idle":"2025-02-07T05:33:04.439742Z","shell.execute_reply.started":"2025-02-07T05:33:04.432834Z","shell.execute_reply":"2025-02-07T05:33:04.438966Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_df_split, valid_df_split = train_test_split(train_df, test_size=0.2, random_state=SEED, stratify=train_df[\"diagnosis\"])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-02-07T05:33:07.155990Z","iopub.execute_input":"2025-02-07T05:33:07.156300Z","iopub.status.idle":"2025-02-07T05:33:07.164569Z","shell.execute_reply.started":"2025-02-07T05:33:07.156276Z","shell.execute_reply":"2025-02-07T05:33:07.163744Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"BATCH_SIZE = 32\ntrain_gen = DataGenerator(train_df_split, batch_size=BATCH_SIZE, transform=train_transform, is_train=True)\nvalid_gen = DataGenerator(valid_df_split, batch_size=BATCH_SIZE, transform=valid_transform, is_train=True)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-02-07T05:33:08.012788Z","iopub.execute_input":"2025-02-07T05:33:08.013071Z","iopub.status.idle":"2025-02-07T05:33:08.019295Z","shell.execute_reply.started":"2025-02-07T05:33:08.013050Z","shell.execute_reply":"2025-02-07T05:33:08.018355Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"weights_path = '/kaggle/input/inceptionresnetv2/keras/default/1/inception_resnet_v2_weights_tf_dim_ordering_tf_kernels_notop.h5'","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-02-07T05:33:08.877209Z","iopub.execute_input":"2025-02-07T05:33:08.877505Z","iopub.status.idle":"2025-02-07T05:33:08.881142Z","shell.execute_reply.started":"2025-02-07T05:33:08.877482Z","shell.execute_reply":"2025-02-07T05:33:08.880273Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"base_model = InceptionResNetV2(include_top=False, \n                               weights=weights_path, \n                               input_shape=(IMG_SIZE, IMG_SIZE, 3))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-02-07T05:33:09.694650Z","iopub.execute_input":"2025-02-07T05:33:09.694943Z","iopub.status.idle":"2025-02-07T05:33:17.402712Z","shell.execute_reply.started":"2025-02-07T05:33:09.694919Z","shell.execute_reply":"2025-02-07T05:33:17.401768Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"for layer in base_model.layers:\n    layer.trainable = True","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-02-07T05:33:17.403757Z","iopub.execute_input":"2025-02-07T05:33:17.404076Z","iopub.status.idle":"2025-02-07T05:33:17.411281Z","shell.execute_reply.started":"2025-02-07T05:33:17.404046Z","shell.execute_reply":"2025-02-07T05:33:17.410438Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"x = base_model.output\nx = GlobalAveragePooling2D()(x)\nx = Dense(100)(x)\nx = Dropout(0.3)(x)\npredictions = Dense(5, activation='softmax')(x)\nmodel = Model(inputs=base_model.input, outputs=predictions)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-02-07T05:33:31.542936Z","iopub.execute_input":"2025-02-07T05:33:31.543242Z","iopub.status.idle":"2025-02-07T05:33:31.608246Z","shell.execute_reply.started":"2025-02-07T05:33:31.543219Z","shell.execute_reply":"2025-02-07T05:33:31.607237Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model.compile(optimizer=Adam(learning_rate=1e-4), \n              loss='categorical_crossentropy', \n              metrics=['accuracy', 'precision', 'recall'])\n# model.summary()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-02-07T05:33:33.430251Z","iopub.execute_input":"2025-02-07T05:33:33.430549Z","iopub.status.idle":"2025-02-07T05:33:33.445472Z","shell.execute_reply.started":"2025-02-07T05:33:33.430527Z","shell.execute_reply":"2025-02-07T05:33:33.444737Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"checkpoint = ModelCheckpoint(\"best_model.keras\", monitor='val_loss', verbose=1, save_best_only=True, mode='min')\nearlystop  = EarlyStopping(monitor='val_loss', patience=20, verbose=1, mode='min', restore_best_weights=True)\nreduce_lr  = ReduceLROnPlateau(monitor='val_loss', factor=0.5, patience=5, verbose=1, min_lr=1e-7)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-02-07T05:33:34.736801Z","iopub.execute_input":"2025-02-07T05:33:34.737137Z","iopub.status.idle":"2025-02-07T05:33:34.741618Z","shell.execute_reply.started":"2025-02-07T05:33:34.737108Z","shell.execute_reply":"2025-02-07T05:33:34.740843Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"EPOCHS = 50\nhistory = model.fit(\n    train_gen,\n    epochs=EPOCHS,\n    validation_data=valid_gen,\n    # callbacks=[checkpoint, earlystop, reduce_lr],\n    callbacks=[TqdmCallback(verbose=1), checkpoint, earlystop, reduce_lr],\n    # workers=4,\n    # verbose = 1,\n    # use_multiprocessing=True\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-02-07T05:33:38.373945Z","iopub.execute_input":"2025-02-07T05:33:38.374282Z","iopub.status.idle":"2025-02-07T05:45:35.811358Z","shell.execute_reply.started":"2025-02-07T05:33:38.374255Z","shell.execute_reply":"2025-02-07T05:45:35.810386Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"test_gen = DataGenerator(test_df, \n                         batch_size=BATCH_SIZE, \n                         transform=valid_transform, \n                         is_train=False, \n                         shuffle=False)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-02-07T05:45:38.912793Z","iopub.execute_input":"2025-02-07T05:45:38.913084Z","iopub.status.idle":"2025-02-07T05:45:38.917772Z","shell.execute_reply.started":"2025-02-07T05:45:38.913061Z","shell.execute_reply":"2025-02-07T05:45:38.916952Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"preds = model.predict(test_gen, verbose=1)\ntest_df[\"diagnosis\"] = np.argmax(preds, axis=1)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-02-07T05:45:40.102921Z","iopub.execute_input":"2025-02-07T05:45:40.103261Z","iopub.status.idle":"2025-02-07T05:47:22.676592Z","shell.execute_reply.started":"2025-02-07T05:45:40.103230Z","shell.execute_reply":"2025-02-07T05:47:22.675712Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"submission_csv = \"submission.csv\"\ntest_df[[\"id_code\", \"diagnosis\"]].to_csv(submission_csv, index=False)\nprint(f\"Submission file saved as {submission_csv}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-02-07T05:47:22.677805Z","iopub.execute_input":"2025-02-07T05:47:22.678059Z","iopub.status.idle":"2025-02-07T05:47:22.691529Z","shell.execute_reply.started":"2025-02-07T05:47:22.678035Z","shell.execute_reply":"2025-02-07T05:47:22.690744Z"}},"outputs":[],"execution_count":null}]}