{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.11.13","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"nvidiaTeslaT4","dataSources":[{"sourceId":4104,"databundleVersionId":46661,"sourceType":"competition"},{"sourceId":7866129,"sourceType":"datasetVersion","datasetId":4614938}],"dockerImageVersionId":31090,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"!nvidia-smi","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T10:14:48.897630Z","iopub.execute_input":"2025-07-30T10:14:48.897890Z","iopub.status.idle":"2025-07-30T10:14:49.121405Z","shell.execute_reply.started":"2025-07-30T10:14:48.897863Z","shell.execute_reply":"2025-07-30T10:14:49.120760Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Libraries","metadata":{}},{"cell_type":"code","source":"import pandas as pd\nfrom glob import glob\nimport matplotlib.pyplot as plt\nimport cv2\nimport tensorflow as tf\nimport numpy as np\nimport os\nfrom sklearn.model_selection import train_test_split\nfrom tensorflow.keras import layers, models, callbacks, mixed_precision\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T10:17:42.264897Z","iopub.execute_input":"2025-07-30T10:17:42.265227Z","iopub.status.idle":"2025-07-30T10:18:02.949352Z","shell.execute_reply.started":"2025-07-30T10:17:42.265194Z","shell.execute_reply":"2025-07-30T10:18:02.948780Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import wandb\nfrom kaggle_secrets import UserSecretsClient\nuser_secrets = UserSecretsClient()\nsecret_value_0 = user_secrets.get_secret(\"WANDB_API_KEY\")\n\nwandb.login(key=secret_value_0)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T10:18:02.950405Z","iopub.execute_input":"2025-07-30T10:18:02.950925Z","iopub.status.idle":"2025-07-30T10:18:12.400372Z","shell.execute_reply.started":"2025-07-30T10:18:02.950903Z","shell.execute_reply":"2025-07-30T10:18:12.399828Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# import tensorflow as tf\nprint(tf.__version__)\n# Check if a GPU is available\ngpus = tf.config.list_physical_devices('GPU')\nif gpus:\n    try:\n        # Set memory growth to prevent TensorFlow from allocating all memory at once\n        for gpu in gpus:\n            tf.config.experimental.set_memory_growth(gpu, True)\n        print(\"GPU is available and will be used.\")\n    except RuntimeError as e:\n        # Memory growth must be set before GPUs have been initialized\n        print(f\"Error: {e}\")\nelse:\n    print(\"GPU is not available, running on CPU.\")\n\n\ntf.test.is_gpu_available()\n\npolicy = mixed_precision.Policy('mixed_float16')\nmixed_precision.set_global_policy(policy)\nprint(\"Mixed precision enabled:\", policy)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T10:23:25.104751Z","iopub.execute_input":"2025-07-30T10:23:25.105103Z","iopub.status.idle":"2025-07-30T10:23:27.175358Z","shell.execute_reply.started":"2025-07-30T10:23:25.105082Z","shell.execute_reply":"2025-07-30T10:23:27.174503Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Imports","metadata":{}},{"cell_type":"code","source":"IMG_SIZE = 224\nBATCH_SIZE = 8\nEPOCHS = 3\nFROZEN_EPOCHS = 2\n\ntrain_csv_path = \"/kaggle/input/diabetic-retinopathy-detection/trainLabels.csv.zip\"\ntrain_images_dir = \"/kaggle/input/diabetic-retinopathy-train-unzipped/train/\"\ntest_images_dir = \"/kaggle/input/diabetic-retinopathy-test-unzipped/test/\"\nsubmission_csv_path = \"/kaggle/input/diabetic-retinopathy-detection/sampleSubmission.csv.zip\"","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T10:23:27.635527Z","iopub.execute_input":"2025-07-30T10:23:27.636247Z","iopub.status.idle":"2025-07-30T10:23:27.640014Z","shell.execute_reply.started":"2025-07-30T10:23:27.636223Z","shell.execute_reply":"2025-07-30T10:23:27.639275Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"img_number = 10016\n\ndf = pd.read_csv(train_csv_path)\ndf_train = df[:img_number].copy()\ndf_train.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T10:23:28.191520Z","iopub.execute_input":"2025-07-30T10:23:28.192164Z","iopub.status.idle":"2025-07-30T10:23:28.265589Z","shell.execute_reply.started":"2025-07-30T10:23:28.192138Z","shell.execute_reply":"2025-07-30T10:23:28.264830Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"**Train Test Split**","metadata":{}},{"cell_type":"code","source":"# Convert multiclass level to binary: 0 = No DR, 1 = DR Present\ndf_train[\"Label\"] = df_train[\"level\"].apply(lambda x: False if x == 0 else True)\n\ndf_train[\"filepath\"] = df_train[\"image\"].apply(lambda x: os.path.join(train_images_dir, f\"{x}.jpeg\"))\n\ntrain_df, val_df = train_test_split(df_train, test_size=0.4, stratify=df_train[\"Label\"], random_state=42)\nval_df, test_df = train_test_split(val_df, test_size=0.5, stratify=val_df[\"Label\"], random_state=42)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T10:23:29.443657Z","iopub.execute_input":"2025-07-30T10:23:29.444315Z","iopub.status.idle":"2025-07-30T10:23:29.489648Z","shell.execute_reply.started":"2025-07-30T10:23:29.444288Z","shell.execute_reply":"2025-07-30T10:23:29.488733Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print(train_df.shape, val_df.shape, test_df.shape)\n# train_df.filepath[0]\ntrain_df","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T10:23:29.895592Z","iopub.execute_input":"2025-07-30T10:23:29.895984Z","iopub.status.idle":"2025-07-30T10:23:29.908412Z","shell.execute_reply.started":"2025-07-30T10:23:29.895952Z","shell.execute_reply":"2025-07-30T10:23:29.907550Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Visualization","metadata":{}},{"cell_type":"code","source":"import cv2\nimport matplotlib.pyplot as plt\n\nplt.figure(figsize=(15, 15))\n\n# Show first 25 images from train_df\nfor idx, (i, row) in enumerate(train_df.head(25).iterrows()):\n    plt.subplot(5, 5, idx + 1)\n    plt.xticks([])\n    plt.yticks([])\n    plt.grid(False)\n    \n    # Load and preprocess image\n    img_path = row['filepath']\n    img = cv2.imread(img_path)\n    \n    if img is None:\n        print(f\"Warning: Image not found at {img_path}\")\n        continue\n    \n    img = cv2.resize(img, (224, 224))\n    img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)\n    \n    # Set label from binary column\n    label = row.get('binary_label', row.get('Label', None))\n    label_text = 'Yes' if label else 'No'\n    \n    plt.imshow(img)\n    plt.xlabel(label_text, fontsize=12, color='green' if label else 'red')\n\nplt.tight_layout()\nplt.suptitle(\"Sample Images with Binary DR Labels\", fontsize=20, y=1.02)\nplt.show()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T10:23:32.416742Z","iopub.execute_input":"2025-07-30T10:23:32.417326Z","iopub.status.idle":"2025-07-30T10:23:36.414048Z","shell.execute_reply.started":"2025-07-30T10:23:32.417301Z","shell.execute_reply":"2025-07-30T10:23:36.413258Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Evaluation Functions","metadata":{}},{"cell_type":"markdown","source":"## Results","metadata":{}},{"cell_type":"code","source":"# from sklearn.metrics import (\n#     accuracy_score, precision_score, recall_score, f1_score, roc_auc_score,\n#     average_precision_score, confusion_matrix, cohen_kappa_score,\n#     precision_recall_curve, roc_curve\n# )\n# import tensorflow as tf\n# import pandas as pd\n# import numpy as np\n# import os\n\n# def Results(model, model_name,test_set, save_csv=False):\n#     # Evaluate the model\n#     results = model.evaluate(test_set)\n#     print(\"Evaluation results: \", results)\n\n#     y_true = []\n#     y_pred_probs = []\n\n#     print(\"Loading....\", flush=True)\n\n#     for images, labels in test_set:\n#         y_true.extend(labels.numpy())\n#         y_pred_probs.extend(model.predict(images, verbose=0).flatten())\n\n#     y_true = tf.convert_to_tensor(y_true)\n#     y_pred_probs = tf.convert_to_tensor(y_pred_probs)\n#     y_pred = (y_pred_probs > 0.5).numpy().astype(\"int32\")\n\n#     acc = accuracy_score(y_true, y_pred)\n#     precision = precision_score(y_true, y_pred, zero_division=1)\n#     recall = recall_score(y_true, y_pred)\n#     f1 = f1_score(y_true, y_pred)\n#     roc_auc = roc_auc_score(y_true, y_pred_probs)\n#     prc_auc = average_precision_score(y_true, y_pred_probs)\n#     conf_matrix = confusion_matrix(y_true, y_pred)\n#     kappa = cohen_kappa_score(y_true, y_pred)\n#     tn, fp, fn, tp = conf_matrix.ravel()\n#     npv = tn / (tn + fn)\n\n#     print(f\"Accuracy: {acc}\")\n#     print(f\"Precision: {precision}\")\n#     print(f\"Recall: {recall}\")\n#     print(f\"F1 Score: {f1}\")\n#     print(f\"ROC AUC: {roc_auc}\")\n#     print(f\"PRC AUC: {prc_auc}\")\n#     print(f\"Confusion Matrix: \\n{conf_matrix}\")\n#     print(f\"Kappa Coefficient: {kappa}\")\n#     print(f\"NPV: {npv}\")\n\n#     if save_csv:\n#         # Compute ROC and Precision-Recall curves\n#         fpr, tpr, _ = roc_curve(y_true, y_pred_probs)\n#         prec, rec, _ = precision_recall_curve(y_true, y_pred_probs)\n\n#         # Prepare DataFrame\n#         max_len = max(len(fpr), len(prec))\n#         fpr = np.pad(fpr, (0, max_len - len(fpr)), 'constant', constant_values=np.nan)\n#         tpr = np.pad(tpr, (0, max_len - len(tpr)), 'constant', constant_values=np.nan)\n#         prec = np.pad(prec, (0, max_len - len(prec)), 'constant', constant_values=np.nan)\n#         rec = np.pad(rec, (0, max_len - len(rec)), 'constant', constant_values=np.nan)\n\n#         df = pd.DataFrame({\n#             'FPR': fpr,\n#             'TPR': tpr,\n#             'Precision': prec,\n#             'Recall': rec\n#         })\n\n\n#         file_name = model_name\n#         df.to_csv(file_name, index=False)\n#         print(f\"Saved metrics to: {file_name}\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T10:23:38.357310Z","iopub.execute_input":"2025-07-30T10:23:38.357676Z","iopub.status.idle":"2025-07-30T10:23:38.363404Z","shell.execute_reply.started":"2025-07-30T10:23:38.357650Z","shell.execute_reply":"2025-07-30T10:23:38.362400Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from sklearn.metrics import (\n    accuracy_score, precision_score, recall_score, f1_score, roc_auc_score,\n    average_precision_score, confusion_matrix, cohen_kappa_score,\n    precision_recall_curve, roc_curve\n)\nimport tensorflow as tf\nimport pandas as pd\nimport numpy as np\nimport os\nimport wandb\nimport matplotlib.pyplot as plt\n\ndef Results(model, test_set, model_name=\"Model\", save_csv=False, wandb_log=False):\n    # Evaluate the model\n    results = model.evaluate(test_set)\n    print(\"Evaluation results: \", results)\n\n    y_true = []\n    y_pred_probs = []\n\n    print(\"Loading....\", flush=True)\n\n    for images, labels in test_set:\n        y_true.extend(labels.numpy())\n        y_pred_probs.extend(model.predict(images, verbose=0).flatten())\n\n    y_true = tf.convert_to_tensor(y_true)\n    y_pred_probs = tf.convert_to_tensor(y_pred_probs)\n    y_pred = (y_pred_probs > 0.5).numpy().astype(\"int32\")\n\n    acc = accuracy_score(y_true, y_pred)\n    precision = precision_score(y_true, y_pred, zero_division=1)\n    recall = recall_score(y_true, y_pred)\n    f1 = f1_score(y_true, y_pred)\n    roc_auc = roc_auc_score(y_true, y_pred_probs)\n    prc_auc = average_precision_score(y_true, y_pred_probs)\n    conf_matrix = confusion_matrix(y_true, y_pred)\n    kappa = cohen_kappa_score(y_true, y_pred)\n    tn, fp, fn, tp = conf_matrix.ravel()\n    npv = tn / (tn + fn)\n\n    # Print metrics\n    print(f\"Accuracy: {acc}\")\n    print(f\"Precision: {precision}\")\n    print(f\"Recall: {recall}\")\n    print(f\"F1 Score: {f1}\")\n    print(f\"ROC AUC: {roc_auc}\")\n    print(f\"PRC AUC: {prc_auc}\")\n    print(f\"Confusion Matrix: \\n{conf_matrix}\")\n    print(f\"Kappa Coefficient: {kappa}\")\n    print(f\"NPV: {npv}\")\n\n    # Log metrics to W&B\n    if wandb_log:\n        wandb.log({\n            \"Accuracy\": acc,\n            \"Precision\": precision,\n            \"Recall\": recall,\n            \"F1 Score\": f1,\n            \"ROC AUC\": roc_auc,\n            \"PRC AUC\": prc_auc,\n            \"Kappa\": kappa,\n            \"NPV\": npv\n        })\n\n    if save_csv or wandb_log:\n        # Compute ROC and Precision-Recall curves\n        fpr, tpr, _ = roc_curve(y_true, y_pred_probs)\n        prec, rec, _ = precision_recall_curve(y_true, y_pred_probs)\n\n        # Pad arrays to same length\n        max_len = max(len(fpr), len(prec))\n        fpr = np.pad(fpr, (0, max_len - len(fpr)), 'constant', constant_values=np.nan)\n        tpr = np.pad(tpr, (0, max_len - len(tpr)), 'constant', constant_values=np.nan)\n        prec = np.pad(prec, (0, max_len - len(prec)), 'constant', constant_values=np.nan)\n        rec = np.pad(rec, (0, max_len - len(rec)), 'constant', constant_values=np.nan)\n\n        df = pd.DataFrame({\n            'FPR': fpr,\n            'TPR': tpr,\n            'Precision': prec,\n            'Recall': rec\n        })\n\n        file_name = model_name+'.metrices.csv'\n        df.to_csv(file_name, index=False)\n        print(f\"Saved metrics to: {file_name}\")\n\n        if wandb_log:\n            wandb.save(file_name)\n\n            # Plot ROC Curve\n            plt.figure()\n            plt.plot(fpr, tpr, label=f'ROC AUC = {roc_auc:.2f}')\n            plt.xlabel(\"False Positive Rate\")\n            plt.ylabel(\"True Positive Rate\")\n            plt.title(\"ROC Curve\")\n            plt.legend()\n            wandb.log({\"ROC Curve\": wandb.Image(plt)})\n            plt.close()\n\n            # Plot PR Curve\n            plt.figure()\n            plt.plot(rec, prec, label=f'PRC AUC = {prc_auc:.2f}')\n            plt.xlabel(\"Recall\")\n            plt.ylabel(\"Precision\")\n            plt.title(\"Precision-Recall Curve\")\n            plt.legend()\n            wandb.log({\"PR Curve\": wandb.Image(plt)})\n            plt.close()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T10:23:38.624865Z","iopub.execute_input":"2025-07-30T10:23:38.625228Z","iopub.status.idle":"2025-07-30T10:23:38.638985Z","shell.execute_reply.started":"2025-07-30T10:23:38.625206Z","shell.execute_reply":"2025-07-30T10:23:38.638093Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score, roc_auc_score, average_precision_score, confusion_matrix, cohen_kappa_score\nimport tensorflow as tf\n\ndef Results_old(model, test_set):\n    # Evaluate the model\n    results = model.evaluate(test_set)\n    print(\"Evaluation results: \", results)\n\n    y_true = []\n    y_pred_probs = []\n\n    print(\"Loading....\", flush=True)\n\n    for images, labels in test_set:\n        y_true.extend(labels.numpy())\n        y_pred_probs.extend(model.predict(images, verbose=0).flatten())\n\n    y_true = tf.convert_to_tensor(y_true)\n    y_pred_probs = tf.convert_to_tensor(y_pred_probs)\n    y_pred = (y_pred_probs > 0.5).numpy().astype(\"int32\")\n\n    acc = accuracy_score(y_true, y_pred)\n    precision = precision_score(y_true, y_pred, zero_division=1)\n    recall = recall_score(y_true, y_pred)\n    f1 = f1_score(y_true, y_pred)\n    roc_auc = roc_auc_score(y_true, y_pred_probs)\n    prc_auc = average_precision_score(y_true, y_pred_probs)\n    conf_matrix = confusion_matrix(y_true, y_pred)\n    kappa = cohen_kappa_score(y_true, y_pred)\n    tn, fp, fn, tp = conf_matrix.ravel()\n    npv = tn / (tn + fn)\n\n    print(f\"Accuracy: {acc}\")\n    print(f\"Precision: {precision}\")\n    print(f\"Recall: {recall}\")\n    print(f\"F1 Score: {f1}\")\n    print(f\"ROC AUC: {roc_auc}\")\n    print(f\"PRC AUC: {prc_auc}\")\n    print(f\"Confusion Matrix: \\n{conf_matrix}\")\n    print(f\"Kappa Coefficient: {kappa}\")\n    print(f\"NPV: {npv}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T10:23:39.128827Z","iopub.execute_input":"2025-07-30T10:23:39.129413Z","iopub.status.idle":"2025-07-30T10:23:39.136801Z","shell.execute_reply.started":"2025-07-30T10:23:39.129388Z","shell.execute_reply":"2025-07-30T10:23:39.135950Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## MACS & FLOPS","metadata":{}},{"cell_type":"code","source":"import tensorflow as tf\nfrom tensorflow.python.framework.convert_to_constants import convert_variables_to_constants_v2_as_graph\n\ndef get_flops(model, input_shape):\n    # Convert Keras model to ConcreteFunction\n    concrete_func = tf.function(model).get_concrete_function(tf.TensorSpec(input_shape, tf.float32))\n    \n    # Convert ConcreteFunction to a frozen graph\n    frozen_func, graph_def = convert_variables_to_constants_v2_as_graph(concrete_func)\n    \n    # Create a session to run the frozen graph\n    with tf.compat.v1.Session(graph=tf.Graph()) as sess:\n        tf.import_graph_def(graph_def, name=\"\")\n        graph = tf.compat.v1.get_default_graph()\n        \n        # Calculate FLOPs using TensorFlow profiler\n        run_meta = tf.compat.v1.RunMetadata()\n        opts = tf.compat.v1.profiler.ProfileOptionBuilder.float_operation()\n        flops = tf.compat.v1.profiler.profile(graph=graph, run_meta=run_meta, cmd='op', options=opts)\n        \n    return flops.total_float_ops","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T10:23:40.796708Z","iopub.execute_input":"2025-07-30T10:23:40.797326Z","iopub.status.idle":"2025-07-30T10:23:40.802820Z","shell.execute_reply.started":"2025-07-30T10:23:40.797298Z","shell.execute_reply":"2025-07-30T10:23:40.801841Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# # Define input shape\n# input_shape = (1, 224, 224,3 )\n# # Calculate FLOPs\n# flops = get_flops(model, input_shape)\n# macs = flops // 2  # MACs is half the FLOPs for Conv2D\n\n# print(f\"MACs: {macs}\")\n# print(f\"FLOPs: {flops}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T10:23:40.960393Z","iopub.execute_input":"2025-07-30T10:23:40.960925Z","iopub.status.idle":"2025-07-30T10:23:40.964440Z","shell.execute_reply.started":"2025-07-30T10:23:40.960898Z","shell.execute_reply":"2025-07-30T10:23:40.963562Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## Parameters","metadata":{}},{"cell_type":"code","source":"import numpy as np\n\ndef model_parametersInfo(model):\n    \"\"\"\n    Prints total, trainable, and non-trainable parameters of a Keras model.\n    \"\"\"\n    total_params = model.count_params()\n    trainable_params = np.sum([np.prod(v.shape) for v in model.trainable_variables])\n    non_trainable_params = np.sum([np.prod(v.shape) for v in model.non_trainable_variables])\n\n    print(f\"Total params: {total_params:,}\")\n    print(f\"Trainable params: {trainable_params:,}\")\n    print(f\"Non-trainable params: {non_trainable_params:,}\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T10:23:41.308745Z","iopub.execute_input":"2025-07-30T10:23:41.309011Z","iopub.status.idle":"2025-07-30T10:23:41.313787Z","shell.execute_reply.started":"2025-07-30T10:23:41.308993Z","shell.execute_reply":"2025-07-30T10:23:41.312989Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## Inference Report","metadata":{}},{"cell_type":"code","source":"import tensorflow as tf\nimport psutil\nimport os\nimport time\n\ndef inference_Report(model, test_set):\n    process = psutil.Process(os.getpid())\n\n    if tf.config.list_physical_devices('GPU'):\n        gpu_enabled = True\n        gpu_device = 'GPU:0'\n    else:\n        gpu_enabled = False\n\n    print(\"🔍 Capturing memory stats and inference time for 100 images...\\n\")\n\n    # --- Before Inference ---\n    ram_before = process.memory_info().rss\n    gpu_before = tf.config.experimental.get_memory_info(gpu_device)['current'] if gpu_enabled else 0\n\n    total_images = 0\n    start_time = time.time()\n\n    for images, _ in test_set:\n        for i in range(images.shape[0]):\n            if total_images >= 100:\n                break\n            image = tf.expand_dims(images[i], axis=0)\n            _ = model(image, training=False)\n            total_images += 1\n        if total_images >= 100:\n            break\n\n    end_time = time.time()\n\n    # --- After Inference ---\n    ram_after = process.memory_info().rss\n    gpu_after = tf.config.experimental.get_memory_info(gpu_device)['current'] if gpu_enabled else 0\n\n    # --- Results ---\n    print(\"📊 Inference Resource Usage Summary (100 images):\")\n    print(f\"CPU RAM Before: {ram_before / (1024 ** 2):.2f} MB\")\n    print(f\"CPU RAM After : {ram_after / (1024 ** 2):.2f} MB\")\n    print(f\"CPU RAM Used  : {(ram_after - ram_before) / (1024 ** 2):.2f} MB\\n\")\n\n    if gpu_enabled:\n        print(f\"GPU Mem Before: {gpu_before / (1024 ** 2):.2f} MB\")\n        print(f\"GPU Mem After : {gpu_after / (1024 ** 2):.2f} MB\")\n        print(f\"GPU Mem Used  : {(gpu_after - gpu_before) / (1024 ** 2):.2f} MB\\n\")\n    else:\n        print(\"GPU Not Detected.\\n\")\n    time_per_img = (end_time - start_time)/100\n    print(f\"🕒 Inference Time per image: {time_per_img:.4f} seconds\")\n\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T10:23:43.433266Z","iopub.execute_input":"2025-07-30T10:23:43.434003Z","iopub.status.idle":"2025-07-30T10:23:43.441207Z","shell.execute_reply.started":"2025-07-30T10:23:43.433975Z","shell.execute_reply":"2025-07-30T10:23:43.440406Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Data Pipeline","metadata":{}},{"cell_type":"code","source":"def retreive_dataset(set_name):\n    images,labels=[],[]\n    def imgResize(img,width,height):\n        imgResize = cv2.resize(img,(width,height))\n        return imgResize\n    \n    for (img, imclass) in zip(set_name['filepath'], set_name['Label']):\n        img = cv2.imread(img)\n\n        # img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)   #BGR to RGB\n        img = cv2.resize(img, (224, 224))    \n        # img = img.astype(np.float32) / 255.0   #preprocess\n        images.append(img)\n        if(imclass==True):\n            labels.append(1)\n        else:\n            labels.append(0)\n    print(f\"Done\")\n    return np.array(images),np.array(labels)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T10:23:44.796787Z","iopub.execute_input":"2025-07-30T10:23:44.797512Z","iopub.status.idle":"2025-07-30T10:23:44.802398Z","shell.execute_reply.started":"2025-07-30T10:23:44.797490Z","shell.execute_reply":"2025-07-30T10:23:44.801502Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"X_train,y_train=retreive_dataset(train_df)\nX_val,y_val=retreive_dataset(val_df)\nX_test,y_test=retreive_dataset(test_df)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T10:23:44.964191Z","iopub.execute_input":"2025-07-30T10:23:44.964844Z","iopub.status.idle":"2025-07-30T10:33:07.563705Z","shell.execute_reply.started":"2025-07-30T10:23:44.964817Z","shell.execute_reply":"2025-07-30T10:33:07.562828Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"\n\nindex = 0  # Change this to view another image\nimage = X_train[index]\nlabel = y_train[index]\n\nplt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))\nplt.title(f\"Label: {'DR Present' if label == 1 else 'No DR'}\")\nplt.axis('off')\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T10:33:07.565132Z","iopub.execute_input":"2025-07-30T10:33:07.565370Z","iopub.status.idle":"2025-07-30T10:33:07.758576Z","shell.execute_reply.started":"2025-07-30T10:33:07.565352Z","shell.execute_reply":"2025-07-30T10:33:07.757766Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_set_raw=tf.data.Dataset.from_tensor_slices((X_train,y_train))\nvalid_set_raw=tf.data.Dataset.from_tensor_slices((X_val,y_val))\ntest_set_raw=tf.data.Dataset.from_tensor_slices((X_test,y_test))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T10:33:07.759539Z","iopub.execute_input":"2025-07-30T10:33:07.759813Z","iopub.status.idle":"2025-07-30T10:33:11.598645Z","shell.execute_reply.started":"2025-07-30T10:33:07.759768Z","shell.execute_reply":"2025-07-30T10:33:11.598049Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# EfficientNet","metadata":{}},{"cell_type":"code","source":"tf.keras.backend.clear_session()  # extra code – resets layer name counter\n\nbatch_size = 32\npreprocess = tf.keras.applications.efficientnet.preprocess_input\ntrain_set = train_set_raw.map(lambda X, y: (preprocess(tf.cast(X, tf.float32)), y))\ntrain_set = train_set.shuffle(1000, seed=42).batch(batch_size).prefetch(1)\nvalid_set = valid_set_raw.map(lambda X, y: (preprocess(tf.cast(X, tf.float32)), y)).batch(batch_size)\ntest_set = test_set_raw.map(lambda X, y: (preprocess(tf.cast(X, tf.float32)), y)).batch(batch_size)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T10:33:32.226735Z","iopub.execute_input":"2025-07-30T10:33:32.227481Z","iopub.status.idle":"2025-07-30T10:33:35.383917Z","shell.execute_reply.started":"2025-07-30T10:33:32.227456Z","shell.execute_reply":"2025-07-30T10:33:35.383279Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"plt.figure(figsize=(12, 12))\nfor X_batch, y_batch in train_set.take(1):\n    for index in range(9):\n        plt.subplot(3, 3, index + 1)\n        img = (X_batch[index].numpy())\n        img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)\n        plt.imshow(img /np.max(img)) # rescale to 0–1 for imshow()\n        if(y_batch[index]==1):\n            classt= 'DR Present'\n        else:\n            classt= \"No DR\"\n        plt.title(f\"Class: {classt}\")\n        plt.axis(\"off\")\n\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T10:33:39.422581Z","iopub.execute_input":"2025-07-30T10:33:39.423335Z","iopub.status.idle":"2025-07-30T10:33:41.715146Z","shell.execute_reply.started":"2025-07-30T10:33:39.423297Z","shell.execute_reply":"2025-07-30T10:33:41.714295Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"tf.random.set_seed(42)  # Ensures reproducibility\n\ntf.keras.backend.clear_session()\n# Ensures reproducibility\n\n\nbase_model = tf.keras.applications.EfficientNetB0(weights=\"imagenet\", include_top=False)\navg = tf.keras.layers.GlobalAveragePooling2D()(base_model.output)\noutput = tf.keras.layers.Dense(1, activation=\"sigmoid\")(avg)\nmodel = tf.keras.Model(inputs=base_model.input, outputs=output)\nfor layer in base_model.layers:\n    layer.trainable = False","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T10:33:54.347347Z","iopub.execute_input":"2025-07-30T10:33:54.347986Z","iopub.status.idle":"2025-07-30T10:33:56.975339Z","shell.execute_reply.started":"2025-07-30T10:33:54.347962Z","shell.execute_reply":"2025-07-30T10:33:56.974726Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"optimizer = tf.keras.optimizers.Adam(learning_rate=0.0001)\nmodel.compile(loss=\"binary_crossentropy\", optimizer=optimizer,\n              metrics=[\"accuracy\"])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T10:34:16.493276Z","iopub.execute_input":"2025-07-30T10:34:16.493967Z","iopub.status.idle":"2025-07-30T10:34:16.507754Z","shell.execute_reply.started":"2025-07-30T10:34:16.493937Z","shell.execute_reply":"2025-07-30T10:34:16.507165Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-29T07:22:04.625122Z","iopub.execute_input":"2025-07-29T07:22:04.625419Z","iopub.status.idle":"2025-07-29T07:22:06.327352Z","shell.execute_reply.started":"2025-07-29T07:22:04.625398Z","shell.execute_reply":"2025-07-29T07:22:06.326616Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"wandb.init(\n    project=\"Diabetic Retinopathy Detection\",   # change this\n    name=\"EfficientNetB0\",        # optional\n    config={                       # optional: log hyperparameters\n        \"epochs\": 10,\n        \"batch_size\": 32,\n        \"learning_rate\": 0.001\n    }\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T10:34:40.037141Z","iopub.execute_input":"2025-07-30T10:34:40.037640Z","iopub.status.idle":"2025-07-30T10:34:50.261821Z","shell.execute_reply.started":"2025-07-30T10:34:40.037615Z","shell.execute_reply":"2025-07-30T10:34:50.261164Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-29T07:18:35.39783Z","iopub.execute_input":"2025-07-29T07:18:35.398368Z","iopub.status.idle":"2025-07-29T07:18:41.62801Z","shell.execute_reply.started":"2025-07-29T07:18:35.39834Z","shell.execute_reply":"2025-07-29T07:18:41.627385Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from tensorflow.keras.callbacks import ModelCheckpoint, CSVLogger\n# from wandb.keras import WandbMetricsLogger, WandbModelCheckpoint\n\nmodel_name = \"DR_EfficentNetB0\"\n\n# checkpoint_callback = ModelCheckpoint(\n#     filepath='best_model.keras',  # Path to save the model\n#     monitor='val_accuracy',        # yMetric to monitor\n#     save_best_only=True,       # Save only the best model\n#     save_weights_only=False,   # Save the entire model, not just weights\n#     mode='max',                # Mode to minimize the monitored metric\n#     verbose=1                  # Verbosity mode\n# )\ncsv_logger = CSVLogger(model_name+'.csv',append = True)\n\n# callbacks = [checkpoint_callback,csv_logger]\ncallbacks = [csv_logger,wandb.keras.WandbMetricsLogger(log_freq=5)]","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T10:35:18.298815Z","iopub.execute_input":"2025-07-30T10:35:18.299106Z","iopub.status.idle":"2025-07-30T10:35:18.353334Z","shell.execute_reply.started":"2025-07-30T10:35:18.299085Z","shell.execute_reply":"2025-07-30T10:35:18.352437Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"history = model.fit(train_set, validation_data=valid_set, epochs=10, callbacks= callbacks)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T10:35:31.766698Z","iopub.execute_input":"2025-07-30T10:35:31.767009Z","iopub.status.idle":"2025-07-30T10:38:00.476755Z","shell.execute_reply.started":"2025-07-30T10:35:31.766981Z","shell.execute_reply":"2025-07-30T10:38:00.476160Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model.save_weights(model_name+'.weights.h5')\n\n# model.load_weights('/kaggle/working/DR_Xception.weights.h5')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T10:38:00.477987Z","iopub.execute_input":"2025-07-30T10:38:00.478206Z","iopub.status.idle":"2025-07-30T10:38:01.007013Z","shell.execute_reply.started":"2025-07-30T10:38:00.478189Z","shell.execute_reply":"2025-07-30T10:38:01.006249Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"Results(model,test_set,model_name=model_name,save_csv=True,wandb_log=True)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T10:38:01.007896Z","iopub.execute_input":"2025-07-30T10:38:01.008181Z","iopub.status.idle":"2025-07-30T10:38:30.686316Z","shell.execute_reply.started":"2025-07-30T10:38:01.008156Z","shell.execute_reply":"2025-07-30T10:38:30.685421Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"wandb.save(f\"/kaggle/working/{model_name}.metrices.csv\", policy=\"now\")\nwandb.save(f\"/kaggle/working/{model_name}.weights.h5\", policy=\"now\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T10:38:30.688029Z","iopub.execute_input":"2025-07-30T10:38:30.688300Z","iopub.status.idle":"2025-07-30T10:38:30.700431Z","shell.execute_reply.started":"2025-07-30T10:38:30.688278Z","shell.execute_reply":"2025-07-30T10:38:30.699530Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"inference_Report(model,test_set)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T10:38:30.701313Z","iopub.execute_input":"2025-07-30T10:38:30.701650Z","iopub.status.idle":"2025-07-30T10:38:59.603628Z","shell.execute_reply.started":"2025-07-30T10:38:30.701628Z","shell.execute_reply":"2025-07-30T10:38:59.602821Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Define input shape\ninput_shape = (1, 224, 224,3 )\n# Calculate FLOPs\nflops = get_flops(model, input_shape)\nmacs = flops // 2  # MACs is half the FLOPs for Conv2D\n\nprint(f\"MACs: {macs}\")\nprint(f\"FLOPs: {flops}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T10:38:59.604504Z","iopub.execute_input":"2025-07-30T10:38:59.604740Z","iopub.status.idle":"2025-07-30T10:39:06.773885Z","shell.execute_reply.started":"2025-07-30T10:38:59.604710Z","shell.execute_reply":"2025-07-30T10:39:06.773090Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model_parametersInfo(model)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T10:39:06.774671Z","iopub.execute_input":"2025-07-30T10:39:06.774915Z","iopub.status.idle":"2025-07-30T10:39:06.788001Z","shell.execute_reply.started":"2025-07-30T10:39:06.774897Z","shell.execute_reply":"2025-07-30T10:39:06.787340Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"wandb.finish()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T10:39:06.788655Z","iopub.execute_input":"2025-07-30T10:39:06.788906Z","iopub.status.idle":"2025-07-30T10:39:07.365974Z","shell.execute_reply.started":"2025-07-30T10:39:06.788888Z","shell.execute_reply":"2025-07-30T10:39:07.365339Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# EfficientNet fine tuned","metadata":{}},{"cell_type":"code","source":"n =len(base_model.layers)\nL = int(0.3*n)  # 30% of n\nf\"{L} trainable of {n} layers\"","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T10:39:18.934481Z","iopub.execute_input":"2025-07-30T10:39:18.934803Z","iopub.status.idle":"2025-07-30T10:39:18.940347Z","shell.execute_reply.started":"2025-07-30T10:39:18.934756Z","shell.execute_reply":"2025-07-30T10:39:18.939534Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"for layer in base_model.layers[-L:]:\n    layer.trainable = True","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T10:39:39.353577Z","iopub.execute_input":"2025-07-30T10:39:39.354423Z","iopub.status.idle":"2025-07-30T10:39:39.359630Z","shell.execute_reply.started":"2025-07-30T10:39:39.354394Z","shell.execute_reply":"2025-07-30T10:39:39.358714Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"optimizer = tf.keras.optimizers.Adam(learning_rate=0.0001)\nmodel.compile(loss=\"binary_crossentropy\", optimizer=optimizer,\n              metrics=[\"accuracy\"])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T10:39:40.625364Z","iopub.execute_input":"2025-07-30T10:39:40.625643Z","iopub.status.idle":"2025-07-30T10:39:40.647094Z","shell.execute_reply.started":"2025-07-30T10:39:40.625620Z","shell.execute_reply":"2025-07-30T10:39:40.646271Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"wandb.init(\n    project=\"Diabetic Retinopathy Detection\", \n    name=\"EfficientNetB0_ft\",   # Change this to \"VGG_Model_Run\", etc. for next model\n    resume=\"allow\"\n)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T10:47:46.791336Z","iopub.execute_input":"2025-07-30T10:47:46.791959Z","iopub.status.idle":"2025-07-30T10:47:53.653391Z","shell.execute_reply.started":"2025-07-30T10:47:46.791933Z","shell.execute_reply":"2025-07-30T10:47:53.652608Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model_name = model_name+'_ft'\nmodel_name","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-29T12:36:14.726887Z","iopub.execute_input":"2025-07-29T12:36:14.727478Z","iopub.status.idle":"2025-07-29T12:36:14.732182Z","shell.execute_reply.started":"2025-07-29T12:36:14.727457Z","shell.execute_reply":"2025-07-29T12:36:14.731481Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from tensorflow.keras.callbacks import ModelCheckpoint, CSVLogger\n\ncsv_logger = CSVLogger(model_name+'.csv',append = True)\n\ncallbacks = [csv_logger,wandb.keras.WandbMetricsLogger(log_freq=5)]","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T10:40:13.924643Z","iopub.execute_input":"2025-07-30T10:40:13.925309Z","iopub.status.idle":"2025-07-30T10:40:13.931422Z","shell.execute_reply.started":"2025-07-30T10:40:13.925281Z","shell.execute_reply":"2025-07-30T10:40:13.930534Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"history = model.fit(train_set, validation_data=valid_set, epochs=10, callbacks= callbacks)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T10:40:16.519349Z","iopub.execute_input":"2025-07-30T10:40:16.519640Z","iopub.status.idle":"2025-07-30T10:43:37.277520Z","shell.execute_reply.started":"2025-07-30T10:40:16.519619Z","shell.execute_reply":"2025-07-30T10:43:37.276640Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model.save_weights(model_name+'.weights.h5')\n\n# model.load_weights('/kaggle/working/DR_Xception.weights.h5')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T10:45:12.946522Z","iopub.execute_input":"2025-07-30T10:45:12.947412Z","iopub.status.idle":"2025-07-30T10:45:13.551503Z","shell.execute_reply.started":"2025-07-30T10:45:12.947380Z","shell.execute_reply":"2025-07-30T10:45:13.550652Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"\nResults(model,test_set,model_name=model_name,save_csv=True,wandb_log=True)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T10:48:06.370478Z","iopub.execute_input":"2025-07-30T10:48:06.370808Z","iopub.status.idle":"2025-07-30T10:48:15.973561Z","shell.execute_reply.started":"2025-07-30T10:48:06.370763Z","shell.execute_reply":"2025-07-30T10:48:15.972920Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"wandb.save(f\"/kaggle/working/{model_name}.metrices.csv\", policy=\"now\")\nwandb.save(f\"/kaggle/working/{model_name}.weights.h5\", policy=\"now\")\nprint(f\"saved to wandb {model_name}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T10:48:49.256994Z","iopub.execute_input":"2025-07-30T10:48:49.257281Z","iopub.status.idle":"2025-07-30T10:48:49.265221Z","shell.execute_reply.started":"2025-07-30T10:48:49.257258Z","shell.execute_reply":"2025-07-30T10:48:49.264528Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"inference_Report(model,test_set)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T10:45:38.974668Z","iopub.execute_input":"2025-07-30T10:45:38.974928Z","iopub.status.idle":"2025-07-30T10:46:04.994329Z","shell.execute_reply.started":"2025-07-30T10:45:38.974906Z","shell.execute_reply":"2025-07-30T10:46:04.993613Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model_parametersInfo(model)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T10:46:04.995936Z","iopub.execute_input":"2025-07-30T10:46:04.996192Z","iopub.status.idle":"2025-07-30T10:46:05.007487Z","shell.execute_reply.started":"2025-07-30T10:46:04.996173Z","shell.execute_reply":"2025-07-30T10:46:05.006698Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Define input shape\ninput_shape = (1, 224, 224,3 )\n# Calculate FLOPs\nflops = get_flops(model, input_shape)\nmacs = flops // 2  # MACs is half the FLOPs for Conv2D\n\nprint(f\"MACs: {macs}\")\nprint(f\"FLOPs: {flops}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T10:46:05.008264Z","iopub.execute_input":"2025-07-30T10:46:05.008502Z","iopub.status.idle":"2025-07-30T10:46:12.488183Z","shell.execute_reply.started":"2025-07-30T10:46:05.008475Z","shell.execute_reply":"2025-07-30T10:46:12.487332Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"wandb.finish()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-30T10:46:12.489062Z","iopub.execute_input":"2025-07-30T10:46:12.489662Z","iopub.status.idle":"2025-07-30T10:46:12.910719Z","shell.execute_reply.started":"2025-07-30T10:46:12.489640Z","shell.execute_reply":"2025-07-30T10:46:12.910153Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}