{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.6.6","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"nvidiaTeslaT4","dataSources":[{"sourceId":16880,"databundleVersionId":858837,"sourceType":"competition"},{"sourceId":924245,"sourceType":"datasetVersion","datasetId":464091},{"sourceId":150019,"sourceType":"modelInstanceVersion","isSourceIdPinned":true,"modelInstanceId":127369,"modelId":150310}],"dockerImageVersionId":29845,"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        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","execution":{"iopub.status.busy":"2024-10-29T09:15:11.204569Z","iopub.execute_input":"2024-10-29T09:15:11.204894Z","iopub.status.idle":"2024-10-29T09:17:07.782288Z","shell.execute_reply.started":"2024-10-29T09:15:11.204837Z","shell.execute_reply":"2024-10-29T09:17:07.781310Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"dataset_path = '/kaggle/input/deepfake-faces/metadata.csv'","metadata":{"execution":{"iopub.status.busy":"2024-10-29T09:17:07.783993Z","iopub.execute_input":"2024-10-29T09:17:07.784246Z","iopub.status.idle":"2024-10-29T09:17:07.788015Z","shell.execute_reply.started":"2024-10-29T09:17:07.784205Z","shell.execute_reply":"2024-10-29T09:17:07.787163Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df = pd.read_csv(dataset_path)","metadata":{"execution":{"iopub.status.busy":"2024-10-29T09:17:07.789620Z","iopub.execute_input":"2024-10-29T09:17:07.789975Z","iopub.status.idle":"2024-10-29T09:17:07.940579Z","shell.execute_reply.started":"2024-10-29T09:17:07.789915Z","shell.execute_reply":"2024-10-29T09:17:07.939974Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df.head()","metadata":{"execution":{"iopub.status.busy":"2024-10-29T09:17:07.942196Z","iopub.execute_input":"2024-10-29T09:17:07.942536Z","iopub.status.idle":"2024-10-29T09:17:07.966167Z","shell.execute_reply.started":"2024-10-29T09:17:07.942478Z","shell.execute_reply":"2024-10-29T09:17:07.965496Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df.tail()","metadata":{"execution":{"iopub.status.busy":"2024-10-29T09:17:07.969933Z","iopub.execute_input":"2024-10-29T09:17:07.970214Z","iopub.status.idle":"2024-10-29T09:17:07.980936Z","shell.execute_reply.started":"2024-10-29T09:17:07.970159Z","shell.execute_reply":"2024-10-29T09:17:07.979993Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df.shape","metadata":{"execution":{"iopub.status.busy":"2024-10-29T09:17:07.983359Z","iopub.execute_input":"2024-10-29T09:17:07.983656Z","iopub.status.idle":"2024-10-29T09:17:07.989149Z","shell.execute_reply.started":"2024-10-29T09:17:07.983568Z","shell.execute_reply":"2024-10-29T09:17:07.988424Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def classify_features(df):\n    categorical_features = []\n    non_categorical_features = []\n    discrete_features = []\n    continuous_features = []\n\n    for column in df.columns:\n        if df[column].dtype == 'object':\n            if df[column].nunique() < 10:\n                categorical_features.append(column)\n            else:\n                non_categorical_features.append(column)\n        elif df[column].dtype in ['int64', 'float64']:\n            if df[column].nunique() < 10:\n                discrete_features.append(column)\n            else:\n                continuous_features.append(column)\n\n    return categorical_features, non_categorical_features, discrete_features, continuous_features","metadata":{"execution":{"iopub.status.busy":"2024-10-29T09:17:07.990710Z","iopub.execute_input":"2024-10-29T09:17:07.991049Z","iopub.status.idle":"2024-10-29T09:17:07.999745Z","shell.execute_reply.started":"2024-10-29T09:17:07.990949Z","shell.execute_reply":"2024-10-29T09:17:07.998998Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"categorical, non_categorical, discrete, continuous = classify_features(df)","metadata":{"execution":{"iopub.status.busy":"2024-10-29T09:17:08.001014Z","iopub.execute_input":"2024-10-29T09:17:08.001290Z","iopub.status.idle":"2024-10-29T09:17:08.051763Z","shell.execute_reply.started":"2024-10-29T09:17:08.001233Z","shell.execute_reply":"2024-10-29T09:17:08.051114Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(\"Categorical Features:\", categorical)\nprint(\"Non-Categorical Features:\", non_categorical)\nprint(\"Discrete Features:\", discrete)\nprint(\"Continuous Features:\", continuous)","metadata":{"execution":{"iopub.status.busy":"2024-10-29T09:17:08.053064Z","iopub.execute_input":"2024-10-29T09:17:08.053372Z","iopub.status.idle":"2024-10-29T09:17:08.059291Z","shell.execute_reply.started":"2024-10-29T09:17:08.053318Z","shell.execute_reply":"2024-10-29T09:17:08.058313Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for i in categorical:\n    print(i,':', df[i].unique())\n    print()","metadata":{"execution":{"iopub.status.busy":"2024-10-29T09:17:08.060730Z","iopub.execute_input":"2024-10-29T09:17:08.061173Z","iopub.status.idle":"2024-10-29T09:17:08.072547Z","shell.execute_reply.started":"2024-10-29T09:17:08.060969Z","shell.execute_reply":"2024-10-29T09:17:08.071779Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for i in categorical:\n    print(df[i].value_counts())\n    print()","metadata":{"execution":{"iopub.status.busy":"2024-10-29T09:17:08.073808Z","iopub.execute_input":"2024-10-29T09:17:08.074332Z","iopub.status.idle":"2024-10-29T09:17:08.102873Z","shell.execute_reply.started":"2024-10-29T09:17:08.074118Z","shell.execute_reply":"2024-10-29T09:17:08.101824Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import pandas as pd\nfrom sklearn.utils import resample\n\n# Assuming 'df' is your DataFrame\n# Separate real and fake entries\nreal_df = df[df['label'] == 'REAL']\nfake_df = df[df['label'] == 'FAKE']\n\n# Get the count of real entries\nnum_real = len(real_df)\n\n# Under-sample the fake entries to match the count of real entries\nfake_df_balanced = resample(fake_df, n_samples=num_real, random_state=42)\n\n# Concatenate the balanced data\nbalanced_df = pd.concat([real_df, fake_df_balanced])\n\n# Shuffle the dataset to mix real and fake entries\nbalanced_df = balanced_df.sample(frac=1, random_state=42).reset_index(drop=True)\n\n# Display the result\nprint(f\"Balanced dataset:\\n{balanced_df['label'].value_counts()}\")\n","metadata":{"execution":{"iopub.status.busy":"2024-10-29T09:17:08.104352Z","iopub.execute_input":"2024-10-29T09:17:08.104690Z","iopub.status.idle":"2024-10-29T09:17:09.305707Z","shell.execute_reply.started":"2024-10-29T09:17:08.104630Z","shell.execute_reply":"2024-10-29T09:17:09.304900Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import numpy as np \nimport pandas as pd \nimport matplotlib.pyplot as plt\nimport seaborn as sns","metadata":{"execution":{"iopub.status.busy":"2024-10-29T09:17:09.306961Z","iopub.execute_input":"2024-10-29T09:17:09.307193Z","iopub.status.idle":"2024-10-29T09:17:09.705301Z","shell.execute_reply.started":"2024-10-29T09:17:09.307153Z","shell.execute_reply":"2024-10-29T09:17:09.704628Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import warnings\nwarnings.filterwarnings('ignore')","metadata":{"execution":{"iopub.status.busy":"2024-10-29T09:17:09.706622Z","iopub.execute_input":"2024-10-29T09:17:09.706866Z","iopub.status.idle":"2024-10-29T09:17:09.710432Z","shell.execute_reply.started":"2024-10-29T09:17:09.706814Z","shell.execute_reply":"2024-10-29T09:17:09.709698Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for i in categorical:\n    plt.figure(figsize=(15,6))\n    sns.countplot(x = balanced_df[i], data =balanced_df, palette = 'hls')\n    plt.show()","metadata":{"execution":{"iopub.status.busy":"2024-10-29T09:17:09.711670Z","iopub.execute_input":"2024-10-29T09:17:09.711990Z","iopub.status.idle":"2024-10-29T09:17:10.029453Z","shell.execute_reply.started":"2024-10-29T09:17:09.711886Z","shell.execute_reply":"2024-10-29T09:17:10.028133Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"real_df = balanced_df[balanced_df[\"label\"] == \"REAL\"]\nfake_df = balanced_df[balanced_df[\"label\"] == \"FAKE\"]\nsample_size = 10000\n\nreal_df = real_df.sample(sample_size, random_state=42)\nfake_df = fake_df.sample(sample_size, random_state=42)\n\nsample_meta = pd.concat([real_df, fake_df])","metadata":{"execution":{"iopub.status.busy":"2024-10-29T09:17:10.031590Z","iopub.execute_input":"2024-10-29T09:17:10.032220Z","iopub.status.idle":"2024-10-29T09:17:10.083102Z","shell.execute_reply.started":"2024-10-29T09:17:10.031975Z","shell.execute_reply":"2024-10-29T09:17:10.082122Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from sklearn.model_selection import train_test_split\n\nTrain_set, Test_set = train_test_split(sample_meta,test_size=0.25,random_state=42,stratify=sample_meta['label'])\nTrain_set, Val_set  = train_test_split(Train_set,test_size=0.25,random_state=42,stratify=Train_set['label'])","metadata":{"execution":{"iopub.status.busy":"2024-10-29T09:17:10.085428Z","iopub.execute_input":"2024-10-29T09:17:10.086131Z","iopub.status.idle":"2024-10-29T09:17:10.400952Z","shell.execute_reply.started":"2024-10-29T09:17:10.085790Z","shell.execute_reply":"2024-10-29T09:17:10.400328Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"Train_set.shape,Val_set.shape,Test_set.shape","metadata":{"execution":{"iopub.status.busy":"2024-10-29T09:17:10.402086Z","iopub.execute_input":"2024-10-29T09:17:10.402332Z","iopub.status.idle":"2024-10-29T09:17:10.408013Z","shell.execute_reply.started":"2024-10-29T09:17:10.402292Z","shell.execute_reply":"2024-10-29T09:17:10.407201Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import cv2","metadata":{"execution":{"iopub.status.busy":"2024-10-29T09:17:10.409368Z","iopub.execute_input":"2024-10-29T09:17:10.409693Z","iopub.status.idle":"2024-10-29T09:17:10.576344Z","shell.execute_reply.started":"2024-10-29T09:17:10.409632Z","shell.execute_reply":"2024-10-29T09:17:10.575786Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.figure(figsize=(15,15))\nfor cur,i in enumerate(Train_set.index[25:50]):\n    plt.subplot(5,5,cur+1)\n    plt.xticks([])\n    plt.yticks([])\n    plt.grid(False)\n    \n    plt.imshow(cv2.imread('../input/deepfake-faces/faces_224/'+Train_set.loc[i,'videoname'][:-4]+'.jpg'))\n    \n    if(Train_set.loc[i,'label']=='FAKE'):\n        plt.xlabel('FAKE Image')\n    else:\n        plt.xlabel('REAL Image')\n        \nplt.show()","metadata":{"execution":{"iopub.status.busy":"2024-10-29T09:17:10.577684Z","iopub.execute_input":"2024-10-29T09:17:10.578007Z","iopub.status.idle":"2024-10-29T09:17:12.380674Z","shell.execute_reply.started":"2024-10-29T09:17:10.577949Z","shell.execute_reply":"2024-10-29T09:17:12.379967Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def retreive_dataset(set_name):\n    images,labels=[],[]\n    for (img, imclass) in zip(set_name['videoname'], set_name['label']):\n        images.append(cv2.imread('../input/deepfake-faces/faces_224/'+img[:-4]+'.jpg'))\n        if(imclass=='FAKE'):\n            labels.append(1)\n        else:\n            labels.append(0)\n    \n    return np.array(images),np.array(labels)","metadata":{"execution":{"iopub.status.busy":"2024-10-29T09:17:12.381874Z","iopub.execute_input":"2024-10-29T09:17:12.382171Z","iopub.status.idle":"2024-10-29T09:17:12.388942Z","shell.execute_reply.started":"2024-10-29T09:17:12.382117Z","shell.execute_reply":"2024-10-29T09:17:12.388124Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"X_train,y_train=retreive_dataset(Train_set)\nX_val,y_val=retreive_dataset(Val_set)\nX_test,y_test=retreive_dataset(Test_set)","metadata":{"execution":{"iopub.status.busy":"2024-10-29T09:17:12.390195Z","iopub.execute_input":"2024-10-29T09:17:12.390555Z","iopub.status.idle":"2024-10-29T09:19:28.613836Z","shell.execute_reply.started":"2024-10-29T09:17:12.390371Z","shell.execute_reply":"2024-10-29T09:19:28.612810Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print('X_train shape: ',X_train.shape)","metadata":{"execution":{"iopub.status.busy":"2024-10-29T09:19:28.615380Z","iopub.execute_input":"2024-10-29T09:19:28.615660Z","iopub.status.idle":"2024-10-29T09:19:28.620362Z","shell.execute_reply.started":"2024-10-29T09:19:28.615607Z","shell.execute_reply":"2024-10-29T09:19:28.619499Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print('y_train shape: ',y_train.shape)","metadata":{"execution":{"iopub.status.busy":"2024-10-28T08:11:56.218936Z","iopub.execute_input":"2024-10-28T08:11:56.219221Z","iopub.status.idle":"2024-10-28T08:11:56.224583Z","shell.execute_reply.started":"2024-10-28T08:11:56.219180Z","shell.execute_reply":"2024-10-28T08:11:56.223580Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import tensorflow as tf\nfrom tensorflow.keras import layers, models\nfrom functools import partial","metadata":{"execution":{"iopub.status.busy":"2024-10-28T11:23:15.533000Z","iopub.execute_input":"2024-10-28T11:23:15.533243Z","iopub.status.idle":"2024-10-28T11:23:20.168606Z","shell.execute_reply.started":"2024-10-28T11:23:15.533202Z","shell.execute_reply":"2024-10-28T11:23:20.167888Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"tf.random.set_seed(42)","metadata":{"execution":{"iopub.status.busy":"2024-10-27T05:01:59.984364Z","iopub.execute_input":"2024-10-27T05:01:59.984716Z","iopub.status.idle":"2024-10-27T05:01:59.994955Z","shell.execute_reply.started":"2024-10-27T05:01:59.984613Z","shell.execute_reply":"2024-10-27T05:01:59.994186Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Model Definition\nmodel = models.Sequential([\n    layers.Reshape((224, 224 * 3), input_shape=[224, 224, 3]),  # Reshaping to (224, 224*3) for RNN\n    layers.SimpleRNN(64, activation=\"relu\", return_sequences=False),\n    layers.BatchNormalization(),\n    layers.Dropout(0.5),\n    layers.Dense(units=64, activation=\"relu\", kernel_initializer=\"he_normal\"),\n    layers.BatchNormalization(),\n    layers.Dropout(0.5),\n    layers.Dense(units=1, activation=\"sigmoid\")\n])\n","metadata":{"execution":{"iopub.status.busy":"2024-10-05T02:41:47.213569Z","iopub.execute_input":"2024-10-05T02:41:47.213934Z","iopub.status.idle":"2024-10-05T02:41:51.212369Z","shell.execute_reply.started":"2024-10-05T02:41:47.213876Z","shell.execute_reply":"2024-10-05T02:41:51.211713Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"initial_learning_rate = 0.001\nlr_schedule = tf.keras.optimizers.schedules.ExponentialDecay(\n    initial_learning_rate, decay_steps=100000, decay_rate=0.96, staircase=True\n)","metadata":{"execution":{"iopub.status.busy":"2024-10-05T02:41:54.583314Z","iopub.execute_input":"2024-10-05T02:41:54.583671Z","iopub.status.idle":"2024-10-05T02:41:54.588374Z","shell.execute_reply.started":"2024-10-05T02:41:54.583608Z","shell.execute_reply":"2024-10-05T02:41:54.58763Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.compile(optimizer=tf.keras.optimizers.Adam(learning_rate=lr_schedule),\n              loss=\"binary_crossentropy\", metrics=[\"accuracy\"])","metadata":{"execution":{"iopub.status.busy":"2024-10-05T02:41:57.950239Z","iopub.execute_input":"2024-10-05T02:41:57.950581Z","iopub.status.idle":"2024-10-05T02:41:57.99628Z","shell.execute_reply.started":"2024-10-05T02:41:57.950518Z","shell.execute_reply":"2024-10-05T02:41:57.995595Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.summary()","metadata":{"execution":{"iopub.status.busy":"2024-10-05T02:42:03.030125Z","iopub.execute_input":"2024-10-05T02:42:03.030421Z","iopub.status.idle":"2024-10-05T02:42:03.037225Z","shell.execute_reply.started":"2024-10-05T02:42:03.030379Z","shell.execute_reply":"2024-10-05T02:42:03.036322Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"history = model.fit(\n    X_train, y_train,\n    epochs=10,  # Adjust as needed\n    batch_size=32,  # Adjust as needed\n    validation_data=(X_val, y_val),\n    verbose=1\n)","metadata":{"execution":{"iopub.status.busy":"2024-10-05T02:42:06.637441Z","iopub.execute_input":"2024-10-05T02:42:06.637805Z","iopub.status.idle":"2024-10-05T02:48:33.494238Z","shell.execute_reply.started":"2024-10-05T02:42:06.637743Z","shell.execute_reply":"2024-10-05T02:48:33.493574Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"y_pred = model.predict(X_test)","metadata":{"execution":{"iopub.status.busy":"2024-10-05T02:48:39.968068Z","iopub.execute_input":"2024-10-05T02:48:39.968362Z","iopub.status.idle":"2024-10-05T02:48:42.977482Z","shell.execute_reply.started":"2024-10-05T02:48:39.968318Z","shell.execute_reply":"2024-10-05T02:48:42.97681Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"from sklearn.metrics import accuracy_score, f1_score, precision_score, recall_score, confusion_matrix, classification_report, roc_auc_score","metadata":{"execution":{"iopub.status.busy":"2024-03-30T03:21:32.271636Z","iopub.status.idle":"2024-03-30T03:21:32.272102Z","shell.execute_reply.started":"2024-03-30T03:21:32.271849Z","shell.execute_reply":"2024-03-30T03:21:32.27187Z"}}},{"cell_type":"code","source":"y_test_pred_binary = (y_pred > 0.5).astype(int)","metadata":{"execution":{"iopub.status.busy":"2024-10-05T02:48:43.315816Z","iopub.execute_input":"2024-10-05T02:48:43.316115Z","iopub.status.idle":"2024-10-05T02:48:43.320329Z","shell.execute_reply.started":"2024-10-05T02:48:43.316073Z","shell.execute_reply":"2024-10-05T02:48:43.319485Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"y_train_pred = model.predict(X_train)\ny_train_pred_binary = (y_train_pred > 0.5).astype(int)","metadata":{"execution":{"iopub.status.busy":"2024-10-05T02:48:44.66948Z","iopub.execute_input":"2024-10-05T02:48:44.669823Z","iopub.status.idle":"2024-10-05T02:48:52.49315Z","shell.execute_reply.started":"2024-10-05T02:48:44.669768Z","shell.execute_reply":"2024-10-05T02:48:52.492394Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from sklearn.metrics import accuracy_score, f1_score, precision_score, recall_score, confusion_matrix, classification_report, roc_auc_score\n\ntrain_accuracy = accuracy_score(y_train, y_train_pred_binary)\nprint(f\"Training Accuracy: {train_accuracy * 100:.2f}%\")","metadata":{"execution":{"iopub.status.busy":"2024-10-05T02:48:52.495168Z","iopub.execute_input":"2024-10-05T02:48:52.495492Z","iopub.status.idle":"2024-10-05T02:48:52.502257Z","shell.execute_reply.started":"2024-10-05T02:48:52.495435Z","shell.execute_reply":"2024-10-05T02:48:52.501329Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_accuracy = accuracy_score(y_test, y_test_pred_binary)\nprint(f\"Test Accuracy: {test_accuracy * 100:.2f}%\")","metadata":{"execution":{"iopub.status.busy":"2024-10-05T02:48:52.503416Z","iopub.execute_input":"2024-10-05T02:48:52.503735Z","iopub.status.idle":"2024-10-05T02:48:52.512777Z","shell.execute_reply.started":"2024-10-05T02:48:52.503667Z","shell.execute_reply":"2024-10-05T02:48:52.511858Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"f1 = f1_score(y_test, y_test_pred_binary)\nprint(f\"F1 Score: {f1:.4f}\")\n\nprecision = precision_score(y_test, y_test_pred_binary)\nprint(f\"Precison: {precision:.4f}\")\n\nrecall = recall_score(y_test, y_test_pred_binary)\nprint(f\"Recall: {recall:.4f}\")\n\n# Calculate AUC-ROC\nauc_roc = roc_auc_score(y_test, y_test_pred_binary)\nprint(f\"AUC-ROC: {auc_roc:.4f}\")","metadata":{"execution":{"iopub.status.busy":"2024-10-05T02:48:52.514219Z","iopub.execute_input":"2024-10-05T02:48:52.514557Z","iopub.status.idle":"2024-10-05T02:48:52.532684Z","shell.execute_reply.started":"2024-10-05T02:48:52.514466Z","shell.execute_reply":"2024-10-05T02:48:52.531948Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"conf_matrix = confusion_matrix(y_test, y_test_pred_binary)\nprint(\"Confusion Matrix:\")\nprint(conf_matrix)","metadata":{"execution":{"iopub.status.busy":"2024-10-05T02:48:53.292091Z","iopub.execute_input":"2024-10-05T02:48:53.292429Z","iopub.status.idle":"2024-10-05T02:48:53.306723Z","shell.execute_reply.started":"2024-10-05T02:48:53.292366Z","shell.execute_reply":"2024-10-05T02:48:53.305824Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import scikitplot as skplt","metadata":{"execution":{"iopub.status.busy":"2024-10-05T02:48:53.715092Z","iopub.execute_input":"2024-10-05T02:48:53.715356Z","iopub.status.idle":"2024-10-05T02:48:53.939028Z","shell.execute_reply.started":"2024-10-05T02:48:53.715314Z","shell.execute_reply":"2024-10-05T02:48:53.938398Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"skplt.metrics.plot_confusion_matrix(y_test, y_test_pred_binary, normalize=True)\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2024-10-05T02:48:56.370462Z","iopub.execute_input":"2024-10-05T02:48:56.370808Z","iopub.status.idle":"2024-10-05T02:48:56.648853Z","shell.execute_reply.started":"2024-10-05T02:48:56.370745Z","shell.execute_reply":"2024-10-05T02:48:56.647826Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class_report = classification_report(y_test, y_test_pred_binary)\nprint(\"Classification Report:\")\nprint(class_report)","metadata":{"execution":{"iopub.status.busy":"2024-10-05T02:48:56.874027Z","iopub.execute_input":"2024-10-05T02:48:56.874263Z","iopub.status.idle":"2024-10-05T02:48:56.888685Z","shell.execute_reply.started":"2024-10-05T02:48:56.874223Z","shell.execute_reply":"2024-10-05T02:48:56.887842Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.figure(figsize=(12, 4))\nplt.subplot(1, 2, 1)\nplt.plot(history.history['accuracy'], label='Training Accuracy')\nplt.plot(history.history['val_accuracy'], label='Validation Accuracy')\nplt.title('Training and Validation Accuracy')\nplt.xlabel('Epoch')\nplt.ylabel('Accuracy')\nplt.legend()\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2024-10-05T02:49:00.148532Z","iopub.execute_input":"2024-10-05T02:49:00.148857Z","iopub.status.idle":"2024-10-05T02:49:00.434896Z","shell.execute_reply.started":"2024-10-05T02:49:00.148811Z","shell.execute_reply":"2024-10-05T02:49:00.433676Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.plot(history.history['loss'], label='Training Loss')\nplt.plot(history.history['val_loss'], label='Validation Loss')\nplt.title('Training and Validation Loss')\nplt.xlabel('Epoch')\nplt.ylabel('Loss')\nplt.legend()\nplt.tight_layout()\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2024-10-05T02:49:01.597582Z","iopub.execute_input":"2024-10-05T02:49:01.597917Z","iopub.status.idle":"2024-10-05T02:49:02.174446Z","shell.execute_reply.started":"2024-10-05T02:49:01.59786Z","shell.execute_reply":"2024-10-05T02:49:02.173385Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**CNN+RNN with Canny Edges extracted**","metadata":{}},{"cell_type":"code","source":"pip install -U scikit-image\n","metadata":{"execution":{"iopub.status.busy":"2024-10-27T05:38:59.447879Z","iopub.execute_input":"2024-10-27T05:38:59.448211Z","iopub.status.idle":"2024-10-27T05:39:11.272884Z","shell.execute_reply.started":"2024-10-27T05:38:59.448150Z","shell.execute_reply":"2024-10-27T05:39:11.271749Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import numpy as np\nfrom skimage.feature import hog\nfrom sklearn import svm\nfrom sklearn.metrics import accuracy_score\nimport cv2\nfrom tqdm import tqdm\n\n# Parameters for HOG\nhog_params = {\n    'orientations': 9,\n    'pixels_per_cell': (8, 8),\n    'cells_per_block': (2, 2),\n    'block_norm': 'L2-Hys'\n}\n\n# Function to apply HOG transformation with a progress bar\ndef apply_hog(images):\n    hog_features = []\n    for image in tqdm(images, desc=\"Processing HOG Features\"):\n        # Convert image to grayscale\n        gray_image = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)\n        \n        # Compute HOG features\n        features = hog(gray_image, **hog_params)\n        \n        # Append features to the list\n        hog_features.append(features)\n        \n    return np.array(hog_features)\n\n# Apply HOG to each dataset split with progress indication\nprint(\"Processing X_train:\")\nX_train_hog = apply_hog(X_train)\n\nprint(\"Processing X_val:\")\nX_val_hog = apply_hog(X_val)\n\nprint(\"Processing X_test:\")\nX_test_hog = apply_hog(X_test)\n\n# Initialize the SVM classifier\nsvm_classifier = svm.SVC(kernel='linear', C=1.0, random_state=42)\n\n# Train the SVM classifier on the training data\nprint(\"Training SVM...\")\nsvm_classifier.fit(X_train_hog, y_train)\n\n# Predict on validation and test sets\nprint(\"Evaluating on validation set...\")\ny_val_pred = svm_classifier.predict(X_val_hog)\nprint(\"Evaluating on test set...\")\ny_test_pred = svm_classifier.predict(X_test_hog)\n\n# Calculate accuracy on validation and test sets\nval_accuracy = accuracy_score(y_val, y_val_pred)\ntest_accuracy = accuracy_score(y_test, y_test_pred)\n\nprint(f\"Validation Accuracy: {val_accuracy:.2f}\")\nprint(f\"Test Accuracy: {test_accuracy:.2f}\")\n","metadata":{"execution":{"iopub.status.busy":"2024-10-27T05:41:53.312905Z","iopub.execute_input":"2024-10-27T05:41:53.313208Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"****CNN RNN Model test 1****","metadata":{}},{"cell_type":"code","source":"#improved model\nimport torch\nimport torch.nn as nn\nimport torch.optim as optim\nfrom torch.utils.data import DataLoader, TensorDataset, random_split\nimport numpy as np\nfrom torchvision import transforms\nfrom torch.optim.lr_scheduler import ReduceLROnPlateau","metadata":{"execution":{"iopub.status.busy":"2024-10-29T09:20:20.069170Z","iopub.execute_input":"2024-10-29T09:20:20.069476Z","iopub.status.idle":"2024-10-29T09:20:20.074878Z","shell.execute_reply.started":"2024-10-29T09:20:20.069434Z","shell.execute_reply":"2024-10-29T09:20:20.073953Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Data Augmentation\ntransform = transforms.Compose([\n    transforms.RandomHorizontalFlip(),\n    transforms.RandomRotation(15),\n    transforms.ColorJitter(brightness=0.2, contrast=0.2, saturation=0.2, hue=0.1),\n    transforms.ToTensor(),\n])\n\nclass CNNRNNModel(nn.Module):\n    def __init__(self):\n        super(CNNRNNModel, self).__init__()\n        \n        # CNN part with Batch Normalization and Dropout\n        self.conv1 = nn.Conv2d(in_channels=3, out_channels=32, kernel_size=3, stride=1, padding=1)\n        self.bn1 = nn.BatchNorm2d(32)\n        \n        self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)\n        self.bn2 = nn.BatchNorm2d(64)\n        \n        self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)\n        self.bn3 = nn.BatchNorm2d(128)\n        \n        self.conv4 = nn.Conv2d(128, 256, kernel_size=3, stride=1, padding=1)\n        self.bn4 = nn.BatchNorm2d(256)\n        \n        self.conv5 = nn.Conv2d(256, 512, kernel_size=3, stride=1, padding=1)\n        self.bn5 = nn.BatchNorm2d(512)\n        \n        self.dropout = nn.Dropout(0.5)\n        self.pool = nn.MaxPool2d(2, 2)\n        \n        # RNN part (Adjusted input size to match CNN output dimensions)\n        self.lstm_input_size = num_filters * width  # Match this to the actual CNN output shape\n        self.hidden_size = 128\n        self.num_layers = 2\n        self.lstm = nn.LSTM(input_size=self.lstm_input_size, hidden_size=self.hidden_size, \n                            num_layers=self.num_layers, batch_first=True)\n        \n        # Fully connected layer for classification\n        self.fc = nn.Linear(self.hidden_size, 1)\n\n    def forward(self, x):\n        # CNN Forward Pass\n        x = self.pool(torch.relu(self.bn1(self.conv1(x))))\n        x = self.pool(torch.relu(self.bn2(self.conv2(x))))\n        x = self.pool(torch.relu(self.bn3(self.conv3(x))))\n        x = self.pool(torch.relu(self.bn4(self.conv4(x))))\n        x = self.pool(torch.relu(self.bn5(self.conv5(x))))\n        x = self.dropout(x)\n        \n        # Reshape CNN output to fit into LSTM\n        batch_size, num_filters, height, width = x.shape\n        x = x.permute(0, 2, 3, 1)  # Change to (batch_size, height, width, num_filters)\n        x = x.reshape(batch_size, height, width * num_filters)  # Flatten width and channels together\n\n        # LSTM Forward Pass\n        h0 = torch.zeros(self.num_layers, x.size(0), self.hidden_size).to(x.device)\n        c0 = torch.zeros(self.num_layers, x.size(0), self.hidden_size).to(x.device)\n        \n        out, _ = self.lstm(x, (h0, c0))\n        out = out[:, -1, :]  # Take the output from the last time step\n        \n        # Fully connected layer for final classification\n        out = self.fc(out)\n        return out\n\n# Assuming X_train and y_train are already available as tensors\nX_train_tensor = (torch.tensor(X_train, dtype=torch.float32) / 255).permute(0, 3, 1, 2)\ny_train_tensor = torch.tensor(y_train, dtype=torch.float32)\n\n# Split into training and validation sets\ntrain_size = int(0.8 * len(X_train_tensor))\nval_size = len(X_train_tensor) - train_size\ntrain_dataset, val_dataset = random_split(TensorDataset(X_train_tensor, y_train_tensor), [train_size, val_size])\n\n# Create DataLoaders with augmentation for the training set\ntrain_loader = DataLoader(train_dataset, batch_size=32, shuffle=True)\nval_loader = DataLoader(val_dataset, batch_size=32, shuffle=False)\n\n# Initialize model, optimizer, and learning rate scheduler\ncnn_rnn_model = CNNRNNModel().cuda()\ncriterion = nn.BCEWithLogitsLoss()\noptimizer = optim.AdamW(cnn_rnn_model.parameters(), lr=0.0001, weight_decay=0.01)\nscheduler = ReduceLROnPlateau(optimizer, mode='min', patience=3, factor=0.5, verbose=True)\n\n# Early stopping and model saving parameters\nnum_epochs = 35\npatience = 10\nbest_val_loss = np.inf\npatience_counter = 0\nbest_model_path = \"/kaggle/working/best_cnn_rnn_model.pth\"","metadata":{"execution":{"iopub.status.busy":"2024-10-29T10:31:15.978794Z","iopub.execute_input":"2024-10-29T10:31:15.979135Z","iopub.status.idle":"2024-10-29T10:31:21.167215Z","shell.execute_reply.started":"2024-10-29T10:31:15.979087Z","shell.execute_reply":"2024-10-29T10:31:21.166143Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Training Loop with Early Stopping, Gradient Clipping, and Model Saving\nfor epoch in range(num_epochs):\n    cnn_rnn_model.train()\n    running_loss = 0.0\n    correct = 0\n    total = 0\n    \n    for images, labels in train_loader:\n        images, labels = images.cuda(), labels.cuda()\n        \n        optimizer.zero_grad()\n        outputs = cnn_rnn_model(images)\n        labels = labels.view(-1, 1)\n        loss = criterion(outputs, labels)\n        \n        loss.backward()\n        torch.nn.utils.clip_grad_norm_(cnn_rnn_model.parameters(), max_norm=1.0)\n        optimizer.step()\n        \n        predicted = (outputs >= 0).float()\n        correct += (predicted == labels).sum().item()\n        total += labels.size(0)\n        running_loss += loss.item()\n    \n    train_accuracy = 100 * correct / total\n    train_loss = running_loss / len(train_loader)\n    \n    # Validation Phase\n    cnn_rnn_model.eval()\n    val_loss = 0.0\n    correct_val = 0\n    total_val = 0\n    \n    with torch.no_grad():\n        for images, labels in val_loader:\n            images, labels = images.cuda(), labels.cuda()\n            outputs = cnn_rnn_model(images)\n            labels = labels.view(-1, 1)\n            loss = criterion(outputs, labels)\n            \n            predicted = (outputs >= 0).float()\n            correct_val += (predicted == labels).sum().item()\n            total_val += labels.size(0)\n            val_loss += loss.item()\n    \n    val_accuracy = 100 * correct_val / total_val\n    val_loss /= len(val_loader)\n    \n    # Display training and validation results\n    print(f\"Epoch [{epoch+1}/{num_epochs}], Train Loss: {train_loss:.4f}, Train Accuracy: {train_accuracy:.2f}%\")\n    print(f\"Validation Loss: {val_loss:.4f}, Validation Accuracy: {val_accuracy:.2f}%\")\n    \n    # Learning Rate Scheduler Step\n    scheduler.step(val_loss)\n\n    # Early stopping and model saving every 10 epochs\n    if val_loss < best_val_loss:\n        best_val_loss = val_loss\n        patience_counter = 0  # Reset patience counter\n        if (epoch + 1) % 10 == 0 or epoch == num_epochs - 1:\n            torch.save(cnn_rnn_model.state_dict(), best_model_path)\n            print(f\"Model saved at epoch {epoch+1} with validation loss {val_loss:.4f}\")\n    else:\n        patience_counter += 1\n    \n    if patience_counter >= patience:\n        print(f\"Early stopping at epoch {epoch+1}\")\n        break\n\n# Final model save if early stopping is not triggered\nif patience_counter < patience:\n    final_model_path = \"/kaggle/working/final_cnn_rnn_model.pth\"\n    torch.save(cnn_rnn_model.state_dict(), final_model_path)\n    print(\"Training completed, final model saved.\")\n","metadata":{"execution":{"iopub.status.busy":"2024-10-29T10:31:21.168482Z","iopub.status.idle":"2024-10-29T10:31:21.168973Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"final_model = '/kaggle/input/cnnrnn/pytorch/default/1/best_cnn_rnn_model.pth'","metadata":{"execution":{"iopub.status.busy":"2024-10-29T09:09:20.992564Z","iopub.execute_input":"2024-10-29T09:09:20.992915Z","iopub.status.idle":"2024-10-29T09:09:20.998239Z","shell.execute_reply.started":"2024-10-29T09:09:20.992860Z","shell.execute_reply":"2024-10-29T09:09:20.997391Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Training Losses for each epoch\ntrain_losses = [\n    0.6683, 0.6501, 0.6376, 0.6283, 0.6208, 0.6084, 0.5963, 0.5904, 0.5764, 0.5680,\n    0.5508, 0.5431, 0.5288, 0.5182, 0.5145, 0.4931, 0.4924, 0.4814, 0.4671, 0.4227,\n    0.4122, 0.3994, 0.3847, 0.3679, 0.3655, 0.3516, 0.3492, 0.3118, 0.3040, 0.2939,\n    0.2914, 0.2708, 0.2513\n]\n\n# Validation Losses for each epoch\nval_losses = [\n    0.6690, 0.6580, 0.6467, 0.6457, 0.6209, 0.6174, 0.6160, 0.6181, 0.5912, 0.6113,\n    0.5778, 0.5702, 0.5787, 0.5753, 0.5598, 0.5817, 0.6376, 0.5729, 0.5679, 0.5788,\n    0.5818, 0.5473, 0.5451, 0.5607, 0.5738, 0.5823, 0.5954, 0.5953, 0.5791, 0.5923,\n    0.5973, 0.5931, 0.6438\n]\n\n# Training Accuracies for each epoch\ntrain_accuracies = [\n    59.23, 61.93, 63.19, 64.04, 65.06, 65.98, 66.88, 68.26, 69.58, 70.13,\n    71.61, 72.77, 73.04, 73.83, 74.21, 75.93, 75.27, 76.64, 77.74, 80.47,\n    80.93, 81.82, 82.18, 83.17, 83.49, 84.04, 84.69, 86.52, 86.44, 87.31,\n    87.40, 88.36, 89.23\n]\n\n# Validation Accuracies for each epoch\nval_accuracies = [\n    58.76, 61.11, 62.44, 62.13, 64.09, 65.60, 65.24, 66.98, 68.04, 66.27,\n    68.58, 70.36, 70.89, 70.62, 70.18, 70.62, 66.44, 72.40, 73.02, 72.49,\n    74.22, 74.18, 74.62, 75.42, 74.44, 74.89, 75.07, 74.53, 74.89, 75.82,\n    74.71, 76.36, 75.47\n]\n","metadata":{"execution":{"iopub.status.busy":"2024-10-29T09:24:32.444928Z","iopub.execute_input":"2024-10-29T09:24:32.445311Z","iopub.status.idle":"2024-10-29T09:24:32.459253Z","shell.execute_reply.started":"2024-10-29T09:24:32.445269Z","shell.execute_reply":"2024-10-29T09:24:32.458388Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import matplotlib.pyplot as plt\n\n# Plot Loss\nplt.figure(figsize=(12, 5))\nplt.plot(train_losses, label=\"Train Loss\", color='blue')\nplt.plot(val_losses, label=\"Validation Loss\", color='orange')\nplt.xlabel(\"Epochs\")\nplt.ylabel(\"Loss\")\nplt.title(\"Training and Validation Loss\")\nplt.legend()\nplt.show()\n\n# Plot Accuracy\nplt.figure(figsize=(12, 5))\nplt.plot(train_accuracies, label=\"Train Accuracy\", color='blue')\nplt.plot(val_accuracies, label=\"Validation Accuracy\", color='orange')\nplt.xlabel(\"Epochs\")\nplt.ylabel(\"Accuracy (%)\")\nplt.title(\"Training and Validation Accuracy\")\nplt.legend()\nplt.show()\n","metadata":{"execution":{"iopub.status.busy":"2024-10-29T09:24:41.509092Z","iopub.execute_input":"2024-10-29T09:24:41.509431Z","iopub.status.idle":"2024-10-29T09:24:42.127439Z","shell.execute_reply.started":"2024-10-29T09:24:41.509370Z","shell.execute_reply":"2024-10-29T09:24:42.126452Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#loading the model\nimport torch\n\n# Load the model architecture\nclass CNNRNNModel(nn.Module):\n    # Define model architecture here as used in training\n\n    # Initialize the model and load weights\n    model = CNNRNNModel()\n    # Assuming you have defined CNNRNNModel with the exact same architecture\n    model = CNNRNNModel()\n    model.load_state_dict(torch.load(\"/kaggle/input/cnnrnn/pytorch/default/1/best_cnn_rnn_model.pth\", map_location=torch.device(\"cpu\")), strict=False)\n\n    #model.load_state_dict(torch.load(\"/kaggle/input/cnnrnn/pytorch/default/1/best_cnn_rnn_model.pth\", map_location=torch.device(\"cpu\")))  # Adjust the path\n    model.eval()\n","metadata":{"execution":{"iopub.status.busy":"2024-10-29T09:29:00.172894Z","iopub.execute_input":"2024-10-29T09:29:00.173263Z","iopub.status.idle":"2024-10-29T09:29:00.192517Z","shell.execute_reply.started":"2024-10-29T09:29:00.173202Z","shell.execute_reply":"2024-10-29T09:29:00.191749Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# **CNN RNN Modified**","metadata":{}},{"cell_type":"code","source":"import torch\nimport torch.nn as nn\nimport torch.optim as optim\nfrom torch.optim.lr_scheduler import ReduceLROnPlateau\nimport numpy as np\nfrom torch.utils.data import DataLoader, random_split, TensorDataset\nfrom torchvision import transforms, models\nimport matplotlib.pyplot as plt\n\n# Data Augmentation\ntransform = transforms.Compose([\n    transforms.RandomHorizontalFlip(),\n    transforms.RandomRotation(20),\n    transforms.RandomResizedCrop(size=(224, 224), scale=(0.7, 1.0)),\n    transforms.ColorJitter(brightness=0.4, contrast=0.4, saturation=0.4, hue=0.1),\n    transforms.RandomErasing(p=0.5, scale=(0.02, 0.2), ratio=(0.3, 3.3)),\n    transforms.ToTensor(),\n])\n\n# Updated Focal Loss for harder focus on challenging examples\nclass FocalLoss(nn.Module):\n    def __init__(self, alpha=1, gamma=3):  # Experiment with gamma=3\n        super(FocalLoss, self).__init__()\n        self.alpha = alpha\n        self.gamma = gamma\n\n    def forward(self, inputs, targets):\n        BCE_loss = nn.functional.binary_cross_entropy_with_logits(inputs, targets, reduction='none')\n        pt = torch.exp(-BCE_loss)  # Avoids nans when probability is 0\n        F_loss = self.alpha * (1 - pt) ** self.gamma * BCE_loss\n        return F_loss.mean()\n\n# CNN-RNN Model with Pre-trained ResNet and GRU\nclass CNNGRUModel(nn.Module):\n    def __init__(self):\n        super(CNNGRUModel, self).__init__()\n        \n        # Pre-trained ResNet Backbone\n        resnet = models.resnet34(pretrained=True)\n        self.resnet_base = nn.Sequential(*list(resnet.children())[:-2])  # Use up to last conv layer\n        self.dropout = nn.Dropout(0.5)\n\n        # Calculate GRU input size based on ResNet output\n        dummy_input = torch.zeros(1, 3, 224, 224)\n        cnn_output = self.resnet_base(dummy_input)\n        _, num_filters, height, width = cnn_output.shape\n        self.gru_input_size = num_filters * width\n\n        # GRU with layer normalization\n        self.hidden_size = 128\n        self.num_layers = 2\n        self.gru = nn.GRU(input_size=self.gru_input_size, hidden_size=self.hidden_size, \n                          num_layers=self.num_layers, batch_first=True, bidirectional=True)\n        \n        # Decrease dropout in the fully connected layer\n        self.fc = nn.Sequential(\n            nn.LayerNorm(2 * self.hidden_size),\n            nn.Dropout(0.3),  # Reduced dropout\n            nn.Linear(2 * self.hidden_size, 1)\n        )\n\n    def forward(self, x):\n        # Pass through ResNet Backbone\n        x = self.resnet_base(x)\n        x = self.dropout(x)\n        \n        # Reshape output to fit into GRU\n        batch_size, num_filters, height, width = x.shape\n        x = x.permute(0, 2, 3, 1)\n        x = x.reshape(batch_size, height, width * num_filters)\n\n        # GRU forward pass\n        h0 = torch.zeros(2 * self.num_layers, x.size(0), self.hidden_size).to(x.device)  # Bidirectional * num_layers\n        out, _ = self.gru(x, h0)\n        out = out[:, -1, :]  # Take the output from the last time step\n        out = self.fc(out)\n        return out","metadata":{"execution":{"iopub.status.busy":"2024-10-29T11:39:16.895760Z","iopub.execute_input":"2024-10-29T11:39:16.896110Z","iopub.status.idle":"2024-10-29T11:39:16.920864Z","shell.execute_reply.started":"2024-10-29T11:39:16.896061Z","shell.execute_reply":"2024-10-29T11:39:16.919837Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Assuming X_train and y_train are already available as tensors\nX_train_tensor = (torch.tensor(X_train, dtype=torch.float32) / 255).permute(0, 3, 1, 2)\ny_train_tensor = torch.tensor(y_train, dtype=torch.float32)\n\n# Split into training and validation sets\ntrain_size = int(0.8 * len(X_train_tensor))\nval_size = len(X_train_tensor) - train_size\ntrain_dataset, val_dataset = random_split(TensorDataset(X_train_tensor, y_train_tensor), [train_size, val_size])\n\n# DataLoaders\ntrain_loader = DataLoader(train_dataset, batch_size=32, shuffle=True)\nval_loader = DataLoader(val_dataset, batch_size=32, shuffle=False)\n\n# Initialize model, optimizer, and scheduler\ncnn_gru_model = CNNGRUModel().cuda()\ncriterion = FocalLoss(alpha=1, gamma=3)  # Focal Loss with gamma=3\noptimizer = optim.SGD(cnn_gru_model.parameters(), lr=0.005, momentum=0.9, weight_decay=0.0005)\nscheduler = ReduceLROnPlateau(optimizer, mode='min', factor=0.5, patience=3, verbose=True)\n\n# Training setup\nnum_epochs = 35\npatience = 3\nbest_val_loss = np.inf\npatience_counter = 0\nbest_model_path = \"/kaggle/working/best_cnn_gru_model.pth\"\n\n# Track metrics for plotting and for logging each epoch's details\ntrain_losses, val_losses, train_accuracies, val_accuracies = [], [], [], []\nepoch_summaries = []  # List to store each epoch's summary for final printing\n\n# Training Loop\nfor epoch in range(num_epochs):\n    cnn_gru_model.train()\n    running_loss, correct, total = 0.0, 0, 0\n    \n    for images, labels in train_loader:\n        images, labels = images.cuda(), labels.cuda()\n        \n        optimizer.zero_grad()\n        outputs = cnn_gru_model(images)\n        labels = labels.view(-1, 1)\n        loss = criterion(outputs, labels)\n        \n        loss.backward()\n        torch.nn.utils.clip_grad_norm_(cnn_gru_model.parameters(), max_norm=1.0)\n        optimizer.step()\n\n        predicted = (outputs >= 0).float()\n        correct += (predicted == labels).sum().item()\n        total += labels.size(0)\n        running_loss += loss.item()\n    \n    # Store train metrics\n    train_accuracy = 100 * correct / total\n    train_loss = running_loss / len(train_loader)\n    train_losses.append(train_loss)\n    train_accuracies.append(train_accuracy)\n    \n    # Validation phase\n    cnn_gru_model.eval()\n    val_loss, correct_val, total_val = 0.0, 0, 0\n    \n    with torch.no_grad():\n        for images, labels in val_loader:\n            images, labels = images.cuda(), labels.cuda()\n            outputs = cnn_gru_model(images)\n            labels = labels.view(-1, 1)\n            loss = criterion(outputs, labels)\n            \n            predicted = (outputs >= 0).float()\n            correct_val += (predicted == labels).sum().item()\n            total_val += labels.size(0)\n            val_loss += loss.item()\n    \n    # Store validation metrics\n    val_accuracy = 100 * correct_val / total_val\n    val_loss /= len(val_loader)\n    val_losses.append(val_loss)\n    val_accuracies.append(val_accuracy)\n    \n    # Store each epoch's metrics as a dictionary in `epoch_summaries`\n    epoch_summary = {\n        'epoch': epoch + 1,\n        'train_loss': train_loss,\n        'train_accuracy': train_accuracy,\n        'val_loss': val_loss,\n        'val_accuracy': val_accuracy\n    }\n    epoch_summaries.append(epoch_summary)\n    \n    # Print the epoch details\n    print(f\"Epoch [{epoch+1}/{num_epochs}], Train Loss: {train_loss:.4f}, Train Accuracy: {train_accuracy:.2f}%\", flush=True)\n    print(f\"Validation Loss: {val_loss:.4f}, Validation Accuracy: {val_accuracy:.2f}%\", flush=True)\n\n    # Scheduler and Early stopping\n    scheduler.step(val_loss)\n    \n    if val_loss < best_val_loss:\n        best_val_loss = val_loss\n        patience_counter = 0\n        torch.save(cnn_gru_model.state_dict(), best_model_path)\n        print(f\"Model saved at epoch {epoch+1} with validation loss {val_loss:.4f}\", flush=True)\n    else:\n        patience_counter += 1\n    \n    if patience_counter >= patience:\n        print(f\"Early stopping at epoch {epoch+1}\", flush=True)\n        break\n\n# Print summary of all epochs at the end\nprint(\"\\nEpoch Summary:\")\nfor summary in epoch_summaries:\n    print(f\"Epoch {summary['epoch']}: Train Loss = {summary['train_loss']:.4f}, \"\n          f\"Train Accuracy = {summary['train_accuracy']:.2f}%, \"\n          f\"Val Loss = {summary['val_loss']:.4f}, \"\n          f\"Val Accuracy = {summary['val_accuracy']:.2f}%\")\n\n# Plot Training and Validation Loss\nplt.figure(figsize=(10, 5))\nplt.plot(train_losses, label=\"Train Loss\", color=\"blue\")\nplt.plot(val_losses, label=\"Validation Loss\", color=\"orange\")\nplt.xlabel(\"Epochs\")\nplt.ylabel(\"Loss\")\nplt.title(\"Training and Validation Loss\")\nplt.legend()\nplt.show()\n\n# Plot Training and Validation Accuracy\nplt.figure(figsize=(10, 5))\nplt.plot(train_accuracies, label=\"Train Accuracy\", color=\"blue\")\nplt.plot(val_accuracies, label=\"Validation Accuracy\", color=\"orange\")\nplt.xlabel(\"Epochs\")\nplt.ylabel(\"Accuracy (%)\")\nplt.title(\"Training and Validation Accuracy\")\nplt.legend()\nplt.show()\n","metadata":{"execution":{"iopub.status.busy":"2024-10-29T12:20:49.977068Z","iopub.execute_input":"2024-10-29T12:20:49.977393Z","iopub.status.idle":"2024-10-29T12:29:51.227950Z","shell.execute_reply.started":"2024-10-29T12:20:49.977348Z","shell.execute_reply":"2024-10-29T12:29:51.226803Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# **Results**","metadata":{}},{"cell_type":"code","source":"from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score, confusion_matrix\nimport matplotlib.pyplot as plt\nimport numpy as np\nimport seaborn as sns\nimport torch\nfrom torch.utils.data import DataLoader, TensorDataset\n\n# Convert test data to PyTorch tensors\nX_test_tensor = (torch.tensor(X_test, dtype=torch.float32) / 255).permute(0, 3, 1, 2)\ny_test_tensor = torch.tensor(y_test, dtype=torch.float32)\n\n# Create DataLoader for test set\ntest_dataset = TensorDataset(X_test_tensor, y_test_tensor)\ntest_loader = DataLoader(test_dataset, batch_size=32, shuffle=False)\n\n# Switch to evaluation mode\ncnn_gru_model.eval()\n\n# Collect predictions and true labels\nall_preds = []\nall_labels = []\n\nwith torch.no_grad():\n    for images, labels in test_loader:\n        images, labels = images.cuda(), labels.cuda()\n        \n        # Get model outputs and apply sigmoid to get probabilities\n        outputs = torch.sigmoid(cnn_gru_model(images))\n        \n        # Convert probabilities to binary predictions with threshold 0.5\n        preds = (outputs >= 0.5).float()\n        \n        # Append predictions and labels to lists\n        all_preds.extend(preds.cpu().numpy())\n        all_labels.extend(labels.cpu().numpy())\n\n# Convert lists to numpy arrays for metrics calculation\nall_preds = np.array(all_preds).flatten()\nall_labels = np.array(all_labels).flatten()\n\n# Calculate evaluation metrics\naccuracy = accuracy_score(all_labels, all_preds)\nprecision = precision_score(all_labels, all_preds)\nrecall = recall_score(all_labels, all_preds)\nf1 = f1_score(all_labels, all_preds)\n\n# Print the evaluation metrics\nprint(\"Evaluating on test data:\")\nprint(f\"Accuracy: {accuracy:.2f}\")\nprint(f\"Precision: {precision:.2f}\")\nprint(f\"Recall: {recall:.2f}\")\nprint(f\"F1 Score: {f1:.2f}\")\n\n# Confusion Matrix\nconf_matrix = confusion_matrix(all_labels, all_preds)\n\n# Plotting the Confusion Matrix\nplt.figure(figsize=(8, 6))\nsns.heatmap(conf_matrix, annot=True, fmt=\"d\", cmap=\"Blues\", xticklabels=[0, 1], yticklabels=[0, 1])\nplt.xlabel(\"Predicted Labels\")\nplt.ylabel(\"True Labels\")\nplt.title(\"Confusion Matrix on Test Data\")\nplt.show()\n","metadata":{"execution":{"iopub.status.busy":"2024-10-29T12:30:17.377507Z","iopub.execute_input":"2024-10-29T12:30:17.377808Z","iopub.status.idle":"2024-10-29T12:30:28.671390Z","shell.execute_reply.started":"2024-10-29T12:30:17.377765Z","shell.execute_reply":"2024-10-29T12:30:28.670330Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"pip install torchsummary\n","metadata":{"execution":{"iopub.status.busy":"2024-10-29T12:32:40.837661Z","iopub.execute_input":"2024-10-29T12:32:40.838020Z","iopub.status.idle":"2024-10-29T12:32:49.023921Z","shell.execute_reply.started":"2024-10-29T12:32:40.837975Z","shell.execute_reply":"2024-10-29T12:32:49.023020Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Model Summary with pre trained layers\nfrom torchsummary import summary\n\n# Display a summary of the model structure with input shape (3, 224, 224)\ncnn_gru_model = CNNGRUModel().cuda()  # Ensure model is on the GPU if using cuda\nsummary(cnn_gru_model, input_size=(3, 224, 224))\n","metadata":{"execution":{"iopub.status.busy":"2024-10-29T12:32:49.808742Z","iopub.execute_input":"2024-10-29T12:32:49.809051Z","iopub.status.idle":"2024-10-29T12:32:50.537867Z","shell.execute_reply.started":"2024-10-29T12:32:49.809003Z","shell.execute_reply":"2024-10-29T12:32:50.537089Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"pip install torchviz\n","metadata":{"execution":{"iopub.status.busy":"2024-10-29T12:33:13.658881Z","iopub.execute_input":"2024-10-29T12:33:13.659193Z","iopub.status.idle":"2024-10-29T12:33:21.981466Z","shell.execute_reply.started":"2024-10-29T12:33:13.659150Z","shell.execute_reply":"2024-10-29T12:33:21.980372Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from torchviz import make_dot\nimport torch\n\n# Create a sample input tensor with the shape expected by the model\nsample_input = torch.randn(1, 3, 224, 224).cuda()  # Ensure tensor is on GPU if model is on GPU\n\n# Perform a forward pass to capture the computation graph\ncnn_gru_model = CNNGRUModel().cuda()  # Ensure model is on GPU if using cuda\noutput = cnn_gru_model(sample_input)\n\n# Generate the graph and save as PNG\ngraph = make_dot(output, params=dict(cnn_gru_model.named_parameters()))\ngraph.render(\"cnn_gru_model_architecture\")  # This will save it as a .pdf file by default\n\n# To save it as a .png file, remove 'format=\"png\"' and convert the .pdf to .png after rendering\ngraph.format = 'png'  # Manually set the format to PNG if possible\ngraph.render(\"cnn_gru_model_architecture\")\n","metadata":{"execution":{"iopub.status.busy":"2024-10-29T12:34:02.572597Z","iopub.execute_input":"2024-10-29T12:34:02.572921Z","iopub.status.idle":"2024-10-29T12:34:10.373439Z","shell.execute_reply.started":"2024-10-29T12:34:02.572876Z","shell.execute_reply":"2024-10-29T12:34:10.372416Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Model Summary without printing all pre trained layers\nimport torch\nimport torch.nn as nn\nfrom torchvision import models\n\nclass CNNGRUModel(nn.Module):\n    def __init__(self):\n        super(CNNGRUModel, self).__init__()\n        \n        # Pre-trained ResNet Backbone\n        resnet = models.resnet34(pretrained=True)\n        self.resnet_base = nn.Sequential(*list(resnet.children())[:-2])  # Use up to last conv layer\n        self.dropout = nn.Dropout(0.5)\n\n        # Calculate GRU input size based on ResNet output\n        dummy_input = torch.zeros(1, 3, 224, 224)\n        cnn_output = self.resnet_base(dummy_input)\n        _, num_filters, height, width = cnn_output.shape\n        self.gru_input_size = num_filters * width\n\n        # GRU with layer normalization\n        self.hidden_size = 128\n        self.num_layers = 2\n        self.gru = nn.GRU(input_size=self.gru_input_size, hidden_size=self.hidden_size, \n                          num_layers=self.num_layers, batch_first=True, bidirectional=True)\n        \n        # Fully connected layer\n        self.fc = nn.Sequential(\n            nn.LayerNorm(2 * self.hidden_size),\n            nn.Dropout(0.3),\n            nn.Linear(2 * self.hidden_size, 1)\n        )\n\n    def forward(self, x):\n        # Full forward pass\n        x = self.resnet_base(x)\n        x = self.dropout(x)\n        \n        # Reshape output to fit into GRU\n        batch_size, num_filters, height, width = x.shape\n        x = x.permute(0, 2, 3, 1)\n        x = x.reshape(batch_size, height, width * num_filters)\n\n        # GRU forward pass\n        h0 = torch.zeros(2 * self.num_layers, x.size(0), self.hidden_size).to(x.device)\n        out, _ = self.gru(x, h0)\n        out = out[:, -1, :]  # Take the output from the last time step\n        out = self.fc(out)\n        return out\n\n# Instantiate the model\nmodel = CNNGRUModel().cuda()\n\n# Custom summary function for full model with pretrained and custom layers\ndef custom_full_summary(model):\n    print(\"Full Model Summary:\\n\")\n    print(f\"{'Layer':<30} {'Output Shape':<30} {'Param #':<10}\")\n    print(\"=\"*80)\n\n    total_params = 0\n    \n    # ResNet Backbone summary\n    resnet_params = sum(p.numel() for p in model.resnet_base.parameters() if p.requires_grad)\n    total_params += resnet_params\n    resnet_output_shape = (1, 512, 7, 7)  # Expected output from ResNet layer\n    print(f\"{'ResNet Backbone':<30} {str(resnet_output_shape):<30} {resnet_params:<10}\")\n\n    # GRU Layer summary\n    gru_input_shape = (1, 7, model.gru_input_size)  # Simulated input shape for GRU layer\n    gru_output_shape = (gru_input_shape[0], gru_input_shape[1], 2 * model.hidden_size)\n    gru_params = sum(p.numel() for p in model.gru.parameters() if p.requires_grad)\n    total_params += gru_params\n    print(f\"{'GRU Layer':<30} {str(gru_output_shape):<30} {gru_params:<10}\")\n\n    # Fully Connected Layer summary\n    fc_input_shape = (gru_output_shape[0], gru_output_shape[2])\n    fc_output_shape = (fc_input_shape[0], 1)\n    fc_params = sum(p.numel() for p in model.fc.parameters() if p.requires_grad)\n    total_params += fc_params\n    print(f\"{'Fully Connected Layer':<30} {str(fc_output_shape):<30} {fc_params:<10}\")\n\n    print(\"=\"*80)\n    print(f\"Total Trainable Parameters: {total_params}\")\n\n# Call the custom summary\ncustom_full_summary(model)\n","metadata":{"execution":{"iopub.status.busy":"2024-10-30T23:53:14.505996Z","iopub.execute_input":"2024-10-30T23:53:14.506309Z","iopub.status.idle":"2024-10-30T23:53:15.190405Z","shell.execute_reply.started":"2024-10-30T23:53:14.506266Z","shell.execute_reply":"2024-10-30T23:53:15.189545Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}