{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.11.11","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"nvidiaTeslaT4","dataSources":[{"sourceId":924245,"sourceType":"datasetVersion","datasetId":464091}],"dockerImageVersionId":31011,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"# This Python 3 environment comes with many helpful analytics libraries installed\n# It is defined by the kaggle/python Docker image: https://github.com/kaggle/docker-python\n# For example, here's several helpful packages to load\n\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n\n# Input data files are available in the read-only \"../input/\" directory\n# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory\n\nimport os\nfor dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n        print(os.path.join(dirname, filename))\n\n# You can write up to 20GB to the current directory (/kaggle/working/) that gets preserved as output when you create a version using \"Save & Run All\" \n# You can also write temporary files to /kaggle/temp/, but they won't be saved outside of the current session","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2025-05-16T02:59:52.159639Z","iopub.execute_input":"2025-05-16T02:59:52.159865Z","iopub.status.idle":"2025-05-16T03:03:33.057434Z","shell.execute_reply.started":"2025-05-16T02:59:52.159848Z","shell.execute_reply":"2025-05-16T03:03:33.056667Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"dataset_path = '/kaggle/input/deepfake-faces/metadata.csv'","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-16T03:07:05.518911Z","iopub.execute_input":"2025-05-16T03:07:05.519743Z","iopub.status.idle":"2025-05-16T03:07:05.523683Z","shell.execute_reply.started":"2025-05-16T03:07:05.519712Z","shell.execute_reply":"2025-05-16T03:07:05.522905Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"df = pd.read_csv(dataset_path)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-16T03:07:08.072333Z","iopub.execute_input":"2025-05-16T03:07:08.073194Z","iopub.status.idle":"2025-05-16T03:07:08.252262Z","shell.execute_reply.started":"2025-05-16T03:07:08.073156Z","shell.execute_reply":"2025-05-16T03:07:08.251382Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"df.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-16T03:07:10.859474Z","iopub.execute_input":"2025-05-16T03:07:10.859739Z","iopub.status.idle":"2025-05-16T03:07:10.887984Z","shell.execute_reply.started":"2025-05-16T03:07:10.859718Z","shell.execute_reply":"2025-05-16T03:07:10.887106Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"df.tail()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-16T03:07:13.592647Z","iopub.execute_input":"2025-05-16T03:07:13.592973Z","iopub.status.idle":"2025-05-16T03:07:13.602055Z","shell.execute_reply.started":"2025-05-16T03:07:13.592952Z","shell.execute_reply":"2025-05-16T03:07:13.601395Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"df.shape","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-16T03:07:16.080004Z","iopub.execute_input":"2025-05-16T03:07:16.080267Z","iopub.status.idle":"2025-05-16T03:07:16.085251Z","shell.execute_reply.started":"2025-05-16T03:07:16.080247Z","shell.execute_reply":"2025-05-16T03:07:16.084503Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"df.columns","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-16T03:07:18.365946Z","iopub.execute_input":"2025-05-16T03:07:18.366230Z","iopub.status.idle":"2025-05-16T03:07:18.373690Z","shell.execute_reply.started":"2025-05-16T03:07:18.366210Z","shell.execute_reply":"2025-05-16T03:07:18.373095Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"df.duplicated().sum()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-16T03:07:21.107228Z","iopub.execute_input":"2025-05-16T03:07:21.107655Z","iopub.status.idle":"2025-05-16T03:07:21.159911Z","shell.execute_reply.started":"2025-05-16T03:07:21.107633Z","shell.execute_reply":"2025-05-16T03:07:21.159340Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"df.isnull().sum()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-16T03:07:23.319214Z","iopub.execute_input":"2025-05-16T03:07:23.319948Z","iopub.status.idle":"2025-05-16T03:07:23.347857Z","shell.execute_reply.started":"2025-05-16T03:07:23.319918Z","shell.execute_reply":"2025-05-16T03:07:23.347030Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"df.nunique()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-16T03:07:25.839812Z","iopub.execute_input":"2025-05-16T03:07:25.840461Z","iopub.status.idle":"2025-05-16T03:07:25.876379Z","shell.execute_reply.started":"2025-05-16T03:07:25.840439Z","shell.execute_reply":"2025-05-16T03:07:25.875782Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"df['label'].unique()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-16T03:07:28.488111Z","iopub.execute_input":"2025-05-16T03:07:28.488699Z","iopub.status.idle":"2025-05-16T03:07:28.496906Z","shell.execute_reply.started":"2025-05-16T03:07:28.488677Z","shell.execute_reply":"2025-05-16T03:07:28.496184Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"df['label'].value_counts()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-16T03:07:30.904798Z","iopub.execute_input":"2025-05-16T03:07:30.905452Z","iopub.status.idle":"2025-05-16T03:07:30.915424Z","shell.execute_reply.started":"2025-05-16T03:07:30.905426Z","shell.execute_reply":"2025-05-16T03:07:30.914778Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"images_folder = '/kaggle/input/deepfake-faces/faces_224/'\n\ndf1 = pd.DataFrame()\ndf1['image_path'] = df['videoname'].apply(lambda x: os.path.join(images_folder, x.replace('.mp4', '.jpg')))\ndf1['label'] = df['label']","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-16T03:07:33.449244Z","iopub.execute_input":"2025-05-16T03:07:33.449829Z","iopub.status.idle":"2025-05-16T03:07:33.543259Z","shell.execute_reply.started":"2025-05-16T03:07:33.449807Z","shell.execute_reply":"2025-05-16T03:07:33.542743Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"df1","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-16T03:07:36.398847Z","iopub.execute_input":"2025-05-16T03:07:36.399461Z","iopub.status.idle":"2025-05-16T03:07:36.410215Z","shell.execute_reply.started":"2025-05-16T03:07:36.399438Z","shell.execute_reply":"2025-05-16T03:07:36.409506Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"df1['label'].unique()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-16T03:07:39.256120Z","iopub.execute_input":"2025-05-16T03:07:39.256398Z","iopub.status.idle":"2025-05-16T03:07:39.265088Z","shell.execute_reply.started":"2025-05-16T03:07:39.256347Z","shell.execute_reply":"2025-05-16T03:07:39.264282Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"df1['label'].value_counts()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-16T03:07:41.509262Z","iopub.execute_input":"2025-05-16T03:07:41.509839Z","iopub.status.idle":"2025-05-16T03:07:41.519963Z","shell.execute_reply.started":"2025-05-16T03:07:41.509798Z","shell.execute_reply":"2025-05-16T03:07:41.519316Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"fake_df = df1[df1['label'] == 'FAKE'].sample(n=10000, random_state=42)\nreal_df = df1[df1['label'] == 'REAL'].sample(n=10000, random_state=42)\n\ndf2 = pd.concat([fake_df, real_df]).reset_index(drop=True)\n\ndf2 = df2.sample(frac=1, random_state=42).reset_index(drop=True)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-16T03:07:44.496374Z","iopub.execute_input":"2025-05-16T03:07:44.497003Z","iopub.status.idle":"2025-05-16T03:07:44.528399Z","shell.execute_reply.started":"2025-05-16T03:07:44.496981Z","shell.execute_reply":"2025-05-16T03:07:44.527854Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"df2","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-16T03:07:47.661416Z","iopub.execute_input":"2025-05-16T03:07:47.662060Z","iopub.status.idle":"2025-05-16T03:07:47.670250Z","shell.execute_reply.started":"2025-05-16T03:07:47.662039Z","shell.execute_reply":"2025-05-16T03:07:47.669518Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import seaborn as sns\nimport matplotlib.pyplot as plt\n\nsns.set_style(\"whitegrid\")\n\nfig, ax = plt.subplots(figsize=(8, 6))\nsns.countplot(data=df2, x=\"label\", palette=\"viridis\", ax=ax)\n\nax.set_title(\"Distribution of Disease Types\", fontsize=14, fontweight='bold')\nax.set_xlabel(\"Tumor Type\", fontsize=12)\nax.set_ylabel(\"Count\", fontsize=12)\n\nfor p in ax.patches:\n    ax.annotate(f'{int(p.get_height())}', \n                (p.get_x() + p.get_width() / 2., p.get_height()), \n                ha='center', va='bottom', fontsize=11, color='black', \n                xytext=(0, 5), textcoords='offset points')\n\nplt.show()\n\nlabel_counts = df2[\"label\"].value_counts()\n\nfig, ax = plt.subplots(figsize=(8, 6))\ncolors = sns.color_palette(\"viridis\", len(label_counts))\n\nax.pie(label_counts, labels=label_counts.index, autopct='%1.1f%%', \n       startangle=140, colors=colors, textprops={'fontsize': 12, 'weight': 'bold'},\n       wedgeprops={'edgecolor': 'black', 'linewidth': 1})\n\nax.set_title(\"Distribution of Disease Types - Pie Chart\", fontsize=14, fontweight='bold')\n\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-16T03:07:50.431105Z","iopub.execute_input":"2025-05-16T03:07:50.431421Z","iopub.status.idle":"2025-05-16T03:07:52.002553Z","shell.execute_reply.started":"2025-05-16T03:07:50.431394Z","shell.execute_reply":"2025-05-16T03:07:52.001803Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import cv2\nimport os\nfrom tqdm import tqdm\n\n# To store only valid (non-corrupted) rows\nvalid_rows = []\n\n# Go through each image path\nfor idx, row in tqdm(df2.iterrows(), total=len(df2)):\n    img_path = row['image_path']\n    \n    # Try reading the image\n    img = cv2.imread(img_path)\n    \n    # If image is valid (not None)\n    if img is not None:\n        valid_rows.append(row)\n\n# Create a new cleaned dataframe\ndf2_clean = pd.DataFrame(valid_rows).reset_index(drop=True)\n\n# Print result\nprint(f\"Original df2 size: {len(df2)}\")\nprint(f\"Cleaned df2_clean size (after removing corrupted images): {len(df2_clean)}\")\n\n# Optional: check class distribution\nprint(df2_clean['label'].value_counts())","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-16T03:07:59.429718Z","iopub.execute_input":"2025-05-16T03:07:59.430131Z","iopub.status.idle":"2025-05-16T03:11:10.807932Z","shell.execute_reply.started":"2025-05-16T03:07:59.430110Z","shell.execute_reply":"2025-05-16T03:11:10.807176Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import cv2\n\nnum_images = 5\n\nplt.figure(figsize=(15, 12))\n\ncategories = ['REAL', 'FAKE']\n\nfor i, category in enumerate(categories):\n    category_images = df2[df2['label'] == category]['image_path'].iloc[:num_images]\n\n    for j, img_path in enumerate(category_images):\n\n        img = cv2.imread(img_path)\n        img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)  \n\n        plt.subplot(len(categories), num_images, i * num_images + j + 1)\n        plt.imshow(img)\n        plt.axis('off')\n        plt.title(category)\n\nplt.tight_layout()\nplt.show()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-16T03:11:10.809341Z","iopub.execute_input":"2025-05-16T03:11:10.809614Z","iopub.status.idle":"2025-05-16T03:11:12.482113Z","shell.execute_reply.started":"2025-05-16T03:11:10.809596Z","shell.execute_reply":"2025-05-16T03:11:12.481123Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from sklearn.preprocessing import LabelEncoder\nlabel_encoder = LabelEncoder()\ndf2['category_encoded'] = label_encoder.fit_transform(df2['label'])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-16T03:11:12.482913Z","iopub.execute_input":"2025-05-16T03:11:12.483112Z","iopub.status.idle":"2025-05-16T03:11:12.606841Z","shell.execute_reply.started":"2025-05-16T03:11:12.483096Z","shell.execute_reply":"2025-05-16T03:11:12.606122Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"df2 = df2[['image_path', 'category_encoded']]","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-16T03:11:12.608303Z","iopub.execute_input":"2025-05-16T03:11:12.608501Z","iopub.status.idle":"2025-05-16T03:11:12.613429Z","shell.execute_reply.started":"2025-05-16T03:11:12.608486Z","shell.execute_reply":"2025-05-16T03:11:12.612816Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"min_samples = df2['category_encoded'].value_counts().min()\nbalanced_df = df2.groupby('category_encoded').sample(n=min_samples, random_state=42)\nbalanced_df = balanced_df.reset_index(drop=True)\nbalanced_df = balanced_df[['image_path', 'category_encoded']]\nprint(balanced_df)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-16T03:11:12.614099Z","iopub.execute_input":"2025-05-16T03:11:12.614413Z","iopub.status.idle":"2025-05-16T03:11:12.645855Z","shell.execute_reply.started":"2025-05-16T03:11:12.614391Z","shell.execute_reply":"2025-05-16T03:11:12.645283Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"df_resampled = balanced_df","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-16T03:11:12.646719Z","iopub.execute_input":"2025-05-16T03:11:12.647332Z","iopub.status.idle":"2025-05-16T03:11:12.655774Z","shell.execute_reply.started":"2025-05-16T03:11:12.647315Z","shell.execute_reply":"2025-05-16T03:11:12.655086Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"df_resampled['category_encoded'] = df_resampled['category_encoded'].astype(str)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-16T03:11:12.656380Z","iopub.execute_input":"2025-05-16T03:11:12.656610Z","iopub.status.idle":"2025-05-16T03:11:12.677716Z","shell.execute_reply.started":"2025-05-16T03:11:12.656596Z","shell.execute_reply":"2025-05-16T03:11:12.677049Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from sklearn.model_selection import train_test_split\nfrom sklearn.metrics import confusion_matrix, classification_report\n\nimport tensorflow as tf\nfrom tensorflow import keras\nfrom tensorflow.keras.models import Sequential\nfrom tensorflow.keras.optimizers import Adam\nfrom tensorflow.keras.preprocessing.image import ImageDataGenerator\nfrom tensorflow.keras.layers import Conv2D, MaxPooling2D, Flatten, Dense, Activation, Dropout, BatchNormalization\nfrom tensorflow.keras import regularizers\n\nimport warnings\nwarnings.filterwarnings(\"ignore\")\n\nprint ('check')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-16T03:11:12.678421Z","iopub.execute_input":"2025-05-16T03:11:12.678972Z","iopub.status.idle":"2025-05-16T03:11:34.654510Z","shell.execute_reply.started":"2025-05-16T03:11:12.678949Z","shell.execute_reply":"2025-05-16T03:11:34.653686Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_df_new, temp_df_new = train_test_split(\n    df_resampled,\n    train_size=0.8,  \n    shuffle=True,\n    random_state=42,\n    stratify=df_resampled['category_encoded']  \n)\n\nvalid_df_new, test_df_new = train_test_split(\n    temp_df_new,\n    test_size=0.5,  \n    shuffle=True,\n    random_state=42,\n    stratify=temp_df_new['category_encoded'] \n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-16T03:11:34.655436Z","iopub.execute_input":"2025-05-16T03:11:34.655954Z","iopub.status.idle":"2025-05-16T03:11:34.685849Z","shell.execute_reply.started":"2025-05-16T03:11:34.655935Z","shell.execute_reply":"2025-05-16T03:11:34.685240Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"batch_size = 16\nimg_size = (224, 224)\nchannels = 3  \nimg_shape = (img_size[0], img_size[1], channels)\n\ntr_gen = ImageDataGenerator(rescale=1./255)  \nts_gen = ImageDataGenerator(rescale=1./255)\n\ntrain_gen_new = tr_gen.flow_from_dataframe(\n    train_df_new,\n    x_col='image_path',  \n    y_col='category_encoded',     \n    target_size=img_size,\n    class_mode='binary',  \n    color_mode='rgb', \n    shuffle=True,\n    batch_size=batch_size\n)\n\nvalid_gen_new = ts_gen.flow_from_dataframe(\n    valid_df_new,\n    x_col='image_path',  \n    y_col='category_encoded',     \n    target_size=img_size,\n    class_mode='binary',  \n    color_mode='rgb', \n    shuffle=True,\n    batch_size=batch_size\n)\n\ntest_gen_new = ts_gen.flow_from_dataframe(\n    test_df_new,\n    x_col='image_path', \n    y_col='category_encoded',    \n    target_size=img_size,\n    class_mode='binary',  \n    color_mode='rgb', \n    shuffle=False,  \n    batch_size=batch_size\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-16T03:11:34.688029Z","iopub.execute_input":"2025-05-16T03:11:34.688227Z","iopub.status.idle":"2025-05-16T03:12:01.077458Z","shell.execute_reply.started":"2025-05-16T03:11:34.688213Z","shell.execute_reply":"2025-05-16T03:12:01.076504Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import tensorflow as tf\n\nprint(\"Num GPUs Available: \", len(tf.config.list_physical_devices('GPU')))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-16T03:12:01.078421Z","iopub.execute_input":"2025-05-16T03:12:01.078708Z","iopub.status.idle":"2025-05-16T03:12:03.720269Z","shell.execute_reply.started":"2025-05-16T03:12:01.078690Z","shell.execute_reply":"2025-05-16T03:12:03.719402Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"gpus = tf.config.list_physical_devices('GPU')\nif gpus:\n    try:\n        for gpu in gpus:\n            tf.config.experimental.set_memory_growth(gpu, True)\n        print(\"GPU is set for TensorFlow\")\n    except RuntimeError as e:\n        print(e)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-16T03:12:03.721088Z","iopub.execute_input":"2025-05-16T03:12:03.721669Z","iopub.status.idle":"2025-05-16T03:12:03.775445Z","shell.execute_reply.started":"2025-05-16T03:12:03.721642Z","shell.execute_reply":"2025-05-16T03:12:03.774849Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import tensorflow as tf\nfrom tensorflow.keras import layers, models\n\ndef custom_net(input_shape=(224, 224, 3), num_classes=2):\n    inputs = layers.Input(shape=input_shape)\n\n    x = layers.Conv2D(32, 3, padding='same')(inputs)\n    x = layers.Activation('relu')(x)\n    x = layers.MaxPooling2D()(x)\n    x1 = layers.Conv2D(32, 3, padding='same')(x)\n    x1 = layers.Activation('relu')(x1)\n    x1 = layers.MaxPooling2D()(x1)\n\n    x1 = layers.Conv2D(48, 3, padding='same')(x1)\n    x1 = layers.Activation('relu')(x1)\n    x1 = layers.MaxPooling2D()(x1)\n    x1 = layers.Conv2D(48, 3, padding='same')(x1)\n    x1 = layers.Activation('relu')(x1)\n    x1 = layers.MaxPooling2D()(x1)\n\n    x2 = layers.Conv2D(48, 3, padding='same')(x1)\n    x2 = layers.Activation('relu')(x2)\n    x2 = layers.MaxPooling2D()(x2)\n    x2 = layers.Conv2D(48, 3, padding='same')(x2)\n    x2 = layers.Activation('relu')(x2)\n    x2 = layers.MaxPooling2D()(x2)\n\n    x3 = layers.Conv2D(64, 3, padding='same')(inputs)\n    x3 = layers.Activation('relu')(x3)\n    x3 = layers.MaxPooling2D()(x3)\n    x3 = layers.Conv2D(64, 3, padding='same')(x3)\n    x3 = layers.Activation('relu')(x3)\n    x3 = layers.MaxPooling2D()(x3)\n\n    x1 = layers.Conv2D(128, 3, strides=2, padding='same')(x1)\n    x1 = layers.MaxPooling2D(pool_size=(3, 3))(x1)\n\n    x3 = layers.MaxPooling2D(pool_size=(8, 8))(x3)\n    x3 = layers.Conv2D(128, 3, strides=2, padding='same')(x3)\n\n    x1 = layers.Resizing(4,4)(x1)\n    x2 = layers.Resizing(4,4)(x2)\n\n    concatenated = layers.Concatenate()([x1, x2, x3])\n\n    x = layers.GlobalAveragePooling2D()(concatenated)\n    x = layers.Dense(128, activation='relu')(x)\n    x = layers.Dropout(0.5)(x)\n    outputs = layers.Dense(1, activation='sigmoid')(x)\n\n    model = models.Model(inputs, outputs)\n    return model","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-16T04:02:41.689744Z","iopub.execute_input":"2025-05-16T04:02:41.690308Z","iopub.status.idle":"2025-05-16T04:02:41.699556Z","shell.execute_reply.started":"2025-05-16T04:02:41.690287Z","shell.execute_reply":"2025-05-16T04:02:41.698780Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model = custom_net((224, 224, 3), 2)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-16T04:07:29.658584Z","iopub.execute_input":"2025-05-16T04:07:29.659182Z","iopub.status.idle":"2025-05-16T04:07:29.840906Z","shell.execute_reply.started":"2025-05-16T04:07:29.659162Z","shell.execute_reply":"2025-05-16T04:07:29.840393Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model.compile(optimizer='adam',\n             loss='binary_crossentropy',\n             metrics=['accuracy'])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-16T04:07:31.823257Z","iopub.execute_input":"2025-05-16T04:07:31.823806Z","iopub.status.idle":"2025-05-16T04:07:31.831263Z","shell.execute_reply.started":"2025-05-16T04:07:31.823783Z","shell.execute_reply":"2025-05-16T04:07:31.830734Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model.summary()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-16T04:02:49.953699Z","iopub.execute_input":"2025-05-16T04:02:49.954229Z","iopub.status.idle":"2025-05-16T04:02:49.995043Z","shell.execute_reply.started":"2025-05-16T04:02:49.954206Z","shell.execute_reply":"2025-05-16T04:02:49.994497Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"history = model.fit(\n    train_gen_new,\n    epochs=3,\n    validation_data=valid_gen_new,\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-16T04:02:55.684229Z","iopub.execute_input":"2025-05-16T04:02:55.684762Z","iopub.status.idle":"2025-05-16T04:05:24.297941Z","shell.execute_reply.started":"2025-05-16T04:02:55.684738Z","shell.execute_reply":"2025-05-16T04:05:24.297407Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import tensorflow as tf\nfrom tensorflow.keras import layers, models\n\ndef custom_net(input_shape=(224, 224, 3), num_classes=2):\n    inputs = layers.Input(shape=input_shape)\n\n    # Branch 1\n    x = layers.Conv2D(32, 3, padding='same', kernel_initializer='he_normal')(inputs)\n    x = layers.BatchNormalization()(x)\n    x = layers.Activation('relu')(x)\n    x = layers.MaxPooling2D()(x)\n    x1 = layers.Conv2D(32, 3, padding='same', kernel_initializer='he_normal')(x)\n    x1 = layers.BatchNormalization()(x1)\n    x1 = layers.Activation('relu')(x1)\n    x1 = layers.MaxPooling2D()(x1)\n\n    x1 = layers.Conv2D(48, 3, padding='same', kernel_initializer='he_normal')(x1)\n    x1 = layers.BatchNormalization()(x1)\n    x1 = layers.Activation('relu')(x1)\n    x1 = layers.MaxPooling2D()(x1)\n    x1 = layers.Conv2D(48, 3, padding='same', kernel_initializer='he_normal')(x1)\n    x1 = layers.BatchNormalization()(x1)\n    x1 = layers.Activation('relu')(x1)\n    x1 = layers.MaxPooling2D()(x1)\n\n    # Branch 2\n    x2 = layers.Conv2D(48, 3, padding='same', kernel_initializer='he_normal')(x1)\n    x2 = layers.BatchNormalization()(x2)\n    x2 = layers.Activation('relu')(x2)\n    x2 = layers.MaxPooling2D()(x2)\n    x2 = layers.Conv2D(48, 3, padding='same', kernel_initializer='he_normal')(x2)\n    x2 = layers.BatchNormalization()(x2)\n    x2 = layers.Activation('relu')(x2)\n    x2 = layers.MaxPooling2D()(x2)\n\n    # Branch 3\n    x3 = layers.Conv2D(64, 3, padding='same', kernel_initializer='he_normal')(inputs)\n    x3 = layers.BatchNormalization()(x3)\n    x3 = layers.Activation('relu')(x3)\n    x3 = layers.MaxPooling2D()(x3)\n    x3 = layers.Conv2D(64, 3, padding='same', kernel_initializer='he_normal')(x3)\n    x3 = layers.BatchNormalization()(x3)\n    x3 = layers.Activation('relu')(x3)\n    x3 = layers.MaxPooling2D()(x3)\n\n    # Align dimensions\n    x1 = layers.Conv2D(128, 3, strides=2, padding='same', kernel_initializer='he_normal')(x1)\n    x1 = layers.BatchNormalization()(x1)\n    x1 = layers.MaxPooling2D(pool_size=(3, 3))(x1)\n\n    x3 = layers.MaxPooling2D(pool_size=(8, 8))(x3)\n    x3 = layers.Conv2D(128, 3, strides=2, padding='same', kernel_initializer='he_normal')(x3)\n    x3 = layers.BatchNormalization()(x3)\n\n    x1 = layers.Resizing(4, 4, interpolation='bilinear')(x1)\n    x2 = layers.Resizing(4, 4, interpolation='bilinear')(x2)\n    x3 = layers.Resizing(4, 4, interpolation='bilinear')(x3)\n\n    concatenated = layers.Concatenate()([x1, x2, x3])\n\n    x = layers.GlobalAveragePooling2D()(concatenated)\n    x = layers.Dense(256, activation='relu', kernel_initializer='he_normal')(x)\n    x = layers.Dropout(0.4)(x)\n    x = layers.Dense(128, activation='relu', kernel_initializer='he_normal')(x)\n    x = layers.Dropout(0.4)(x)\n    outputs = layers.Dense(1, activation='sigmoid')(x)\n\n    model = models.Model(inputs, outputs)\n    return model","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-16T04:07:14.979437Z","iopub.execute_input":"2025-05-16T04:07:14.980034Z","iopub.status.idle":"2025-05-16T04:07:14.991629Z","shell.execute_reply.started":"2025-05-16T04:07:14.980011Z","shell.execute_reply":"2025-05-16T04:07:14.991068Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"history = model.fit(\n    train_gen_new,\n    epochs=3,\n    validation_data=valid_gen_new,\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-16T04:07:40.398918Z","iopub.execute_input":"2025-05-16T04:07:40.399174Z","iopub.status.idle":"2025-05-16T04:10:44.880755Z","shell.execute_reply.started":"2025-05-16T04:07:40.399158Z","shell.execute_reply":"2025-05-16T04:10:44.880222Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model = create_efficientnet_with_attention(img_shape,num_classes)\nmodel.compile(optimizer='adam',\n             loss='binary_crossentropy',\n             metrics=['accuracy'])","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import tensorflow as tf\nfrom tensorflow.keras import layers, models\nfrom tensorflow.keras.applications import VGG16\nfrom tensorflow.keras.preprocessing.image import ImageDataGenerator\n\n# Define Channel Attention Module\ndef channel_attention(input_feature, ratio=8):\n    channel = input_feature.shape[-1]\n    \n    shared_layer_one = layers.Dense(channel//ratio, activation='relu')\n    shared_layer_two = layers.Dense(channel)\n    \n    avg_pool = layers.GlobalAveragePooling2D()(input_feature)\n    avg_pool = layers.Reshape((1,1,channel))(avg_pool)\n    avg_pool = shared_layer_one(avg_pool)\n    avg_pool = shared_layer_two(avg_pool)\n    \n    max_pool = layers.GlobalMaxPooling2D()(input_feature)\n    max_pool = layers.Reshape((1,1,channel))(max_pool)\n    max_pool = shared_layer_one(max_pool)\n    max_pool = shared_layer_two(max_pool)\n    \n    cbam_feature = layers.Add()([avg_pool, max_pool])\n    cbam_feature = layers.Activation('sigmoid')(cbam_feature)\n    \n    return layers.Multiply()([input_feature, cbam_feature])\n\n# Build VGG16 with Channel Attention\ndef create_vgg16_with_attention(img_shape):\n    base_model = VGG16(weights='imagenet', include_top=False, input_shape=img_shape)\n    \n    # Freeze VGG16 layers\n    for layer in base_model.layers:\n        layer.trainable = False\n        \n    inputs = layers.Input(shape=img_shape)\n    x = base_model(inputs)\n    \n    # Add channel attention after VGG16\n    x = channel_attention(x)\n    \n    # Add custom head\n    x = layers.GlobalAveragePooling2D()(x)\n    x = layers.Dense(512, activation='relu')(x)\n    x = layers.Dropout(0.5)(x)\n    x = layers.Dense(256, activation='relu')(x)\n    x = layers.Dropout(0.3)(x)\n    outputs = layers.Dense(1, activation='sigmoid')(x)\n    \n    model = models.Model(inputs, outputs)\n    return model\n\n# Create and compile model\nmodel = create_vgg16_with_attention(img_shape)\nmodel.compile(optimizer='adam',\n             loss='binary_crossentropy',\n             metrics=['accuracy'])\n\n# Define callbacks\ncallbacks = [\n    tf.keras.callbacks.EarlyStopping(patience=5, restore_best_weights=True),\n]\n\n# Train model\nhistory = model.fit(\n    train_gen_new,\n    epochs=3,\n    validation_data=valid_gen_new,\n    callbacks=callbacks\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-15T19:04:39.441242Z","iopub.execute_input":"2025-05-15T19:04:39.441964Z","iopub.status.idle":"2025-05-15T19:11:08.403039Z","shell.execute_reply.started":"2025-05-15T19:04:39.441937Z","shell.execute_reply":"2025-05-15T19:11:08.402452Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import tensorflow as tf\nfrom tensorflow.keras import layers, models\nfrom tensorflow.keras.applications import VGG16\nfrom tensorflow.keras.preprocessing.image import ImageDataGenerator\n\n# Define Channel Attention Module\ndef channel_attention(input_feature, ratio=8):\n    channel = input_feature.shape[-1]\n    \n    shared_layer_one = layers.Dense(channel//ratio, activation='relu')\n    shared_layer_two = layers.Dense(channel)\n    \n    avg_pool = layers.GlobalAveragePooling2D()(input_feature)\n    avg_pool = layers.Reshape((1,1,channel))(avg_pool)\n    avg_pool = shared_layer_one(avg_pool)\n    avg_pool = shared_layer_two(avg_pool)\n    \n    max_pool = layers.GlobalMaxPooling2D()(input_feature)\n    max_pool = layers.Reshape((1,1,channel))(max_pool)\n    max_pool = shared_layer_one(max_pool)\n    max_pool = shared_layer_two(max_pool)\n    \n    cbam_feature = layers.Add()([avg_pool, max_pool])\n    cbam_feature = layers.Activation('sigmoid')(cbam_feature)\n    \n    return layers.Multiply()([input_feature, cbam_feature])\n\n# Build VGG16 with Channel Attention and Multi-Head Attention\ndef create_vgg16_with_attention(img_shape, num_heads=8):\n    base_model = VGG16(weights='imagenet', include_top=False, input_shape=img_shape)\n    \n    # Freeze VGG16 layers\n    for layer in base_model.layers:\n        layer.trainable = False\n        \n    inputs = layers.Input(shape=img_shape)\n    x = base_model(inputs)\n    \n    # Add channel attention\n    x = channel_attention(x)\n    \n    # Reshape for multi-head attention (flatten spatial dimensions)\n    _, h, w, c = x.shape\n    x = layers.Reshape((-1, c))(x)  # Shape: (batch_size, h*w, channels)\n    \n    # Add multi-head attention\n    x = layers.MultiHeadAttention(num_heads=num_heads, key_dim=c//num_heads)(x, x)\n    \n    # Reshape back to feature map format if needed or proceed to pooling\n    x = layers.GlobalAveragePooling1D()(x)  # Pool across the sequence dimension\n    \n    # Add custom head\n    x = layers.Dense(512, activation='relu')(x)\n    x = layers.Dropout(0.5)(x)\n    x = layers.Dense(256, activation='relu')(x)\n    x = layers.Dropout(0.3)(x)\n    outputs = layers.Dense(1, activation='sigmoid')(x)\n    \n    model = models.Model(inputs, outputs)\n    return model\n\n# Create and compile model\nimg_shape = (224, 224, 3)\nmodel = create_vgg16_with_attention(img_shape, num_heads=8)\nmodel.compile(optimizer='adam',\n             loss='binary_crossentropy',\n             metrics=['accuracy'])\n\n# Define callbacks\ncallbacks = [\n    tf.keras.callbacks.EarlyStopping(patience=5, restore_best_weights=True),\n]\n\n# Train model\nhistory = model.fit(\n    train_gen_new,\n    epochs=3,\n    validation_data=valid_gen_new,\n    callbacks=callbacks\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-15T19:12:42.602232Z","iopub.execute_input":"2025-05-15T19:12:42.602962Z","iopub.status.idle":"2025-05-15T19:19:27.321019Z","shell.execute_reply.started":"2025-05-15T19:12:42.602935Z","shell.execute_reply":"2025-05-15T19:19:27.320397Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import tensorflow as tf\nfrom tensorflow.keras import layers, models\nfrom tensorflow.keras.applications import EfficientNetB0\nfrom tensorflow.keras.preprocessing.image import ImageDataGenerator\n\n# Define Channel Attention Module\ndef channel_attention(input_feature, ratio=8):\n    channel = input_feature.shape[-1]\n    \n    shared_layer_one = layers.Dense(channel//ratio, activation='relu')\n    shared_layer_two = layers.Dense(channel)\n    \n    avg_pool = layers.GlobalAveragePooling2D()(input_feature)\n    avg_pool = layers.Reshape((1,1,channel))(avg_pool)\n    avg_pool = shared_layer_one(avg_pool)\n    avg_pool = shared_layer_two(avg_pool)\n    \n    max_pool = layers.GlobalMaxPooling2D()(input_feature)\n    max_pool = layers.Reshape((1,1,channel))(max_pool)\n    max_pool = shared_layer_one(max_pool)\n    max_pool = shared_layer_two(max_pool)\n    \n    cbam_feature = layers.Add()([avg_pool, max_pool])\n    cbam_feature = layers.Activation('sigmoid')(cbam_feature)\n    \n    return layers.Multiply()([input_feature, cbam_feature])\n\n# Build EfficientNetB0 with Channel Attention and Multi-Head Attention\ndef create_efficientnet_with_attention(img_shape, num_heads=8):\n    base_model = EfficientNetB0(weights='imagenet', include_top=False, input_shape=img_shape)\n    \n    # Freeze EfficientNetB0 layers\n    for layer in base_model.layers:\n        layer.trainable = False\n        \n    inputs = layers.Input(shape=img_shape)\n    x = base_model(inputs)\n    \n    # Add channel attention\n    x = channel_attention(x)\n    \n    # Reshape for multi-head attention (flatten spatial dimensions)\n    _, h, w, c = x.shape\n    x = layers.Reshape((-1, c))(x)  # Shape: (batch_size, h*w, channels)\n    \n    # Add multi-head attention\n    x = layers.MultiHeadAttention(num_heads=num_heads, key_dim=c//num_heads)(x, x)\n    \n    # Pool across the sequence dimension\n    x = layers.GlobalAveragePooling1D()(x)\n    \n    # Add custom head\n    x = layers.Dense(512, activation='relu')(x)\n    x = layers.Dropout(0.5)(x)\n    x = layers.Dense(256, activation='relu')(x)\n    x = layers.Dropout(0.3)(x)\n    outputs = layers.Dense(1, activation='sigmoid')(x)\n    \n    model = models.Model(inputs, outputs)\n    return model\n\n# Create and compile model\nimg_shape = (224, 224, 3)\nmodel = create_efficientnet_with_attention(img_shape, num_heads=8)\nmodel.compile(optimizer='adam',\n             loss='binary_crossentropy',\n             metrics=['accuracy'])\n\n# Define callbacks\ncallbacks = [\n    tf.keras.callbacks.EarlyStopping(patience=5, restore_best_weights=True),\n]\n\n# Train model\nhistory = model.fit(\n    train_gen_new,\n    epochs=3,\n    validation_data=valid_gen_new,\n    callbacks=callbacks\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-15T19:32:19.418632Z","iopub.execute_input":"2025-05-15T19:32:19.419372Z","iopub.status.idle":"2025-05-15T19:35:12.006595Z","shell.execute_reply.started":"2025-05-15T19:32:19.419345Z","shell.execute_reply":"2025-05-15T19:35:12.005983Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import tensorflow as tf\nfrom tensorflow.keras import layers, Model","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-15T18:59:31.380922Z","iopub.execute_input":"2025-05-15T18:59:31.381566Z","iopub.status.idle":"2025-05-15T18:59:31.385272Z","shell.execute_reply.started":"2025-05-15T18:59:31.381538Z","shell.execute_reply":"2025-05-15T18:59:31.384461Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"history = model.fit(\n    train_dataset,\n    validation_data=valid_dataset,\n    epochs=3,\n    callbacks=[lr_scheduler, early_stopping],\n    verbose=1\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-15T17:59:55.995686Z","iopub.execute_input":"2025-05-15T17:59:55.996223Z","execution_failed":"2025-05-15T18:01:48.359Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"class SEBlock(layers.Layer):\n    def __init__(self, ratio=16):\n        super(SEBlock, self).__init__()\n        self.ratio = ratio\n\n    def build(self, input_shape):\n        self.channels = input_shape[-1]\n        self.global_pool = layers.GlobalAveragePooling2D()\n        self.fc1 = layers.Dense(self.channels // self.ratio, activation='swish')\n        self.fc2 = layers.Dense(self.channels, activation='sigmoid')\n        self.reshape = layers.Reshape((1, 1, self.channels))\n\n    def call(self, inputs):\n        se = self.global_pool(inputs)\n        se = self.fc1(se)\n        se = self.fc2(se)\n        se = self.reshape(se)\n        return inputs * se\n\nclass Avg2MaxPooling(layers.Layer):\n    def __init__(self, pool_size=3, strides=2, padding='same'):\n        super(Avg2MaxPooling, self).__init__()\n        self.avg_pool = layers.AveragePooling2D(pool_size, strides, padding)\n        self.max_pool = layers.MaxPooling2D(pool_size, strides, padding)\n        self.bn = layers.BatchNormalization()\n        \n    def call(self, inputs):\n        x = self.avg_pool(inputs) - 2 * self.max_pool(inputs)\n        return self.bn(x)\n\nclass DepthwiseSeparableConv(layers.Layer):\n    def __init__(self, filters, kernel_size=3, strides=1, se_ratio=16):\n        super(DepthwiseSeparableConv, self).__init__()\n        self.dw = layers.DepthwiseConv2D(kernel_size, strides, padding='same')\n        self.pw = layers.Conv2D(filters, 1, strides=1)\n        self.bn = layers.BatchNormalization()\n        self.se = SEBlock(se_ratio)\n        self.proj = layers.Conv2D(filters, 1, strides=1) if strides != 1 else None\n\n    def call(self, inputs):\n        residual = inputs\n        x = self.dw(inputs)\n        x = self.pw(x)\n        x = self.bn(x)\n        x = tf.nn.swish(x)\n        x = self.se(x)\n        if self.proj is not None:\n            residual = self.proj(residual)\n        return x + residual if residual.shape == x.shape else x\n\ndef create_geometric_net(input_shape=(224, 224, 3), num_classes=2):\n    inputs = layers.Input(shape=input_shape)\n\n    x = layers.Conv2D(32, 3)(inputs)\n    x = layers.Activation('relu')(x)\n    x = layers.Conv2D(32, 3)(x)\n    x = layers.Activation('relu')(x)\n\n    x = layers.Conv2D(48, 3)(x)\n    x2 = layers.Activation('relu')(x)\n    x = layers.MaxPooling2D(2)(x)\n\n    x = layers.Conv2D(72, 3)(x)\n    x3 = layers.Activation('relu')(x)\n    x = layers.MaxPooling2D(2)(x)\n\n    pcb1 = layers.Conv2D(24, 3)(x2)\n    pcb1 = layers.Conv2D(24, 3)(pcb1)\n   \n    x = layers.Conv2D(108, 3)(x)\n    x = layers.Activation('relu')(x)\n    x = layers.MaxPooling2D(2)(x)\n\n    pcb1 = layers.Resizing(25, 25)(pcb1)\n    x = layers.concatenate([x, pcb1])\n    x = layers.Conv2D(108, 1)(x)\n    x = layers.Activation('relu')(x)\n\n    pcb2 = layers.Conv2D(24, 3)(x3)\n    pcb2 = layers.Conv2D(24, 3)(pcb2)\n\n    x = layers.Conv2D(162, 3)(x)\n    x = layers.Activation('relu')(x)\n    x = layers.MaxPooling2D(2)(x)\n\n    pcb2 = layers.Resizing(11,11)(pcb2)\n    x = layers.concatenate([x, pcb2])\n    x = layers.Conv2D(162, 1)(x)\n    x = layers.Activation('relu')(x)\n\n    x = DepthwiseSeparableConv(243)(x)\n    x = DepthwiseSeparableConv(365)(x)\n\n    x = layers.GlobalAveragePooling2D()(x)\n    x = layers.Dropout(0.5)(x)\n    outputs = layers.Dense(1, activation='sigmoid', kernel_regularizer=tf.keras.regularizers.l2(0.001))(x)\n\n    return Model(inputs, outputs)\n\nmodel = create_geometric_net(num_classes=2)\nmodel.summary()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-15T17:17:41.829054Z","iopub.execute_input":"2025-05-15T17:17:41.829722Z","iopub.status.idle":"2025-05-15T17:17:42.237058Z","shell.execute_reply.started":"2025-05-15T17:17:41.829700Z","shell.execute_reply":"2025-05-15T17:17:42.236533Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"class SEBlock(layers.Layer):\n    def __init__(self, ratio=16):\n        super(SEBlock, self).__init__()\n        self.ratio = ratio\n\n    def build(self, input_shape):\n        self.channels = input_shape[-1]\n        self.global_pool = layers.GlobalAveragePooling2D()\n        self.fc1 = layers.Dense(self.channels // self.ratio, activation='swish')\n        self.fc2 = layers.Dense(self.channels, activation='sigmoid')\n        self.reshape = layers.Reshape((1, 1, self.channels))\n\n    def call(self, inputs):\n        se = self.global_pool(inputs)\n        se = self.fc1(se)\n        se = self.fc2(se)\n        se = self.reshape(se)\n        return inputs * se\n\nclass Avg2MaxPooling(layers.Layer):\n    def __init__(self, pool_size=3, strides=2, padding='same'):\n        super(Avg2MaxPooling, self).__init__()\n        self.avg_pool = layers.AveragePooling2D(pool_size, strides, padding)\n        self.max_pool = layers.MaxPooling2D(pool_size, strides, padding)\n        self.bn = layers.BatchNormalization()\n        \n    def call(self, inputs):\n        x = self.avg_pool(inputs) - 2 * self.max_pool(inputs)\n        return self.bn(x)\n\nclass DepthwiseSeparableConv(layers.Layer):\n    def __init__(self, filters, kernel_size=3, strides=1, se_ratio=16):\n        super(DepthwiseSeparableConv, self).__init__()\n        self.dw = layers.DepthwiseConv2D(kernel_size, strides, padding='same')\n        self.pw = layers.Conv2D(filters, 1, strides=1)\n        self.bn = layers.BatchNormalization()\n        self.se = SEBlock(se_ratio)\n        self.proj = layers.Conv2D(filters, 1, strides=1) if strides != 1 else None\n\n    def call(self, inputs):\n        residual = inputs\n        x = self.dw(inputs)\n        x = self.pw(x)\n        x = self.bn(x)\n        x = tf.nn.swish(x)\n        x = self.se(x)\n        if self.proj is not None:\n            residual = self.proj(residual)\n        return x + residual if residual.shape == x.shape else x\n\ndef create_geometric_net(input_shape=(224, 224, 3), num_classes=2):\n    inputs = layers.Input(shape=input_shape)\n\n    x = layers.Conv2D(32, 3, padding='same')(inputs)\n    x = layers.BatchNormalization()(x)\n    x = layers.Activation('swish')(x)\n    x = layers.Conv2D(32, 3, strides=2, padding='same')(x)\n    x = layers.BatchNormalization()(x)\n    x = layers.Activation('swish')(x)\n\n    x = layers.Conv2D(48, 3, padding='same')(x)\n    x = layers.BatchNormalization()(x)\n    x2 = layers.Activation('swish')(x)\n    x = layers.MaxPooling2D(2)(x)\n\n    x = layers.Conv2D(72, 3, padding='same')(x)\n    x = layers.BatchNormalization()(x)\n    x3 = layers.Activation('swish')(x)\n    x = layers.MaxPooling2D(2)(x)\n\n    pcb1 = layers.Conv2D(24, 3, padding='same')(x2)\n    pcb1 = Avg2MaxPooling()(pcb1)\n    pcb1 = layers.Conv2D(24, 3, padding='same')(pcb1)\n    pcb1 = Avg2MaxPooling()(pcb1)\n   \n    x = layers.Conv2D(108, 3, padding='same')(x)\n    x = layers.BatchNormalization()(x)\n    x = layers.Activation('swish')(x)\n    x = layers.MaxPooling2D(2)(x)\n\n    pcb1 = layers.Resizing(14, 14)(pcb1)\n    x = layers.concatenate([x, pcb1])\n    x = layers.Conv2D(108, 1, padding='same')(x)\n    x = layers.BatchNormalization()(x)\n    x = layers.Activation('swish')(x)\n\n    pcb2 = layers.Conv2D(24, 3, padding='same')(x3)\n    pcb2 = Avg2MaxPooling()(pcb2)\n    pcb2 = layers.Conv2D(24, 3, padding='same')(pcb2)\n    pcb2 = Avg2MaxPooling()(pcb2)\n\n    x = layers.Conv2D(162, 3, padding='same')(x)\n    x = layers.BatchNormalization()(x)\n    x = layers.Activation('swish')(x)\n    x = layers.MaxPooling2D(2)(x)\n\n    pcb2 = layers.Resizing(7, 7)(pcb2)\n    x = layers.concatenate([x, pcb2])\n    x = layers.Conv2D(162, 1, padding='same')(x)\n    x = layers.BatchNormalization()(x)\n    x = layers.Activation('swish')(x)\n\n    x = DepthwiseSeparableConv(243)(x)\n    x = DepthwiseSeparableConv(365)(x)\n\n    x = layers.GlobalAveragePooling2D()(x)\n    x = layers.Dropout(0.5)(x)\n    outputs = layers.Dense(1, activation='sigmoid', kernel_regularizer=tf.keras.regularizers.l2(0.001))(x)\n\n    return Model(inputs, outputs)\n\nmodel = create_geometric_net(num_classes=2)\nmodel.summary()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-27T18:30:02.719147Z","iopub.execute_input":"2025-04-27T18:30:02.719911Z","iopub.status.idle":"2025-04-27T18:30:03.384975Z","shell.execute_reply.started":"2025-04-27T18:30:02.719884Z","shell.execute_reply":"2025-04-27T18:30:03.384349Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model.compile(optimizer='adam',\n                  loss=tf.keras.losses.BinaryCrossentropy(),\n                  metrics=['accuracy'])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-15T17:17:53.518425Z","iopub.execute_input":"2025-05-15T17:17:53.519097Z","iopub.status.idle":"2025-05-15T17:17:53.527250Z","shell.execute_reply.started":"2025-05-15T17:17:53.519072Z","shell.execute_reply":"2025-05-15T17:17:53.526751Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"history = model.fit(\n    train_gen_new,\n    validation_data=valid_gen_new,\n    epochs=5,\n    batch_size=16,\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-15T17:17:56.679856Z","iopub.execute_input":"2025-05-15T17:17:56.680464Z","iopub.status.idle":"2025-05-15T17:29:50.568977Z","shell.execute_reply.started":"2025-05-15T17:17:56.680440Z","shell.execute_reply":"2025-05-15T17:29:50.568413Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from sklearn.metrics import confusion_matrix, classification_report","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-27T18:42:58.690984Z","iopub.execute_input":"2025-04-27T18:42:58.691735Z","iopub.status.idle":"2025-04-27T18:42:58.695226Z","shell.execute_reply.started":"2025-04-27T18:42:58.691710Z","shell.execute_reply":"2025-04-27T18:42:58.694610Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def plot_history(history):\n    plt.figure(figsize=(12, 4))\n    \n    plt.subplot(1, 2, 1)\n    plt.plot(history.history['accuracy'], label='Train Accuracy')\n    plt.plot(history.history['val_accuracy'], label='Validation Accuracy')\n    plt.title('Accuracy over Epochs')\n    plt.xlabel('Epoch')\n    plt.ylabel('Accuracy')\n    plt.legend()\n    \n    plt.subplot(1, 2, 2)\n    plt.plot(history.history['loss'], label='Train Loss')\n    plt.plot(history.history['val_loss'], label='Validation Loss')\n    plt.title('Loss over Epochs')\n    plt.xlabel('Epoch')\n    plt.ylabel('Loss')\n    plt.legend()\n    \n    plt.tight_layout()\n    plt.show()\n\nplot_history(history)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-27T18:46:23.881302Z","iopub.execute_input":"2025-04-27T18:46:23.882079Z","iopub.status.idle":"2025-04-27T18:46:24.395117Z","shell.execute_reply.started":"2025-04-27T18:46:23.882052Z","shell.execute_reply":"2025-04-27T18:46:24.394451Z"}},"outputs":[],"execution_count":null}]}