CoolFace
Datasetpublic

AbdullahImran/DeepLearningProject

Deep Learning Project Dataset Summary This repository contains the datasets, trained models, notebooks, experiments, feature-extraction outputs, and supporting resources developed for a deep learning project focused on fire detection, fire severity classification, and related computer vision tasks. The project covers multiple stages of a deep learning workflow, including binary fire classification, three-class fire severity classification, feature extraction… See the full description on the dataset page: https://huggingface.co/datasets/AbdullahImran/DeepLearningProject.

sourceHugging Faceotherupdated 18d agoView on Hugging Face
0likes457downloads
DL Project Recommendations Code.ipynb3768 linesDownload Raw Back to Notebooks
1{
2 "cells": [
3  {
4   "cell_type": "code",
5   "execution_count": null,
6   "metadata": {
7    "colab": {
8     "base_uri": "https://localhost:8080/"
9    },
10    "id": "BzCAg-TDWp7Z",
11    "outputId": "4194cb15-a0f4-4fd4-f194-6376f73be379"
12   },
13   "outputs": [
14    {
15     "name": "stdout",
16     "output_type": "stream",
17     "text": [
18      "Mounted at /content/drive\n"
19     ]
20    }
21   ],
22   "source": [
23    "from google.colab import drive\n",
24    "drive.mount('/content/drive')"
25   ]
26  },
27  {
28   "cell_type": "markdown",
29   "metadata": {},
30   "source": [
31    "# Deep Learning Project: File 2 (Recommendation Generation)"
32   ]
33  },
34  {
35   "cell_type": "markdown",
36   "metadata": {},
37   "source": [
38    "## Loading Earlier Data:"
39   ]
40  },
41  {
42   "cell_type": "code",
43   "execution_count": null,
44   "metadata": {
45    "colab": {
46     "base_uri": "https://localhost:8080/"
47    },
48    "id": "n3h8hao9W8v6",
49    "outputId": "7537f557-9829-484b-d4cf-4f6b7b80c0f0"
50   },
51   "outputs": [
52    {
53     "name": "stdout",
54     "output_type": "stream",
55     "text": [
56      "Unzipped the file to /content/drive/MyDrive/Deep Learning Project/\n"
57     ]
58    }
59   ],
60   "source": [
61    "import zipfile\n",
62    "import os\n",
63    "\n",
64    "# Path to the zip file in Google Drive\n",
65    "zip_file_path = '/content/drive/MyDrive/Deep Learning Project/severity_dataset-20250117T075603Z-001.zip'  # Update with your file path\n",
66    "\n",
67    "# Path where you want to unzip the file (create a new folder if it doesn't exist)\n",
68    "target_folder = '/content/drive/MyDrive/Deep Learning Project/'  # Change this to your desired path\n",
69    "\n",
70    "# Create the target folder if it doesn't exist\n",
71    "os.makedirs(target_folder, exist_ok=True)\n",
72    "\n",
73    "# Unzipping the file\n",
74    "with zipfile.ZipFile(zip_file_path, 'r') as zip_ref:\n",
75    "    zip_ref.extractall(target_folder)\n",
76    "\n",
77    "print(f\"Unzipped the file to {target_folder}\")"
78   ]
79  },
80  {
81   "cell_type": "code",
82   "execution_count": null,
83   "metadata": {
84    "colab": {
85     "base_uri": "https://localhost:8080/"
86    },
87    "id": "xEFaH_dRflHX",
88    "outputId": "7a2e7d7d-f893-46d8-91a1-4c19d33b544e"
89   },
90   "outputs": [
91    {
92     "data": {
93      "text/plain": [
94       "['severity_dataset-20250117T075603Z-001.zip',\n",
95       " 'Tri Classification',\n",
96       " 'severity_dataset']"
97      ]
98     },
99     "execution_count": 6,
100     "metadata": {},
101     "output_type": "execute_result"
102    }
103   ],
104   "source": [
105    "os.listdir(target_folder)"
106   ]
107  },
108  {
109   "cell_type": "code",
110   "execution_count": null,
111   "metadata": {
112    "id": "C0y89c4HgNG9"
113   },
114   "outputs": [],
115   "source": [
116    "import tensorflow as tf\n",
117    "from tensorflow.keras import backend as K\n",
118    "\n",
119    "# Define focal loss\n",
120    "def focal_loss_fixed(y_true, y_pred, gamma=2.0, alpha=0.25):\n",
121    "    \"\"\"\n",
122    "    Focal Loss for multi-class classification.\n",
123    "    Args:\n",
124    "        y_true: True labels (one-hot encoded).\n",
125    "        y_pred: Predicted labels (softmax outputs).\n",
126    "        gamma: Focusing parameter (default=2.0).\n",
127    "        alpha: Balancing parameter (default=0.25).\n",
128    "    Returns:\n",
129    "        Computed focal loss value.\n",
130    "    \"\"\"\n",
131    "    y_true = tf.convert_to_tensor(y_true, dtype=tf.float32)\n",
132    "    y_pred = tf.convert_to_tensor(y_pred, dtype=tf.float32)\n",
133    "\n",
134    "    # Clip predictions to avoid log(0)\n",
135    "    y_pred = K.clip(y_pred, K.epsilon(), 1 - K.epsilon())\n",
136    "\n",
137    "    # Compute focal loss\n",
138    "    cross_entropy = -y_true * K.log(y_pred)\n",
139    "    weight = alpha * y_true * K.pow((1 - y_pred), gamma)\n",
140    "    loss = weight * cross_entropy\n",
141    "    return K.sum(loss, axis=-1)\n",
142    "\n",
143    "# Register custom loss\n",
144    "tf.keras.utils.get_custom_objects().update({\"focal_loss_fixed\": focal_loss_fixed})"
145   ]
146  },
147  {
148   "cell_type": "code",
149   "execution_count": null,
150   "metadata": {
151    "colab": {
152     "base_uri": "https://localhost:8080/"
153    },
154    "id": "OhVg2CDnhGSi",
155    "outputId": "4aac80df-1e71-4894-f11c-3530f35e77b8"
156   },
157   "outputs": [
158    {
159     "name": "stdout",
160     "output_type": "stream",
161     "text": [
162      "Drive already mounted at /content/drive; to attempt to forcibly remount, call drive.mount(\"/content/drive\", force_remount=True).\n"
163     ]
164    }
165   ],
166   "source": [
167    "from google.colab import drive\n",
168    "import os\n",
169    "import numpy as np\n",
170    "from tensorflow.keras.models import load_model\n",
171    "from sklearn.metrics import classification_report, confusion_matrix\n",
172    "import matplotlib.pyplot as plt\n",
173    "import seaborn as sns\n",
174    "\n",
175    "# Mount Google Drive\n",
176    "drive.mount('/content/drive')\n",
177    "\n",
178    "# Define the model path\n",
179    "model_path = '/content/drive/MyDrive/Deep Learning Project/Tri Classification/trial4.keras'"
180   ]
181  },
182  {
183   "cell_type": "code",
184   "execution_count": null,
185   "metadata": {
186    "colab": {
187     "base_uri": "https://localhost:8080/"
188    },
189    "id": "iNi2PDJRi596",
190    "outputId": "277637e6-3883-4454-9108-1d4ffe8fcc8c"
191   },
192   "outputs": [
193    {
194     "name": "stdout",
195     "output_type": "stream",
196     "text": [
197      "Model loaded successfully.\n"
198     ]
199    }
200   ],
201   "source": [
202    "# Load the trained model\n",
203    "model = load_model(model_path)\n",
204    "print(\"Model loaded successfully.\")"
205   ]
206  },
207  {
208   "cell_type": "code",
209   "execution_count": null,
210   "metadata": {
211    "colab": {
212     "base_uri": "https://localhost:8080/"
213    },
214    "id": "lcM23zDZhs3t",
215    "outputId": "d0af5fca-8560-420f-b568-6801537137f9"
216   },
217   "outputs": [
218    {
219     "name": "stdout",
220     "output_type": "stream",
221     "text": [
222      "Found 321 images belonging to 3 classes.\n"
223     ]
224    }
225   ],
226   "source": [
227    "from tensorflow.keras.preprocessing.image import ImageDataGenerator\n",
228    "\n",
229    "# Define test dataset directory\n",
230    "test_dir = '/content/drive/MyDrive/Deep Learning Project/severity_dataset/test'\n",
231    "\n",
232    "# Data generator for test set (only rescaling)\n",
233    "img_height, img_width = 224, 224\n",
234    "batch_size = 32\n",
235    "\n",
236    "datagen = ImageDataGenerator(rescale=1.0 / 255)\n",
237    "\n",
238    "test_generator = datagen.flow_from_directory(\n",
239    "    test_dir,\n",
240    "    target_size=(img_height, img_width),\n",
241    "    batch_size=batch_size,\n",
242    "    class_mode='categorical',\n",
243    "    shuffle=False\n",
244    ")"
245   ]
246  },
247  {
248   "cell_type": "code",
249   "execution_count": null,
250   "metadata": {
251    "colab": {
252     "base_uri": "https://localhost:8080/"
253    },
254    "id": "iJ_HMNhGhyBY",
255    "outputId": "1ecf9fd9-c902-4b26-bf11-2a6b60d472f4"
256   },
257   "outputs": [
258    {
259     "name": "stderr",
260     "output_type": "stream",
261     "text": [
262      "/usr/local/lib/python3.11/dist-packages/keras/src/trainers/data_adapters/py_dataset_adapter.py:122: UserWarning: Your `PyDataset` class should call `super().__init__(**kwargs)` in its constructor. `**kwargs` can include `workers`, `use_multiprocessing`, `max_queue_size`. Do not pass these arguments to `fit()`, as they will be ignored.\n",
263      "  self._warn_if_super_not_called()\n"
264     ]
265    },
266    {
267     "name": "stdout",
268     "output_type": "stream",
269     "text": [
270      "\u001b[1m11/11\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m2s\u001b[0m 141ms/step - accuracy: 0.5661 - loss: 0.1637\n",
271      "Test Loss: 0.14495410025119781, Test Accuracy: 0.6199377179145813\n",
272      "\u001b[1m11/11\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m2s\u001b[0m 159ms/step\n"
273     ]
274    }
275   ],
276   "source": [
277    "# Evaluate the model\n",
278    "test_loss, test_accuracy = model.evaluate(test_generator, verbose=1)\n",
279    "print(f\"Test Loss: {test_loss}, Test Accuracy: {test_accuracy}\")\n",
280    "\n",
281    "# Predict classes\n",
282    "predictions = model.predict(test_generator, verbose=1)\n",
283    "predicted_classes = np.argmax(predictions, axis=1)\n",
284    "true_classes = test_generator.classes\n",
285    "class_labels = list(test_generator.class_indices.keys())"
286   ]
287  },
288  {
289   "cell_type": "code",
290   "execution_count": null,
291   "metadata": {
292    "colab": {
293     "base_uri": "https://localhost:8080/"
294    },
295    "id": "8V28Ur4eiPw7",
296    "outputId": "092fded0-84fe-428f-a57f-12c0a2bbcbf4"
297   },
298   "outputs": [
299    {
300     "name": "stdout",
301     "output_type": "stream",
302     "text": [
303      "\n",
304      "Classification Report:\n",
305      "              precision    recall  f1-score   support\n",
306      "\n",
307      "        mild       0.76      0.61      0.68       106\n",
308      "    moderate       0.49      0.58      0.53       109\n",
309      "      severe       0.66      0.67      0.66       106\n",
310      "\n",
311      "    accuracy                           0.62       321\n",
312      "   macro avg       0.64      0.62      0.63       321\n",
313      "weighted avg       0.64      0.62      0.62       321\n",
314      "\n",
315      "Classification report saved at: /content/drive/MyDrive/Deep Learning Project/Tri Classification/tri_classification_report_test.txt\n"
316     ]
317    }
318   ],
319   "source": [
320    "# Generate classification report\n",
321    "report = classification_report(true_classes, predicted_classes, target_names=class_labels)\n",
322    "print(\"\\nClassification Report:\")\n",
323    "print(report)\n",
324    "\n",
325    "# Save report to file\n",
326    "report_path = '/content/drive/MyDrive/Deep Learning Project/Tri Classification/tri_classification_report_test.txt'\n",
327    "with open(report_path, 'w') as f:\n",
328    "    f.write(report)\n",
329    "print(f\"Classification report saved at: {report_path}\")"
330   ]
331  },
332  {
333   "cell_type": "code",
334   "execution_count": null,
335   "metadata": {
336    "colab": {
337     "base_uri": "https://localhost:8080/",
338     "height": 564
339    },
340    "id": "dpp4IrSGjbJh",
341    "outputId": "f4d91647-e001-40bc-a08a-7c8393041a50"
342   },
343   "outputs": [
344    {
345     "data": {
346      "image/png": "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rZ9//tnUvnDhQlWsWDFDfQIAAKSViyXrXg+rdFcSX3/9dfXr10/h4eE6fvy4XnrpJTVv3lwLFixQYmKiJk6cmO4gBg8erKioKJ0+fVqpqan69ttvdejQIX3xxRf64Ycf0t0fAAAA/p10VxIPHz6sChUqSJIWLFigWrVqad68eZo1a5YWLVqUoSCaNGmipUuXatWqVfL09NTgwYN14MABLV26VPXr189QnwAAAGllsViy7PWwSncl0TAMpaamSpJWrVqlZ599VpJUsGBBXbx4McOB1KxZUytXrszw8QAAAMg8GVonceTIkZozZ47Wr1+vxo0bS5JiY2MVGBiYoSCKFCmiS5cumdrj4+NVpEiRDPUJAACQVjyWzyzdSeLEiRO1Y8cOvfnmmxowYIDtruSFCxeqevXqGQri999/V0pKiqk9OTlZp0+fzlCfAAAAyLh0DzeXK1fO7u7mv4wbN85ujcO0+P77720/L1++XD4+Prb3KSkpWr16tQoVKpTeEAEAANLlYZ47mFXSnSSeOnVKFotFjz32mCTp119/1bx581S6dGl17tw5XX01bdpU0p0/mKioKLttOXPmVKFChTR+/Pj0hggAAIB/Kd3DzW3atNHatWslSXFxcapfv75+/fVXDRgwQMOHD09XX6mpqUpNTVVISIjOnz9ve5+amqrk5GQdOnTIdmMMAABAVmGdRLN0J4n79u1T1apVJUnffPONypYtq02bNmnu3LmaNWtWhoKIjY1V3rx5M3QsAADAv8USOGbpHm6+deuWrFarpDtL4Dz//POSpJIlS+rs2bMZDuT69etav369Tp48aXpyS/fu3TPcLwAAANIv3UlimTJlNG3aNDVu3FgrV67UiBEjJElnzpyRv79/hoLYuXOnGjVqpMTERF2/fl1+fn66ePGicuXKpYCAAJJEAACQpR7eel/WSfdw8/vvv69PPvlEtWvXVuvWrVW+fHlJd+5U/msYOr169uyp5557TleuXJGHh4e2bNmiEydOqHLlyvrPf/6ToT4BAACQcemuJNauXVsXL17UtWvXlCdPHlt7586dlStXrgwFsWvXLn3yySdycXGRq6urkpOTVaRIEY0dO1ZRUVFq3rx5hvoFAABIC5eHeO5gVkl3JVGSXF1d7RJESSpUqJACAgIyFETOnDnl4nInlICAAJ08eVKS5OPjo1OnTmWoTwAA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69ZVeHi4GjZsqAYNGqhFixZyc3PTsWPH1LFjR7322mu2/W/fvm27eS9fvnxq0KCB5s6dq5o1ayo2NlabN2/WJ598Iinj39G0Hgc4AkmiE8mZM6fde4vFYtf21z/iTKTGP3nQ36WEhAS5urpq+/btcnV1tduWO3du288eHh6mm62ioqJ06dIlTZo0SaGhobJarYqIiNDNmzf/8ZzDhg1T8+bNTdvc3d3/xaeBo7i6umrlypXatGmTVqxYoSlTpmjAgAFaunSpJOnTTz+1+2Xlr2P+0rZtW3Xv3l1TpkzRvHnzFB4ebvvlKKPf0bQeBzgCSSIypFSpUoqJiVG7du1sbVu2bHFgRMiuSpUqpUWLFskwDNs/jhs3bpSXl5cee+wx+fn5KWfOnIqJiVFISIgk6cqVKzp8+LBq1aolSapYsaJSUlJ0/vx51axZM13n37hxoz766CM1atRIknTq1CldvHjRbp+cOXMqJSXFrq1SpUo6dOiQwsLCMvS5kT1ZLBZFRkYqMjJSgwcPVmhoqDZu3Kj8+fPr+PHjatu27T2PbdKkiTp37qxly5Zp3rx5dn//ZfQ7+m++20BWI0lEhrz99ttq3769qlSposjISM2dO1e//fabihQp4ujQkM107dpVEydO1FtvvaU333xThw4d0pAhQxQdHS0XFxflzp1bHTt2VJ8+feTv76+AgAANGDBALi7/t/hC8eLF1bZtW7Vr107jx49XxYoVdeHCBa1evVrlypVT48aN73n+YsWKac6cOapSpYquXbumPn36yMPDw26fQoUKafXq1YqMjJTValWePHk0ePBgPfvsswoJCVGLFi3k4uKi3bt3a9++fRo5cmSWXS9knZiYGK1evVoNGjRQQECAYmJidOHCBZUqVUrDhg1T9+7d5ePjo6efflrJycnatm2brly5oujoaEmSp6enmjZtqkGDBunAgQNq3bq1re+Mfkf/zXcbyGosgYMMeemllzRo0CC98847qly5sk6cOKEuXbo4OixkQwUKFNB///tf/frrrypfvrzeeOMNdezYUQMHDrTtM27cONWsWVPPPfec6tWrpxo1aqhy5cp2/cycOVPt2rVTr169VKJECTVt2lRbt261VR/v5bPPPtOVK1dUqVIlvfLKK+revbsCAgLs9hk/frxWrlypggULqmLFipKkhg0b6ocfftCKFSv0+OOP64knntAHH3yg0NDQTLoyeNC8vb21YcMGNWrUSMWLF9fAgQM1fvx4PfPMM+rUqZNmzJihmTNnKjw8XLVq1dKsWbNUuHBhuz7atm2r3bt3q2bNmqbvXka/oxk9DshqFsMwDEcHAQAAgOyFSiIAAABMSBIBAABgQpIIAAAAE5JEAAAAmJAkAgAAwIQkEQAAACYkiQAAADAhSQQAAIAJSSKANGvfvr2aNm1qe1+7dm316NHjgcexbt06WSwWxcfHZ4t+AOBRRJIIPOTat28vi8Uii8UiNzc3hYWFafjw4bp9+3aWn/vbb7/ViBEj0rSvIxKynTt36sUXX1RgYKDc3d1VrFgxvfbaazp8+PADiwEAHlYkicAj4Omnn9bZs2d15MgR9erVS0OHDtW4cePuuu/Nmzcz7bx+fn7y8vLKtP4y0w8//KAnnnhCycnJmjt3rg4cOKAvv/xSPj4+GjRokKPDA4BsjyQReARYrVYFBQUpNDRUXbp0Ub169fT9999L+r8h4lGjRil//vwqUaKEJOnUqVNq2bKlfH195efnpyZNmuj333+39ZmSkqLo6Gj5+vrK399f77zzjv7+qPe/DzcnJyerb9++KliwoKxWq8LCwvTZZ5/p999/V506dSRJefLkkcViUfv27SVJqampGjNmjAoXLiwPDw+VL19eCxcutDvPf//7XxUvXlweHh6qU6eOXZx3k5iYqA4dOqhRo0b6/vvvVa9ePRUuXFjVqlXTf/7zH33yySd3Pe7SpUtq3bq1ChQooFy5cik8PFzz58+322fhwoUKDw+Xh4eH/P39Va9ePV2/fl3SnWpp1apV5enpKV9fX0VGRurEiRO2Y7/77jtVqlRJ7u7uKlKkiIYNG2ar+BqGoaFDhyokJERWq1X58+dX9+7d7/s5ASAr5XB0AAAyn4eHhy5dumR7v3r1anl7e2vlypWSpFu3bqlhw4aKiIjQzz//rBw5cmjkyJF6+umntWfPHrm5uWn8+PGaNWuWPv/8c5UqVUrjx4/X4sWL9dRTT93zvO3atdPmzZs1efJklS9fXrGxsbp48aIKFiyoRYsW6YUXXtChQ4fk7e0tDw8PSdKYMWP05Zdfatq0aSpWrJg2bNigl19+Wfny5VOtWrV06tQpNW/eXN26dVPnzp21bds29erV676ff/ny5bp48aLeeeedu2739fW9a3tSUpIqV66svn37ytvbWz/++KNeeeUVFS1aVFWrVtXZs2fVunVrjR07Vs2aNdOff/6pn3/+WYZh6Pbt22ratKlee+01zZ8/Xzdv3tSvv/4qi8UiSfr555/Vrl07TZ48WTVr1tSxY8fUuXNnSdKQIUO0aNEiffDBB/rqq69UpkwZxcXFaffu3ff9nACQpQwAD7WoqCijSZMmhmEYRmpqqrFy5UrDarUavXv3tm0PDAw0kpOTbcfMmTPHKFGihJGammprS05ONjw8PIzly5cbhmEYwcHBxtixY23bb926ZTz22GO2cxmGYdSqVct4++23DcMwjEOHDhmSjJUrV941zrVr1xqSjCtXrtjakpKSjFy5chmbNm2y27djx45G69atDcMwjP79+xulS5e22963b19TX//r/fffNyQZly9fvuv2+8X0d40bNzZ69eplGIZhbN++3ZBk/P7776b9Ll26ZEgy1q1bd9d+6tata4wePdqubc6cOUZwcLBhGIYxfvx4o3jx4sbNmzfvGzMAPChUEoFHwA8//KDcuXPr1q1bSk1NVZs2bTR06FDb9vDwcLm5udne7969W0ePHjXNJ0xKStKxY8d09epVnT17VtWqVbNty5Ejh6pUqWIacv7Lrl275Orqqlq1aqU57qNHjyoxMVH169e3a79586YqVqwoSTpw4IBdHJIUERFx337vFeM/SUlJ0ejRo/XNN9/o9OnTunnzppKTk5UrVy5JUvny5VW3bl2Fh4erYcOGatCggVq0aKE8efLIz89P7du3V8OGDVW/fn3Vq1dPLVu2VHBwsKQ713zjxo0aNWqU3fmSkpKUmJioF198URMnTlSRIkX09NNPq1GjRnruueeUIwd/TQNwDP72AR4BderU0ccffyw3Nzflz5/flFh4enravU9ISFDlypU1d+5cU1/58uXLUAx/DR+nR0JCgiTpxx9/VIECBey2Wa3WDMUhScWLF5ckHTx48B8Tyv81btw4TZo0SRMnTlR4eLg8PT3Vo0cP280+rq6uWrlypTZt2qQVK1ZoypQpGjBggGJiYlS4cGHNnDlT3bt317Jly/T1119r4MCBWrlypZ544gklJCRo2LBhat68uem87u7uKliwoA4dOqRVq1Zp5cqV6tq1q8aNG6f169crZ86cGb4WAJBR3LgCPAI8PT0VFhamkJCQNFWeKlWqpCNHjiggIEBhYWF2Lx8fH/n4+Cg4OFgxMTG2Y27fvq3t27ffs8/w8HClpqZq/fr1d93+VyUzJSXF1la6dGlZrVadPHnSFEfBggUlSaVKldKvv/5q19eWLVvu+/kaNGigvHnzauzYsXfdfq9leDZu3KgmTZro5ZdfVvny5VWkSBHTcjkWi0WRkZEaNmyYdu7cKTc3Ny1evNi2vWLFiurfv782bdqksmXLat68eZLuXPNDhw6ZPmdYWJhcXO78Vezh4aHnnntOkydP1rp167R582bt3bv3vp8VALIKSSLghNq2bau8efOqSZMm+vnnnxUbG6t169ape/fu+uOPPyRJb7/9tt577z0tWbJEBw8eVNeuXe+7xmGhQoUUFRWlV199VUuWLLH1+c0330iSQkNDZbFY9MMPP+jChQtKSEiQl5eXevfurZ49e2r27Nk6duyYduzYoSlTpmj27NmSpDfeeENHjhxRnz59dOjQIc2bN0+zZs267+fz9PTUjBkz9OOPP+r555/XqlWr9Pvvv2vbtm1655139MYbb9z1uGLFitkqhQcOHNDrr7+uc+fO2bbHxMRo9OjR2rZtm06ePKlvv/1WFy5cUKlSpRQbG6v+/ftr8+bNOnHihFasWKEjR46oVKlSkqTBgwfriy++0LBhw/Tbb7/pwIED+uqrrzRw4EBJ0qxZs/TZZ59p3759On78uL788kt5eHgoNDQ0TX+mAJDpHD0pEsC/8783rqRn+9mzZ4127doZefPmNaxWq1GkSBHjtddeM65evWoYxp0bVd5++23D29vb8PX1NaKjo4127drd88YVwzCMGzduGD179jSCg4MNNzc3IywszPj8889t24cPH24EBQUZFovFiIqKMgzjzs02EydONEqUKGHkzJnTyJcvn9GwYUNj/fr1tuOWLl1qhIWFGVar1ahZs6bx+eef/+MNJ4ZhGFu3bjWaN29u5MuXz7BarUZYWJjRuXNn48iRI4ZhmG9cuXTpktGkSRMjd+7cRkBAgDFw4EC7z7x//36jYcOGtv6KFy9uTJkyxTAMw4iLizOaNm1q++yhoaHG4MGDjZSUFFs8y5YtM6pXr254eHgY3t7eRtWqVY3p06cbhmEYixcvNqpVq2Z4e3sbnp6exhNPPGGsWrXqvp8PALKSxTAyOMMbAAAAjyyGmwEAAGBCkggAAAATkkQAAACYkCQCAADAhCQRAAAAJiSJAAAAMCFJBAAAgAlJIgAAAExIEgEAAGBCkggAAAATkkQAAACY/D/Ta6zq1uBf1AAAAABJRU5ErkJggg==\n",
347      "text/plain": [
348       "<Figure size 800x600 with 2 Axes>"
349      ]
350     },
351     "metadata": {},
352     "output_type": "display_data"
353    }
354   ],
355   "source": [
356    "# Create confusion matrix\n",
357    "conf_matrix = confusion_matrix(true_classes, predicted_classes)\n",
358    "\n",
359    "# Plot confusion matrix\n",
360    "plt.figure(figsize=(8, 6))\n",
361    "sns.heatmap(conf_matrix, annot=True, fmt='d', cmap='Blues', xticklabels=class_labels, yticklabels=class_labels)\n",
362    "plt.xlabel('Predicted Classes')\n",
363    "plt.ylabel('True Classes')\n",
364    "plt.title('Confusion Matrix')\n",
365    "plt.show()"
366   ]
367  },
368  {
369   "cell_type": "code",
370   "execution_count": null,
371   "metadata": {
372    "colab": {
373     "base_uri": "https://localhost:8080/"
374    },
375    "id": "aJES-CJzjfYr",
376    "outputId": "126d655d-fe93-4c22-d8d9-263b6f8721ea"
377   },
378   "outputs": [
379    {
380     "metadata": {
381      "tags": null
382     },
383     "name": "stdout",
384     "output_type": "stream",
385     "text": [
386      "Model loaded successfully.\n",
387      "Found 1458 images belonging to 3 classes.\n",
388      "Found 309 images belonging to 3 classes.\n",
389      "Found 321 images belonging to 3 classes.\n",
390      "Epoch 1/50\n"
391     ]
392    },
393    {
394     "metadata": {
395      "tags": null
396     },
397     "name": "stderr",
398     "output_type": "stream",
399     "text": [
400      "/usr/local/lib/python3.11/dist-packages/keras/src/trainers/data_adapters/py_dataset_adapter.py:122: UserWarning: Your `PyDataset` class should call `super().__init__(**kwargs)` in its constructor. `**kwargs` can include `workers`, `use_multiprocessing`, `max_queue_size`. Do not pass these arguments to `fit()`, as they will be ignored.\n",
401      "  self._warn_if_super_not_called()\n"
402     ]
403    },
404    {
405     "name": "stdout",
406     "output_type": "stream",
407     "text": [
408      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 6s/step - accuracy: 0.7972 - loss: 0.0563\n",
409      "Epoch 1: val_loss improved from inf to 0.08950, saving model to /content/drive/MyDrive/Deep Learning Project/Tri Classification/xception_best.keras\n",
410      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m503s\u001b[0m 9s/step - accuracy: 0.7973 - loss: 0.0563 - val_accuracy: 0.7540 - val_loss: 0.0895 - learning_rate: 5.0000e-06\n",
411      "Epoch 2/50\n",
412      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 664ms/step - accuracy: 0.8090 - loss: 0.0520\n",
413      "Epoch 2: val_loss improved from 0.08950 to 0.08016, saving model to /content/drive/MyDrive/Deep Learning Project/Tri Classification/xception_best.keras\n",
414      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m38s\u001b[0m 738ms/step - accuracy: 0.8090 - loss: 0.0520 - val_accuracy: 0.7152 - val_loss: 0.0802 - learning_rate: 5.0000e-06\n",
415      "Epoch 3/50\n",
416      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 670ms/step - accuracy: 0.7873 - loss: 0.0547\n",
417      "Epoch 3: val_loss improved from 0.08016 to 0.07496, saving model to /content/drive/MyDrive/Deep Learning Project/Tri Classification/xception_best.keras\n",
418      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m38s\u001b[0m 732ms/step - accuracy: 0.7877 - loss: 0.0546 - val_accuracy: 0.7120 - val_loss: 0.0750 - learning_rate: 5.0000e-06\n",
419      "Epoch 4/50\n",
420      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 669ms/step - accuracy: 0.7604 - loss: 0.0547\n",
421      "Epoch 4: val_loss improved from 0.07496 to 0.07047, saving model to /content/drive/MyDrive/Deep Learning Project/Tri Classification/xception_best.keras\n",
422      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m39s\u001b[0m 731ms/step - accuracy: 0.7608 - loss: 0.0545 - val_accuracy: 0.7120 - val_loss: 0.0705 - learning_rate: 5.0000e-06\n",
423      "Epoch 5/50\n",
424      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 674ms/step - accuracy: 0.7784 - loss: 0.0451\n",
425      "Epoch 5: val_loss improved from 0.07047 to 0.06785, saving model to /content/drive/MyDrive/Deep Learning Project/Tri Classification/xception_best.keras\n",
426      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m39s\u001b[0m 736ms/step - accuracy: 0.7787 - loss: 0.0451 - val_accuracy: 0.7120 - val_loss: 0.0679 - learning_rate: 5.0000e-06\n",
427      "Epoch 6/50\n",
428      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 683ms/step - accuracy: 0.7794 - loss: 0.0436\n",
429      "Epoch 6: val_loss improved from 0.06785 to 0.06544, saving model to /content/drive/MyDrive/Deep Learning Project/Tri Classification/xception_best.keras\n",
430      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m38s\u001b[0m 755ms/step - accuracy: 0.7797 - loss: 0.0436 - val_accuracy: 0.7152 - val_loss: 0.0654 - learning_rate: 5.0000e-06\n",
431      "Epoch 7/50\n",
432      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 676ms/step - accuracy: 0.7973 - loss: 0.0431\n",
433      "Epoch 7: val_loss improved from 0.06544 to 0.06366, saving model to /content/drive/MyDrive/Deep Learning Project/Tri Classification/xception_best.keras\n",
434      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m41s\u001b[0m 759ms/step - accuracy: 0.7973 - loss: 0.0430 - val_accuracy: 0.7314 - val_loss: 0.0637 - learning_rate: 5.0000e-06\n",
435      "Epoch 8/50\n",
436      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 677ms/step - accuracy: 0.7938 - loss: 0.0449\n",
437      "Epoch 8: val_loss improved from 0.06366 to 0.06231, saving model to /content/drive/MyDrive/Deep Learning Project/Tri Classification/xception_best.keras\n",
438      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m39s\u001b[0m 768ms/step - accuracy: 0.7941 - loss: 0.0449 - val_accuracy: 0.7346 - val_loss: 0.0623 - learning_rate: 5.0000e-06\n",
439      "Epoch 9/50\n",
440      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 660ms/step - accuracy: 0.8010 - loss: 0.0437\n",
441      "Epoch 9: val_loss improved from 0.06231 to 0.06125, saving model to /content/drive/MyDrive/Deep Learning Project/Tri Classification/xception_best.keras\n",
442      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m38s\u001b[0m 723ms/step - accuracy: 0.8009 - loss: 0.0437 - val_accuracy: 0.7346 - val_loss: 0.0613 - learning_rate: 5.0000e-06\n",
443      "Epoch 10/50\n",
444      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 675ms/step - accuracy: 0.8041 - loss: 0.0416\n",
445      "Epoch 10: val_loss improved from 0.06125 to 0.06061, saving model to /content/drive/MyDrive/Deep Learning Project/Tri Classification/xception_best.keras\n",
446      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m41s\u001b[0m 740ms/step - accuracy: 0.8041 - loss: 0.0416 - val_accuracy: 0.7379 - val_loss: 0.0606 - learning_rate: 5.0000e-06\n",
447      "Epoch 11/50\n",
448      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 674ms/step - accuracy: 0.7977 - loss: 0.0431\n",
449      "Epoch 11: val_loss improved from 0.06061 to 0.05919, saving model to /content/drive/MyDrive/Deep Learning Project/Tri Classification/xception_best.keras\n",
450      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m42s\u001b[0m 750ms/step - accuracy: 0.7978 - loss: 0.0431 - val_accuracy: 0.7411 - val_loss: 0.0592 - learning_rate: 5.0000e-06\n",
451      "Epoch 12/50\n",
452      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 669ms/step - accuracy: 0.8169 - loss: 0.0383\n",
453      "Epoch 12: val_loss improved from 0.05919 to 0.05873, saving model to /content/drive/MyDrive/Deep Learning Project/Tri Classification/xception_best.keras\n",
454      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m41s\u001b[0m 758ms/step - accuracy: 0.8169 - loss: 0.0384 - val_accuracy: 0.7379 - val_loss: 0.0587 - learning_rate: 5.0000e-06\n",
455      "Epoch 13/50\n",
456      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 668ms/step - accuracy: 0.8073 - loss: 0.0422\n",
457      "Epoch 13: val_loss improved from 0.05873 to 0.05861, saving model to /content/drive/MyDrive/Deep Learning Project/Tri Classification/xception_best.keras\n",
458      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m37s\u001b[0m 728ms/step - accuracy: 0.8074 - loss: 0.0421 - val_accuracy: 0.7379 - val_loss: 0.0586 - learning_rate: 5.0000e-06\n",
459      "Epoch 14/50\n",
460      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 670ms/step - accuracy: 0.8079 - loss: 0.0393\n",
461      "Epoch 14: val_loss improved from 0.05861 to 0.05827, saving model to /content/drive/MyDrive/Deep Learning Project/Tri Classification/xception_best.keras\n",
462      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m38s\u001b[0m 731ms/step - accuracy: 0.8079 - loss: 0.0393 - val_accuracy: 0.7411 - val_loss: 0.0583 - learning_rate: 5.0000e-06\n",
463      "Epoch 15/50\n",
464      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 682ms/step - accuracy: 0.7989 - loss: 0.0450\n",
465      "Epoch 15: val_loss improved from 0.05827 to 0.05819, saving model to /content/drive/MyDrive/Deep Learning Project/Tri Classification/xception_best.keras\n",
466      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m38s\u001b[0m 742ms/step - accuracy: 0.7990 - loss: 0.0449 - val_accuracy: 0.7476 - val_loss: 0.0582 - learning_rate: 5.0000e-06\n",
467      "Epoch 16/50\n",
468      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 672ms/step - accuracy: 0.8301 - loss: 0.0368\n",
469      "Epoch 16: val_loss improved from 0.05819 to 0.05804, saving model to /content/drive/MyDrive/Deep Learning Project/Tri Classification/xception_best.keras\n",
470      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m38s\u001b[0m 742ms/step - accuracy: 0.8298 - loss: 0.0369 - val_accuracy: 0.7476 - val_loss: 0.0580 - learning_rate: 5.0000e-06\n",
471      "Epoch 17/50\n",
472      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 661ms/step - accuracy: 0.8267 - loss: 0.0368\n",
473      "Epoch 17: val_loss improved from 0.05804 to 0.05762, saving model to /content/drive/MyDrive/Deep Learning Project/Tri Classification/xception_best.keras\n",
474      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m41s\u001b[0m 741ms/step - accuracy: 0.8263 - loss: 0.0368 - val_accuracy: 0.7379 - val_loss: 0.0576 - learning_rate: 5.0000e-06\n",
475      "Epoch 18/50\n",
476      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 669ms/step - accuracy: 0.8028 - loss: 0.0395\n",
477      "Epoch 18: val_loss improved from 0.05762 to 0.05753, saving model to /content/drive/MyDrive/Deep Learning Project/Tri Classification/xception_best.keras\n",
478      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m39s\u001b[0m 757ms/step - accuracy: 0.8028 - loss: 0.0395 - val_accuracy: 0.7346 - val_loss: 0.0575 - learning_rate: 5.0000e-06\n",
479      "Epoch 19/50\n",
480      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 662ms/step - accuracy: 0.7742 - loss: 0.0409\n",
481      "Epoch 19: val_loss improved from 0.05753 to 0.05747, saving model to /content/drive/MyDrive/Deep Learning Project/Tri Classification/xception_best.keras\n",
482      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m39s\u001b[0m 745ms/step - accuracy: 0.7748 - loss: 0.0409 - val_accuracy: 0.7314 - val_loss: 0.0575 - learning_rate: 5.0000e-06\n",
483      "Epoch 20/50\n",
484      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 663ms/step - accuracy: 0.8017 - loss: 0.0388\n",
485      "Epoch 20: val_loss did not improve from 0.05747\n",
486      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m37s\u001b[0m 698ms/step - accuracy: 0.8017 - loss: 0.0388 - val_accuracy: 0.7249 - val_loss: 0.0581 - learning_rate: 5.0000e-06\n",
487      "Epoch 21/50\n",
488      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 655ms/step - accuracy: 0.7887 - loss: 0.0403\n",
489      "Epoch 21: val_loss did not improve from 0.05747\n",
490      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m41s\u001b[0m 690ms/step - accuracy: 0.7891 - loss: 0.0402 - val_accuracy: 0.7282 - val_loss: 0.0581 - learning_rate: 5.0000e-06\n",
491      "Epoch 22/50\n",
492      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 651ms/step - accuracy: 0.8232 - loss: 0.0369\n",
493      "Epoch 22: val_loss did not improve from 0.05747\n",
494      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m41s\u001b[0m 687ms/step - accuracy: 0.8230 - loss: 0.0370 - val_accuracy: 0.7314 - val_loss: 0.0580 - learning_rate: 5.0000e-06\n",
495      "Epoch 23/50\n",
496      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 655ms/step - accuracy: 0.7911 - loss: 0.0436\n",
497      "Epoch 23: val_loss did not improve from 0.05747\n",
498      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m36s\u001b[0m 701ms/step - accuracy: 0.7913 - loss: 0.0435 - val_accuracy: 0.7346 - val_loss: 0.0580 - learning_rate: 5.0000e-06\n",
499      "Epoch 24/50\n",
500      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 661ms/step - accuracy: 0.7996 - loss: 0.0406\n",
501      "Epoch 24: val_loss did not improve from 0.05747\n",
502      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m41s\u001b[0m 707ms/step - accuracy: 0.7999 - loss: 0.0405 - val_accuracy: 0.7282 - val_loss: 0.0580 - learning_rate: 5.0000e-06\n",
503      "Epoch 25/50\n",
504      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 651ms/step - accuracy: 0.8284 - loss: 0.0354\n",
505      "Epoch 25: val_loss did not improve from 0.05747\n",
506      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m35s\u001b[0m 686ms/step - accuracy: 0.8283 - loss: 0.0354 - val_accuracy: 0.7346 - val_loss: 0.0592 - learning_rate: 5.0000e-06\n",
507      "Epoch 26/50\n",
508      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 648ms/step - accuracy: 0.8168 - loss: 0.0392\n",
509      "Epoch 26: val_loss did not improve from 0.05747\n",
510      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m36s\u001b[0m 684ms/step - accuracy: 0.8169 - loss: 0.0392 - val_accuracy: 0.7314 - val_loss: 0.0594 - learning_rate: 5.0000e-06\n",
511      "Epoch 27/50\n",
512      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 638ms/step - accuracy: 0.8182 - loss: 0.0378\n",
513      "Epoch 27: val_loss did not improve from 0.05747\n",
514      "\n",
515      "Epoch 27: ReduceLROnPlateau reducing learning rate to 2.499999936844688e-06.\n",
516      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m35s\u001b[0m 682ms/step - accuracy: 0.8181 - loss: 0.0378 - val_accuracy: 0.7314 - val_loss: 0.0590 - learning_rate: 5.0000e-06\n",
517      "Epoch 28/50\n",
518      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 655ms/step - accuracy: 0.8125 - loss: 0.0382\n",
519      "Epoch 28: val_loss did not improve from 0.05747\n",
520      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m42s\u001b[0m 698ms/step - accuracy: 0.8126 - loss: 0.0382 - val_accuracy: 0.7379 - val_loss: 0.0591 - learning_rate: 2.5000e-06\n",
521      "Epoch 29/50\n",
522      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 649ms/step - accuracy: 0.8079 - loss: 0.0373\n",
523      "Epoch 29: val_loss did not improve from 0.05747\n",
524      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m35s\u001b[0m 684ms/step - accuracy: 0.8080 - loss: 0.0373 - val_accuracy: 0.7443 - val_loss: 0.0587 - learning_rate: 2.5000e-06\n",
525      "Epoch 30/50\n",
526      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 649ms/step - accuracy: 0.8030 - loss: 0.0417\n",
527      "Epoch 30: val_loss did not improve from 0.05747\n",
528      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m36s\u001b[0m 685ms/step - accuracy: 0.8032 - loss: 0.0417 - val_accuracy: 0.7379 - val_loss: 0.0588 - learning_rate: 2.5000e-06\n",
529      "Epoch 31/50\n",
530      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 652ms/step - accuracy: 0.8273 - loss: 0.0349\n",
531      "Epoch 31: val_loss did not improve from 0.05747\n",
532      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m36s\u001b[0m 697ms/step - accuracy: 0.8272 - loss: 0.0349 - val_accuracy: 0.7314 - val_loss: 0.0588 - learning_rate: 2.5000e-06\n",
533      "Epoch 32/50\n",
534      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 646ms/step - accuracy: 0.8218 - loss: 0.0358\n",
535      "Epoch 32: val_loss did not improve from 0.05747\n",
536      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m35s\u001b[0m 682ms/step - accuracy: 0.8219 - loss: 0.0358 - val_accuracy: 0.7314 - val_loss: 0.0593 - learning_rate: 2.5000e-06\n",
537      "Epoch 33/50\n",
538      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 656ms/step - accuracy: 0.8031 - loss: 0.0376\n",
539      "Epoch 33: val_loss did not improve from 0.05747\n",
540      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m41s\u001b[0m 693ms/step - accuracy: 0.8034 - loss: 0.0376 - val_accuracy: 0.7379 - val_loss: 0.0593 - learning_rate: 2.5000e-06\n",
541      "Epoch 34/50\n",
542      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 651ms/step - accuracy: 0.8369 - loss: 0.0361\n",
543      "Epoch 34: val_loss did not improve from 0.05747\n",
544      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m42s\u001b[0m 696ms/step - accuracy: 0.8369 - loss: 0.0361 - val_accuracy: 0.7282 - val_loss: 0.0596 - learning_rate: 2.5000e-06\n",
545      "Epoch 34: early stopping\n",
546      "Restoring model weights from the end of the best epoch: 19.\n",
547      "\u001b[1m11/11\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m4s\u001b[0m 341ms/step - accuracy: 0.7248 - loss: 0.0765\n",
548      "\u001b[1m11/11\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m7s\u001b[0m 350ms/step\n",
549      "\n",
550      "Classification Report:\n",
551      "              precision    recall  f1-score   support\n",
552      "\n",
553      "        mild       0.88      0.82      0.85       106\n",
554      "    moderate       0.66      0.61      0.64       109\n",
555      "      severe       0.67      0.76      0.71       106\n",
556      "\n",
557      "    accuracy                           0.73       321\n",
558      "   macro avg       0.74      0.73      0.73       321\n",
559      "weighted avg       0.74      0.73      0.73       321\n",
560      "\n"
561     ]
562    }
563   ],
564   "source": [
565    "import tensorflow as tf\n",
566    "from tensorflow.keras.models import load_model\n",
567    "from tensorflow.keras.callbacks import ModelCheckpoint, TerminateOnNaN, EarlyStopping, ReduceLROnPlateau\n",
568    "from tensorflow.keras.optimizers import Adam\n",
569    "from tensorflow.keras.preprocessing.image import ImageDataGenerator\n",
570    "from sklearn.metrics import classification_report, precision_recall_fscore_support\n",
571    "import numpy as np\n",
572    "import os\n",
573    "import json\n",
574    "import matplotlib.pyplot as plt\n",
575    "\n",
576    "# Define the custom focal loss function\n",
577    "def focal_loss_fixed(y_true, y_pred, gamma=2.5, alpha=0.25):\n",
578    "    epsilon = 1e-7\n",
579    "    y_true = tf.cast(y_true, tf.float32)\n",
580    "    y_pred = tf.clip_by_value(y_pred, epsilon, 1. - epsilon)\n",
581    "\n",
582    "    class_weights = tf.constant([1.0, 1.5, 1.2])  # Class weights\n",
583    "    sample_weights = tf.reduce_sum(y_true * class_weights, axis=-1)\n",
584    "\n",
585    "    cross_entropy = -y_true * tf.math.log(y_pred)\n",
586    "    pt = tf.where(y_true == 1, y_pred, 1 - y_pred)\n",
587    "    weight = tf.pow(1. - pt, gamma)\n",
588    "    focal = alpha * weight * cross_entropy * tf.expand_dims(sample_weights, -1)\n",
589    "    focal = tf.where(tf.math.is_finite(focal), focal, epsilon)\n",
590    "    return tf.reduce_mean(tf.reduce_sum(focal, axis=1))\n",
591    "\n",
592    "# Load the saved model from Google Drive\n",
593    "model_path = '/content/drive/MyDrive/Deep Learning Project/Tri Classification/trial4.keras'\n",
594    "model = load_model(model_path, custom_objects={'focal_loss_fixed': focal_loss_fixed})\n",
595    "print(\"Model loaded successfully.\")\n",
596    "\n",
597    "# Data preparation with augmentation\n",
598    "train_datagen = ImageDataGenerator(\n",
599    "    rescale=1./255,\n",
600    "    rotation_range=25,\n",
601    "    width_shift_range=0.2,\n",
602    "    height_shift_range=0.2,\n",
603    "    zoom_range=0.2,\n",
604    "    horizontal_flip=True,\n",
605    "    shear_range=0.15,\n",
606    "    brightness_range=[0.8, 1.2],\n",
607    "    preprocessing_function=lambda x: tf.image.random_contrast(x, 0.8, 1.2)\n",
608    ")\n",
609    "val_datagen = ImageDataGenerator(rescale=1./255)\n",
610    "test_datagen = ImageDataGenerator(rescale=1./255)\n",
611    "\n",
612    "# Adjust data directories and loading\n",
613    "train_data = train_datagen.flow_from_directory(\n",
614    "    '/content/drive/MyDrive/Deep Learning Project/severity_dataset/train',\n",
615    "    target_size=(224, 224),\n",
616    "    batch_size=32,\n",
617    "    class_mode='categorical'\n",
618    ")\n",
619    "val_data = val_datagen.flow_from_directory(\n",
620    "    '/content/drive/MyDrive/Deep Learning Project/severity_dataset/val',\n",
621    "    target_size=(224, 224),\n",
622    "    batch_size=32,\n",
623    "    class_mode='categorical'\n",
624    ")\n",
625    "test_data = test_datagen.flow_from_directory(\n",
626    "    '/content/drive/MyDrive/Deep Learning Project/severity_dataset/test',\n",
627    "    target_size=(224, 224),\n",
628    "    batch_size=32,\n",
629    "    class_mode='categorical',\n",
630    "    shuffle=False\n",
631    ")\n",
632    "\n",
633    "# Define save path in Google Drive\n",
634    "save_path = '/content/drive/MyDrive/Deep Learning Project/Tri Classification/xception_best.keras'\n",
635    "\n",
636    "# Callbacks for training\n",
637    "callbacks = [\n",
638    "    ModelCheckpoint(\n",
639    "        save_path,\n",
640    "        save_best_only=True,\n",
641    "        monitor='val_loss',\n",
642    "        mode='min',\n",
643    "        verbose=1\n",
644    "    ),\n",
645    "    TerminateOnNaN(),\n",
646    "    EarlyStopping(\n",
647    "        monitor='val_loss',\n",
648    "        patience=15,\n",
649    "        restore_best_weights=True,\n",
650    "        verbose=1\n",
651    "    ),\n",
652    "    ReduceLROnPlateau(\n",
653    "        monitor='val_loss',\n",
654    "        factor=0.5,\n",
655    "        patience=8,\n",
656    "        min_lr=1e-7,\n",
657    "        verbose=1\n",
658    "    )\n",
659    "]\n",
660    "\n",
661    "# Compile model\n",
662    "optimizer = Adam(\n",
663    "    learning_rate=5e-6,\n",
664    "    clipnorm=1.0,\n",
665    "    beta_1=0.9,\n",
666    "    beta_2=0.999,\n",
667    "    epsilon=1e-7\n",
668    ")\n",
669    "model.compile(\n",
670    "    optimizer=optimizer,\n",
671    "    loss=focal_loss_fixed,\n",
672    "    metrics=['accuracy']\n",
673    ")\n",
674    "\n",
675    "# Train the model\n",
676    "try:\n",
677    "    history = model.fit(\n",
678    "        train_data,\n",
679    "        epochs=50,\n",
680    "        validation_data=val_data,\n",
681    "        callbacks=callbacks,\n",
682    "        verbose=1\n",
683    "    )\n",
684    "except Exception as e:\n",
685    "    print(f\"Training error: {str(e)}\")\n",
686    "    raise e\n",
687    "\n",
688    "# Evaluate the model\n",
689    "try:\n",
690    "    test_loss, test_accuracy = model.evaluate(test_data)\n",
691    "    y_true = test_data.classes\n",
692    "    y_pred = np.argmax(model.predict(test_data), axis=1)\n",
693    "\n",
694    "    # Classification report\n",
695    "    print(\"\\nClassification Report:\")\n",
696    "    print(classification_report(y_true, y_pred, target_names=['mild', 'moderate', 'severe']))\n",
697    "\n",
698    "except Exception as e:\n",
699    "    print(f\"Evaluation error: {str(e)}\")\n",
700    "    raise e"
701   ]
702  },
703  {
704   "cell_type": "code",
705   "execution_count": null,
706   "metadata": {
707    "colab": {
708     "base_uri": "https://localhost:8080/"
709    },
710    "id": "3QMiozB3jlFb",
711    "outputId": "cf163484-cf49-4d92-a17e-1893ced1ae46"
712   },
713   "outputs": [
714    {
715     "name": "stderr",
716     "output_type": "stream",
717     "text": [
718      "/usr/local/lib/python3.11/dist-packages/keras/src/optimizers/base_optimizer.py:33: UserWarning: Argument `decay` is no longer supported and will be ignored.\n",
719      "  warnings.warn(\n"
720     ]
721    },
722    {
723     "name": "stdout",
724     "output_type": "stream",
725     "text": [
726      "Epoch 1/20\n",
727      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 830ms/step - accuracy: 0.8046 - loss: 0.0855\n",
728      "Epoch 1: val_loss improved from inf to 0.12490, saving model to best_exception2.keras\n",
729      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m73s\u001b[0m 1s/step - accuracy: 0.8043 - loss: 0.0857 - val_accuracy: 0.7379 - val_loss: 0.1249 - learning_rate: 1.0000e-04\n",
730      "Epoch 2/20\n",
731      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 673ms/step - accuracy: 0.7970 - loss: 0.0837\n",
732      "Epoch 2: val_loss did not improve from 0.12490\n",
733      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m57s\u001b[0m 709ms/step - accuracy: 0.7971 - loss: 0.0838 - val_accuracy: 0.7508 - val_loss: 0.1316 - learning_rate: 1.0000e-04\n",
734      "Epoch 3/20\n",
735      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 664ms/step - accuracy: 0.8344 - loss: 0.0697\n",
736      "Epoch 3: val_loss did not improve from 0.12490\n",
737      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m42s\u001b[0m 721ms/step - accuracy: 0.8343 - loss: 0.0698 - val_accuracy: 0.6893 - val_loss: 0.1402 - learning_rate: 1.0000e-04\n",
738      "Epoch 4/20\n",
739      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 663ms/step - accuracy: 0.8377 - loss: 0.0680\n",
740      "Epoch 4: val_loss did not improve from 0.12490\n",
741      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m41s\u001b[0m 720ms/step - accuracy: 0.8373 - loss: 0.0682 - val_accuracy: 0.7638 - val_loss: 0.1381 - learning_rate: 1.0000e-04\n",
742      "Epoch 5/20\n",
743      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 670ms/step - accuracy: 0.8276 - loss: 0.0682\n",
744      "Epoch 5: val_loss did not improve from 0.12490\n",
745      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m41s\u001b[0m 727ms/step - accuracy: 0.8278 - loss: 0.0682 - val_accuracy: 0.7411 - val_loss: 0.1637 - learning_rate: 1.0000e-04\n",
746      "Epoch 6/20\n",
747      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 667ms/step - accuracy: 0.8476 - loss: 0.0647\n",
748      "Epoch 6: val_loss did not improve from 0.12490\n",
749      "\n",
750      "Epoch 6: ReduceLROnPlateau reducing learning rate to 2.9999999242136255e-05.\n",
751      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m40s\u001b[0m 714ms/step - accuracy: 0.8475 - loss: 0.0648 - val_accuracy: 0.7120 - val_loss: 0.1635 - learning_rate: 1.0000e-04\n",
752      "Epoch 7/20\n",
753      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 669ms/step - accuracy: 0.8472 - loss: 0.0616\n",
754      "Epoch 7: val_loss did not improve from 0.12490\n",
755      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m42s\u001b[0m 726ms/step - accuracy: 0.8475 - loss: 0.0615 - val_accuracy: 0.7087 - val_loss: 0.1599 - learning_rate: 3.0000e-05\n",
756      "Epoch 8/20\n",
757      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 665ms/step - accuracy: 0.8738 - loss: 0.0521\n",
758      "Epoch 8: val_loss did not improve from 0.12490\n",
759      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m36s\u001b[0m 702ms/step - accuracy: 0.8737 - loss: 0.0522 - val_accuracy: 0.7217 - val_loss: 0.1676 - learning_rate: 3.0000e-05\n",
760      "Epoch 9/20\n",
761      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 671ms/step - accuracy: 0.8616 - loss: 0.0562\n",
762      "Epoch 9: val_loss did not improve from 0.12490\n",
763      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m38s\u001b[0m 708ms/step - accuracy: 0.8617 - loss: 0.0561 - val_accuracy: 0.7346 - val_loss: 0.1632 - learning_rate: 3.0000e-05\n",
764      "Epoch 10/20\n",
765      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 656ms/step - accuracy: 0.8507 - loss: 0.0534\n",
766      "Epoch 10: val_loss did not improve from 0.12490\n",
767      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m36s\u001b[0m 703ms/step - accuracy: 0.8512 - loss: 0.0532 - val_accuracy: 0.7346 - val_loss: 0.1670 - learning_rate: 3.0000e-05\n",
768      "Epoch 11/20\n",
769      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 660ms/step - accuracy: 0.9072 - loss: 0.0384\n",
770      "Epoch 11: val_loss did not improve from 0.12490\n",
771      "\n",
772      "Epoch 11: ReduceLROnPlateau reducing learning rate to 8.999999772640877e-06.\n",
773      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m37s\u001b[0m 717ms/step - accuracy: 0.9069 - loss: 0.0385 - val_accuracy: 0.7249 - val_loss: 0.1622 - learning_rate: 3.0000e-05\n",
774      "Epoch 11: early stopping\n",
775      "Restoring model weights from the end of the best epoch: 1.\n",
776      "\u001b[1m11/11\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m4s\u001b[0m 368ms/step - accuracy: 0.7297 - loss: 0.1377\n",
777      "\u001b[1m11/11\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m6s\u001b[0m 330ms/step\n",
778      "\n",
779      "Updated Classification Report:\n",
780      "              precision    recall  f1-score   support\n",
781      "\n",
782      "        mild       0.89      0.82      0.85       106\n",
783      "    moderate       0.71      0.61      0.66       109\n",
784      "      severe       0.67      0.81      0.74       106\n",
785      "\n",
786      "    accuracy                           0.75       321\n",
787      "   macro avg       0.75      0.75      0.75       321\n",
788      "weighted avg       0.75      0.75      0.75       321\n",
789      "\n"
790     ]
791    }
792   ],
793   "source": [
794    "# Adjust focal loss for higher focus on moderate and severe classes\n",
795    "def focal_loss_fixed(y_true, y_pred, gamma=2.0, alpha=0.35):\n",
796    "    \"\"\"Modified focal loss with gamma and alpha adjustments\"\"\"\n",
797    "    epsilon = 1e-7\n",
798    "    y_true = tf.cast(y_true, tf.float32)\n",
799    "    y_pred = tf.clip_by_value(y_pred, epsilon, 1. - epsilon)\n",
800    "\n",
801    "    class_weights = tf.constant([1.0, 2.0, 1.5])  # Emphasize moderate and severe classes\n",
802    "    sample_weights = tf.reduce_sum(y_true * class_weights, axis=-1)\n",
803    "\n",
804    "    cross_entropy = -y_true * tf.math.log(y_pred)\n",
805    "    pt = tf.where(y_true == 1, y_pred, 1 - y_pred)\n",
806    "    weight = tf.pow(1. - pt, gamma)\n",
807    "    focal = alpha * weight * cross_entropy * tf.expand_dims(sample_weights, -1)\n",
808    "    return tf.reduce_mean(tf.reduce_sum(focal, axis=1))\n",
809    "\n",
810    "# Adjust ImageDataGenerator for class balancing\n",
811    "train_datagen = ImageDataGenerator(\n",
812    "    rescale=1./255,\n",
813    "    rotation_range=30,\n",
814    "    width_shift_range=0.3,\n",
815    "    height_shift_range=0.3,\n",
816    "    zoom_range=0.3,\n",
817    "    horizontal_flip=True,\n",
818    "    fill_mode='nearest',\n",
819    "    shear_range=0.2,\n",
820    "    brightness_range=[0.8, 1.3],\n",
821    "    preprocessing_function=lambda x: tf.image.random_contrast(x, 0.8, 1.5)\n",
822    ")\n",
823    "\n",
824    "# Modified optimizer settings\n",
825    "optimizer = Adam(\n",
826    "    learning_rate=1e-4,  # Slightly higher learning rate to start\n",
827    "    decay=1e-6,          # Aggressive decay\n",
828    "    clipnorm=1.0,\n",
829    "    beta_1=0.9,\n",
830    "    beta_2=0.999,\n",
831    "    epsilon=1e-7\n",
832    ")\n",
833    "\n",
834    "# Updated callbacks with enhanced configurations\n",
835    "callbacks = [\n",
836    "    ModelCheckpoint(\n",
837    "        'best_exception2.keras',\n",
838    "        save_best_only=True,\n",
839    "        monitor='val_loss',\n",
840    "        mode='min',\n",
841    "        verbose=1\n",
842    "    ),\n",
843    "    TerminateOnNaN(),\n",
844    "    EarlyStopping(\n",
845    "        monitor='val_loss',\n",
846    "        patience=10,\n",
847    "        restore_best_weights=True,\n",
848    "        verbose=1\n",
849    "    ),\n",
850    "    ReduceLROnPlateau(\n",
851    "        monitor='val_loss',\n",
852    "        factor=0.3,\n",
853    "        patience=5,\n",
854    "        min_lr=1e-7,\n",
855    "        verbose=1\n",
856    "    )\n",
857    "]\n",
858    "\n",
859    "# Compile the model with updated focal loss\n",
860    "model.compile(\n",
861    "    optimizer=optimizer,\n",
862    "    loss=focal_loss_fixed,\n",
863    "    metrics=['accuracy']\n",
864    ")\n",
865    "\n",
866    "# Resume training for additional epochs\n",
867    "try:\n",
868    "    history = model.fit(\n",
869    "        train_data,\n",
870    "        epochs=20,  # Adjust number of additional epochs\n",
871    "        validation_data=val_data,\n",
872    "        callbacks=callbacks,\n",
873    "        verbose=1\n",
874    "    )\n",
875    "except Exception as e:\n",
876    "    print(f\"Training error: {str(e)}\")\n",
877    "    raise e\n",
878    "\n",
879    "# Re-evaluate the model after additional training\n",
880    "try:\n",
881    "    test_loss, test_accuracy = model.evaluate(test_data, steps=len(test_data))\n",
882    "    test_predictions = model.predict(test_data, steps=len(test_data))\n",
883    "    y_true = test_data.classes\n",
884    "    y_pred = np.argmax(test_predictions, axis=1)\n",
885    "\n",
886    "    precision, recall, f1, support = precision_recall_fscore_support(y_true, y_pred)\n",
887    "\n",
888    "    print(\"\\nUpdated Classification Report:\")\n",
889    "    print(classification_report(y_true, y_pred, target_names=['mild', 'moderate', 'severe']))\n",
890    "except Exception as e:\n",
891    "    print(f\"Evaluation error: {str(e)}\")\n",
892    "    raise e"
893   ]
894  },
895  {
896   "cell_type": "code",
897   "execution_count": null,
898   "metadata": {
899    "colab": {
900     "base_uri": "https://localhost:8080/"
901    },
902    "id": "oa6EJzfMrX8M",
903    "outputId": "43684372-5423-4df7-b25d-f6cfb7dd5406"
904   },
905   "outputs": [
906    {
907     "name": "stdout",
908     "output_type": "stream",
909     "text": [
910      "Found 1458 images belonging to 3 classes.\n",
911      "Found 309 images belonging to 3 classes.\n",
912      "Epoch 1/10\n",
913      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 487ms/step - accuracy: 0.3150 - loss: 1.1708\n",
914      "Epoch 1: val_loss improved from inf to 1.11522, saving model to xception_best_baseline.keras\n",
915      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m68s\u001b[0m 1s/step - accuracy: 0.3153 - loss: 1.1705 - val_accuracy: 0.3430 - val_loss: 1.1152 - learning_rate: 1.0000e-04\n",
916      "Epoch 2/10\n",
917      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 454ms/step - accuracy: 0.4059 - loss: 1.0731\n",
918      "Epoch 2: val_loss improved from 1.11522 to 1.04606, saving model to xception_best_baseline.keras\n",
919      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m45s\u001b[0m 532ms/step - accuracy: 0.4064 - loss: 1.0727 - val_accuracy: 0.4369 - val_loss: 1.0461 - learning_rate: 1.0000e-04\n",
920      "Epoch 3/10\n",
921      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 441ms/step - accuracy: 0.4730 - loss: 1.0116\n",
922      "Epoch 3: val_loss improved from 1.04606 to 0.99757, saving model to xception_best_baseline.keras\n",
923      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m40s\u001b[0m 509ms/step - accuracy: 0.4733 - loss: 1.0115 - val_accuracy: 0.4984 - val_loss: 0.9976 - learning_rate: 1.0000e-04\n",
924      "Epoch 4/10\n",
925      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 437ms/step - accuracy: 0.4841 - loss: 0.9866\n",
926      "Epoch 4: val_loss improved from 0.99757 to 0.96122, saving model to xception_best_baseline.keras\n",
927      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m26s\u001b[0m 494ms/step - accuracy: 0.4847 - loss: 0.9862 - val_accuracy: 0.5081 - val_loss: 0.9612 - learning_rate: 1.0000e-04\n",
928      "Epoch 5/10\n",
929      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 437ms/step - accuracy: 0.5456 - loss: 0.9345\n",
930      "Epoch 5: val_loss improved from 0.96122 to 0.93304, saving model to xception_best_baseline.keras\n",
931      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m27s\u001b[0m 487ms/step - accuracy: 0.5458 - loss: 0.9344 - val_accuracy: 0.5275 - val_loss: 0.9330 - learning_rate: 1.0000e-04\n",
932      "Epoch 6/10\n",
933      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 436ms/step - accuracy: 0.5446 - loss: 0.9199\n",
934      "Epoch 6: val_loss improved from 0.93304 to 0.91047, saving model to xception_best_baseline.keras\n",
935      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m27s\u001b[0m 487ms/step - accuracy: 0.5451 - loss: 0.9196 - val_accuracy: 0.5437 - val_loss: 0.9105 - learning_rate: 1.0000e-04\n",
936      "Epoch 7/10\n",
937      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 440ms/step - accuracy: 0.5844 - loss: 0.8936\n",
938      "Epoch 7: val_loss improved from 0.91047 to 0.89181, saving model to xception_best_baseline.keras\n",
939      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m41s\u001b[0m 492ms/step - accuracy: 0.5845 - loss: 0.8934 - val_accuracy: 0.5761 - val_loss: 0.8918 - learning_rate: 1.0000e-04\n",
940      "Epoch 8/10\n",
941      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 445ms/step - accuracy: 0.6084 - loss: 0.8737\n",
942      "Epoch 8: val_loss improved from 0.89181 to 0.87698, saving model to xception_best_baseline.keras\n",
943      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m27s\u001b[0m 496ms/step - accuracy: 0.6084 - loss: 0.8736 - val_accuracy: 0.5922 - val_loss: 0.8770 - learning_rate: 1.0000e-04\n",
944      "Epoch 9/10\n",
945      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 440ms/step - accuracy: 0.6045 - loss: 0.8709\n",
946      "Epoch 9: val_loss improved from 0.87698 to 0.86353, saving model to xception_best_baseline.keras\n",
947      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m27s\u001b[0m 492ms/step - accuracy: 0.6043 - loss: 0.8709 - val_accuracy: 0.5955 - val_loss: 0.8635 - learning_rate: 1.0000e-04\n",
948      "Epoch 10/10\n",
949      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 442ms/step - accuracy: 0.6311 - loss: 0.8394\n",
950      "Epoch 10: val_loss improved from 0.86353 to 0.85369, saving model to xception_best_baseline.keras\n",
951      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m41s\u001b[0m 494ms/step - accuracy: 0.6310 - loss: 0.8395 - val_accuracy: 0.5987 - val_loss: 0.8537 - learning_rate: 1.0000e-04\n",
952      "Restoring model weights from the end of the best epoch: 10.\n",
953      "Epoch 1/10\n",
954      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 1s/step - accuracy: 0.4857 - loss: 0.9853\n",
955      "Epoch 1: val_loss improved from 0.85369 to 0.81895, saving model to xception_best_baseline.keras\n",
956      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m115s\u001b[0m 1s/step - accuracy: 0.4867 - loss: 0.9843 - val_accuracy: 0.6246 - val_loss: 0.8190 - learning_rate: 1.0000e-05\n",
957      "Epoch 2/10\n",
958      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 615ms/step - accuracy: 0.6005 - loss: 0.8702\n",
959      "Epoch 2: val_loss improved from 0.81895 to 0.79507, saving model to xception_best_baseline.keras\n",
960      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m96s\u001b[0m 832ms/step - accuracy: 0.6011 - loss: 0.8697 - val_accuracy: 0.6375 - val_loss: 0.7951 - learning_rate: 1.0000e-05\n",
961      "Epoch 3/10\n",
962      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 588ms/step - accuracy: 0.6570 - loss: 0.7976\n",
963      "Epoch 3: val_loss improved from 0.79507 to 0.76283, saving model to xception_best_baseline.keras\n",
964      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m78s\u001b[0m 708ms/step - accuracy: 0.6569 - loss: 0.7977 - val_accuracy: 0.6570 - val_loss: 0.7628 - learning_rate: 1.0000e-05\n",
965      "Epoch 4/10\n",
966      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 612ms/step - accuracy: 0.6750 - loss: 0.7594\n",
967      "Epoch 4: val_loss improved from 0.76283 to 0.73081, saving model to xception_best_baseline.keras\n",
968      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m35s\u001b[0m 686ms/step - accuracy: 0.6751 - loss: 0.7593 - val_accuracy: 0.6893 - val_loss: 0.7308 - learning_rate: 1.0000e-05\n",
969      "Epoch 5/10\n",
970      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 615ms/step - accuracy: 0.6680 - loss: 0.7495\n",
971      "Epoch 5: val_loss improved from 0.73081 to 0.70178, saving model to xception_best_baseline.keras\n",
972      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m39s\u001b[0m 738ms/step - accuracy: 0.6685 - loss: 0.7491 - val_accuracy: 0.7152 - val_loss: 0.7018 - learning_rate: 1.0000e-05\n",
973      "Epoch 6/10\n",
974      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 587ms/step - accuracy: 0.7168 - loss: 0.7086\n",
975      "Epoch 6: val_loss improved from 0.70178 to 0.68145, saving model to xception_best_baseline.keras\n",
976      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m36s\u001b[0m 683ms/step - accuracy: 0.7166 - loss: 0.7086 - val_accuracy: 0.7346 - val_loss: 0.6815 - learning_rate: 1.0000e-05\n",
977      "Epoch 7/10\n",
978      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 609ms/step - accuracy: 0.7046 - loss: 0.6843\n",
979      "Epoch 7: val_loss improved from 0.68145 to 0.65888, saving model to xception_best_baseline.keras\n",
980      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m38s\u001b[0m 759ms/step - accuracy: 0.7047 - loss: 0.6844 - val_accuracy: 0.7508 - val_loss: 0.6589 - learning_rate: 1.0000e-05\n",
981      "Epoch 8/10\n",
982      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 609ms/step - accuracy: 0.7230 - loss: 0.6778\n",
983      "Epoch 8: val_loss improved from 0.65888 to 0.64567, saving model to xception_best_baseline.keras\n",
984      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m41s\u001b[0m 759ms/step - accuracy: 0.7232 - loss: 0.6775 - val_accuracy: 0.7540 - val_loss: 0.6457 - learning_rate: 1.0000e-05\n",
985      "Epoch 9/10\n",
986      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 607ms/step - accuracy: 0.7189 - loss: 0.6585\n",
987      "Epoch 9: val_loss improved from 0.64567 to 0.63323, saving model to xception_best_baseline.keras\n",
988      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m37s\u001b[0m 682ms/step - accuracy: 0.7194 - loss: 0.6579 - val_accuracy: 0.7540 - val_loss: 0.6332 - learning_rate: 1.0000e-05\n",
989      "Epoch 10/10\n",
990      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 580ms/step - accuracy: 0.7580 - loss: 0.5872\n",
991      "Epoch 10: val_loss improved from 0.63323 to 0.62285, saving model to xception_best_baseline.keras\n",
992      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m38s\u001b[0m 740ms/step - accuracy: 0.7577 - loss: 0.5879 - val_accuracy: 0.7605 - val_loss: 0.6228 - learning_rate: 1.0000e-05\n",
993      "Restoring model weights from the end of the best epoch: 10.\n",
994      "Found 321 images belonging to 3 classes.\n",
995      "\u001b[1m11/11\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m3s\u001b[0m 259ms/step - accuracy: 0.7070 - loss: 0.7121\n",
996      "\u001b[1m11/11\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m7s\u001b[0m 367ms/step\n",
997      "\n",
998      "Updated Classification Report:\n",
999      "              precision    recall  f1-score   support\n",
1000      "\n",
1001      "        mild       0.80      0.84      0.82       106\n",
1002      "    moderate       0.79      0.45      0.57       109\n",
1003      "      severe       0.66      0.92      0.77       106\n",
1004      "\n",
1005      "    accuracy                           0.74       321\n",
1006      "   macro avg       0.75      0.74      0.72       321\n",
1007      "weighted avg       0.75      0.74      0.72       321\n",
1008      "\n"
1009     ]
1010    }
1011   ],
1012   "source": [
1013    "import tensorflow as tf\n",
1014    "from tensorflow.keras.optimizers import Adam\n",
1015    "from tensorflow.keras.callbacks import ModelCheckpoint, EarlyStopping, ReduceLROnPlateau\n",
1016    "from tensorflow.keras.preprocessing.image import ImageDataGenerator\n",
1017    "from sklearn.metrics import classification_report, precision_recall_fscore_support\n",
1018    "import numpy as np\n",
1019    "\n",
1020    "# ImageDataGenerator with adjusted augmentations\n",
1021    "train_datagen = ImageDataGenerator(\n",
1022    "    rescale=1./255,\n",
1023    "    rotation_range=15,  # Reduced rotation\n",
1024    "    width_shift_range=0.2,\n",
1025    "    height_shift_range=0.2,\n",
1026    "    zoom_range=0.2,\n",
1027    "    horizontal_flip=True,\n",
1028    "    fill_mode='nearest'\n",
1029    ")\n",
1030    "\n",
1031    "val_datagen = ImageDataGenerator(rescale=1./255)\n",
1032    "\n",
1033    "# Load training and validation data\n",
1034    "train_data = train_datagen.flow_from_directory(\n",
1035    "    \"/content/drive/MyDrive/Deep Learning Project/severity_dataset/train\",\n",
1036    "    target_size=(224, 224),\n",
1037    "    batch_size=32,\n",
1038    "    class_mode=\"categorical\"\n",
1039    ")\n",
1040    "\n",
1041    "val_data = val_datagen.flow_from_directory(\n",
1042    "    \"/content/drive/MyDrive/Deep Learning Project/severity_dataset/val\",\n",
1043    "    target_size=(224, 224),\n",
1044    "    batch_size=32,\n",
1045    "    class_mode=\"categorical\"\n",
1046    ")\n",
1047    "\n",
1048    "# Load the pretrained Xception model and fine-tune\n",
1049    "base_model = tf.keras.applications.Xception(\n",
1050    "    weights='imagenet',\n",
1051    "    include_top=False,\n",
1052    "    input_shape=(224, 224, 3)\n",
1053    ")\n",
1054    "\n",
1055    "x = tf.keras.layers.GlobalAveragePooling2D()(base_model.output)\n",
1056    "x = tf.keras.layers.Dropout(0.4)(x)\n",
1057    "output = tf.keras.layers.Dense(3, activation='softmax')(x)\n",
1058    "\n",
1059    "model = tf.keras.Model(inputs=base_model.input, outputs=output)\n",
1060    "\n",
1061    "# Freeze the base model initially\n",
1062    "for layer in base_model.layers:\n",
1063    "    layer.trainable = False\n",
1064    "\n",
1065    "# Compile the model\n",
1066    "model.compile(\n",
1067    "    optimizer=Adam(learning_rate=1e-4),\n",
1068    "    loss='categorical_crossentropy',\n",
1069    "    metrics=['accuracy']\n",
1070    ")\n",
1071    "\n",
1072    "# Callbacks for monitoring and saving the best model\n",
1073    "callbacks = [\n",
1074    "    ModelCheckpoint(\n",
1075    "        'xception_best_baseline.keras',\n",
1076    "        save_best_only=True,\n",
1077    "        monitor='val_loss',\n",
1078    "        mode='min',\n",
1079    "        verbose=1\n",
1080    "    ),\n",
1081    "    EarlyStopping(\n",
1082    "        monitor='val_loss',\n",
1083    "        patience=5,\n",
1084    "        restore_best_weights=True,\n",
1085    "        verbose=1\n",
1086    "    ),\n",
1087    "    ReduceLROnPlateau(\n",
1088    "        monitor='val_loss',\n",
1089    "        factor=0.3,\n",
1090    "        patience=3,\n",
1091    "        min_lr=1e-7,\n",
1092    "        verbose=1\n",
1093    "    )\n",
1094    "]\n",
1095    "\n",
1096    "# Train the model\n",
1097    "history = model.fit(\n",
1098    "    train_data,\n",
1099    "    epochs=10,  # Start with fewer epochs to validate the new settings\n",
1100    "    validation_data=val_data,\n",
1101    "    callbacks=callbacks,\n",
1102    "    verbose=1\n",
1103    ")\n",
1104    "\n",
1105    "# Unfreeze the base model for fine-tuning\n",
1106    "for layer in base_model.layers:\n",
1107    "    layer.trainable = True\n",
1108    "\n",
1109    "model.compile(\n",
1110    "    optimizer=Adam(learning_rate=1e-5),  # Lower learning rate for fine-tuning\n",
1111    "    loss='categorical_crossentropy',\n",
1112    "    metrics=['accuracy']\n",
1113    ")\n",
1114    "\n",
1115    "# Continue training for fine-tuning\n",
1116    "fine_tune_history = model.fit(\n",
1117    "    train_data,\n",
1118    "    epochs=10,\n",
1119    "    validation_data=val_data,\n",
1120    "    callbacks=callbacks,\n",
1121    "    verbose=1\n",
1122    ")\n",
1123    "\n",
1124    "# Evaluate the model on the test set\n",
1125    "test_datagen = ImageDataGenerator(rescale=1./255)\n",
1126    "test_data = test_datagen.flow_from_directory(\n",
1127    "    \"/content/drive/MyDrive/Deep Learning Project/severity_dataset/test\",\n",
1128    "    target_size=(224, 224),\n",
1129    "    batch_size=32,\n",
1130    "    class_mode=\"categorical\",\n",
1131    "    shuffle=False\n",
1132    ")\n",
1133    "\n",
1134    "test_loss, test_accuracy = model.evaluate(test_data, steps=len(test_data))\n",
1135    "test_predictions = model.predict(test_data, steps=len(test_data))\n",
1136    "y_true = test_data.classes\n",
1137    "y_pred = np.argmax(test_predictions, axis=1)\n",
1138    "\n",
1139    "# Generate the classification report\n",
1140    "target_names = ['mild', 'moderate', 'severe']\n",
1141    "print(\"\\nUpdated Classification Report:\")\n",
1142    "print(classification_report(y_true, y_pred, target_names=target_names))"
1143   ]
1144  },
1145  {
1146   "cell_type": "markdown",
1147   "metadata": {
1148    "id": "nZKEcTAQ1y0z"
1149   },
1150   "source": [
1151    "Our hit and trial method since last 3 days has proven that either compromise on accuracy and get an overall better model with better prescion and recall, or get more accurate model with few class struggling in their prescion or recall.\n",
1152    "\n",
1153    "We always would prefer a model that is more representative of every class."
1154   ]
1155  },
1156  {
1157   "cell_type": "code",
1158   "execution_count": null,
1159   "metadata": {
1160    "colab": {
1161     "base_uri": "https://localhost:8080/"
1162    },
1163    "id": "jCXiG-zwu9Hg",
1164    "outputId": "9b31477b-4117-42a6-a665-d0540a597a7c"
1165   },
1166   "outputs": [
1167    {
1168     "name": "stderr",
1169     "output_type": "stream",
1170     "text": [
1171      "/usr/local/lib/python3.11/dist-packages/keras/src/optimizers/base_optimizer.py:33: UserWarning: Argument `decay` is no longer supported and will be ignored.\n",
1172      "  warnings.warn(\n"
1173     ]
1174    },
1175    {
1176     "name": "stdout",
1177     "output_type": "stream",
1178     "text": [
1179      "Epoch 1/20\n",
1180      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 497ms/step - accuracy: 0.6002 - loss: 0.1601\n",
1181      "Epoch 1: val_loss improved from inf to 0.14476, saving model to best_exception2.keras\n",
1182      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m41s\u001b[0m 659ms/step - accuracy: 0.6005 - loss: 0.1600 - val_accuracy: 0.6472 - val_loss: 0.1448 - learning_rate: 1.0000e-04\n",
1183      "Epoch 2/20\n",
1184      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 480ms/step - accuracy: 0.6090 - loss: 0.1521\n",
1185      "Epoch 2: val_loss did not improve from 0.14476\n",
1186      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m31s\u001b[0m 516ms/step - accuracy: 0.6089 - loss: 0.1521 - val_accuracy: 0.6343 - val_loss: 0.1465 - learning_rate: 1.0000e-04\n",
1187      "Epoch 3/20\n",
1188      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 472ms/step - accuracy: 0.6340 - loss: 0.1493\n",
1189      "Epoch 3: val_loss improved from 0.14476 to 0.14458, saving model to best_exception2.keras\n",
1190      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m41s\u001b[0m 524ms/step - accuracy: 0.6339 - loss: 0.1493 - val_accuracy: 0.6634 - val_loss: 0.1446 - learning_rate: 1.0000e-04\n",
1191      "Epoch 4/20\n",
1192      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 457ms/step - accuracy: 0.6128 - loss: 0.1552\n",
1193      "Epoch 4: val_loss improved from 0.14458 to 0.14435, saving model to best_exception2.keras\n",
1194      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m27s\u001b[0m 509ms/step - accuracy: 0.6128 - loss: 0.1552 - val_accuracy: 0.6537 - val_loss: 0.1443 - learning_rate: 1.0000e-04\n",
1195      "Epoch 5/20\n",
1196      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 467ms/step - accuracy: 0.6404 - loss: 0.1482\n",
1197      "Epoch 5: val_loss improved from 0.14435 to 0.14359, saving model to best_exception2.keras\n",
1198      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m41s\u001b[0m 519ms/step - accuracy: 0.6401 - loss: 0.1482 - val_accuracy: 0.6278 - val_loss: 0.1436 - learning_rate: 1.0000e-04\n",
1199      "Epoch 6/20\n",
1200      "\u001b[1m46/46\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 476ms/step - accuracy: 0.6210 - loss: 0.1417\n",

Showing the first 1,200 of 3768 lines. Download the file for the rest.