{ "nbformat": 4, "nbformat_minor": 0, "metadata": { "colab": { "provenance": [], "gpuType": "T4" }, "kernelspec": { "name": "python3", "display_name": "Python 3" }, "language_info": { "name": "python" }, "accelerator": "GPU" }, "cells": [ { "cell_type": "code", "execution_count": null, "metadata": { "id": "AV-1n4EQ4zoM" }, "outputs": [], "source": [ "import tensorflow as tf\n", "from tensorflow.keras.preprocessing.image import ImageDataGenerator\n", "import pandas as pd\n", "import os" ] }, { "cell_type": "code", "source": [ "#Create an instance of ImageDataGenerator\n", "train_datagen = ImageDataGenerator(rescale=1./255)\n", "val_datagen = ImageDataGenerator(rescale=1./255)\n", "class_labels = {'cocci': 0, 'bacilli': 1, 'spirilla': 2}\n", "\n", "# Load training data from the 'train' folder\n", "# Each subfolder (bacilli, cocci, spirilla) represents a class\n", "train_data = train_datagen.flow_from_directory(\n", " '/content/drive/MyDrive/Bacterial Classification/train', # Path to the train folder\n", " target_size=(224, 224), # Resize all images to 224x224\n", " batch_size=32, # Number of images per batch\n", " class_mode='categorical', # Multi-class classification\n", " classes=class_labels # Explicit class mapping\n", "\n", ")\n", "\n", "# Load validation data from the 'validation' folder\n", "# Each subfolder (bacilli, cocci, spirilla) represents a class\n", "val_data = val_datagen.flow_from_directory(\n", " '/content/drive/MyDrive/Bacterial Classification/validation',# Path to the validation folder\n", " target_size=(224, 224),\n", " batch_size=32,\n", " class_mode='categorical',\n", " classes=class_labels\n", "\n", ")\n", "\n", "# Check class mappings\n", "print(\"Training Class Indices:\", train_data.class_indices)\n", "print(\"Validation Class Indices:\", val_data.class_indices)\n" ], "metadata": { "id": "JoFVIVmJTVPX" }, "execution_count": null, "outputs": [] }, { "cell_type": "code", "source": [ "from tensorflow.keras.applications import MobileNetV2\n", "from tensorflow.keras.layers import GlobalAveragePooling2D\n", "from tensorflow.keras.optimizers import Adam\n", "from tensorflow.keras.callbacks import EarlyStopping\n", "\n", "base_model = MobileNetV2(weights='imagenet', include_top=False, input_shape=(224, 224, 3))\n", "base_model.trainable = False # Freeze the base model\n", "\n", "model = tf.keras.Sequential([\n", " base_model,\n", " GlobalAveragePooling2D(),\n", " tf.keras.layers.Dense(128, activation='relu'),\n", " tf.keras.layers.Dropout(0.5),\n", " tf.keras.layers.Dense(3, activation='softmax')\n", "])\n", "\n", "model.compile(\n", " optimizer=Adam(learning_rate=0.0001), # Lower learning rate\n", " loss='categorical_crossentropy',\n", " metrics=['accuracy']\n", ")\n", "early_stopping = EarlyStopping(\n", " monitor='val_loss',\n", " patience=3,\n", " restore_best_weights=True\n", ")\n", "# Train the model\n", "history = model.fit(\n", " train_data,\n", " validation_data=val_data,\n", " epochs=50, # Allow more epochs but stop early if needed\n", " callbacks=[early_stopping]\n", ")\n", "\n", "\n", "# Evaluate the model on the validation dataset\n", "val_loss, val_accuracy = model.evaluate(val_data)\n", "print(f\"Validation Loss: {val_loss}\")\n", "print(f\"Validation Accuracy: {val_accuracy}\")" ], "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "2PYZtsrhVGjZ", "outputId": "9d6cef82-2302-48f3-dab6-c7406711c331" }, "execution_count": null, "outputs": [ { "output_type": "stream", "name": "stdout", "text": [ "Epoch 1/50\n" ] }, { "output_type": "stream", "name": "stderr", "text": [ "/usr/local/lib/python3.10/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", " self._warn_if_super_not_called()\n" ] }, { "output_type": "stream", "name": "stdout", "text": [ "\u001b[1m12/12\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m136s\u001b[0m 7s/step - accuracy: 0.3350 - loss: 1.6972 - val_accuracy: 0.3417 - val_loss: 1.3020\n", "Epoch 2/50\n", "\u001b[1m12/12\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m4s\u001b[0m 182ms/step - accuracy: 0.3816 - loss: 1.3227 - val_accuracy: 0.4750 - val_loss: 1.1209\n", "Epoch 3/50\n", "\u001b[1m12/12\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m6s\u001b[0m 223ms/step - accuracy: 0.5357 - loss: 0.9564 - val_accuracy: 0.5583 - val_loss: 1.0034\n", "Epoch 4/50\n", "\u001b[1m12/12\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m4s\u001b[0m 175ms/step - accuracy: 0.5961 - loss: 0.8981 - val_accuracy: 0.5667 - val_loss: 0.9151\n", "Epoch 5/50\n", "\u001b[1m12/12\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m5s\u001b[0m 226ms/step - accuracy: 0.5730 - loss: 0.9111 - val_accuracy: 0.5833 - val_loss: 0.8556\n", "Epoch 6/50\n", "\u001b[1m12/12\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m5s\u001b[0m 184ms/step - accuracy: 0.7188 - loss: 0.6853 - val_accuracy: 0.6333 - val_loss: 0.8078\n", "Epoch 7/50\n", "\u001b[1m12/12\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m4s\u001b[0m 218ms/step - accuracy: 0.7019 - loss: 0.6919 - val_accuracy: 0.6750 - val_loss: 0.7685\n", "Epoch 8/50\n", "\u001b[1m12/12\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m4s\u001b[0m 236ms/step - accuracy: 0.7730 - loss: 0.5996 - val_accuracy: 0.6833 - val_loss: 0.7381\n", "Epoch 9/50\n", "\u001b[1m12/12\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m5s\u001b[0m 203ms/step - accuracy: 0.7472 - loss: 0.5987 - val_accuracy: 0.6500 - val_loss: 0.7141\n", "Epoch 10/50\n", "\u001b[1m12/12\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m5s\u001b[0m 196ms/step - accuracy: 0.7470 - loss: 0.6248 - val_accuracy: 0.6833 - val_loss: 0.6917\n", "Epoch 11/50\n", "\u001b[1m12/12\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m5s\u001b[0m 223ms/step - accuracy: 0.7687 - loss: 0.5358 - val_accuracy: 0.6833 - val_loss: 0.6693\n", "Epoch 12/50\n", "\u001b[1m12/12\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m4s\u001b[0m 176ms/step - accuracy: 0.8054 - loss: 0.4860 - val_accuracy: 0.6917 - val_loss: 0.6535\n", "Epoch 13/50\n", "\u001b[1m12/12\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m4s\u001b[0m 196ms/step - accuracy: 0.8217 - loss: 0.4857 - val_accuracy: 0.6833 - val_loss: 0.6379\n", "Epoch 14/50\n", "\u001b[1m12/12\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m5s\u001b[0m 245ms/step - accuracy: 0.8586 - loss: 0.4347 - val_accuracy: 0.7000 - val_loss: 0.6292\n", "Epoch 15/50\n", "\u001b[1m12/12\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m4s\u001b[0m 204ms/step - accuracy: 0.8516 - loss: 0.3888 - val_accuracy: 0.7083 - val_loss: 0.6151\n", "Epoch 16/50\n", "\u001b[1m12/12\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m4s\u001b[0m 191ms/step - accuracy: 0.8199 - loss: 0.4157 - val_accuracy: 0.7333 - val_loss: 0.6084\n", "Epoch 17/50\n", "\u001b[1m12/12\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m6s\u001b[0m 228ms/step - accuracy: 0.8377 - loss: 0.4106 - val_accuracy: 0.7250 - val_loss: 0.5958\n", "Epoch 18/50\n", "\u001b[1m12/12\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m4s\u001b[0m 221ms/step - accuracy: 0.9195 - loss: 0.3326 - val_accuracy: 0.7250 - val_loss: 0.5859\n", "Epoch 19/50\n", "\u001b[1m12/12\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m5s\u001b[0m 234ms/step - accuracy: 0.8840 - loss: 0.3327 - val_accuracy: 0.7083 - val_loss: 0.5821\n", "Epoch 20/50\n", "\u001b[1m12/12\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m5s\u001b[0m 207ms/step - accuracy: 0.8947 - loss: 0.3532 - val_accuracy: 0.7333 - val_loss: 0.5776\n", "Epoch 21/50\n", "\u001b[1m12/12\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m4s\u001b[0m 201ms/step - accuracy: 0.9053 - loss: 0.2998 - val_accuracy: 0.7417 - val_loss: 0.5665\n", "Epoch 22/50\n", "\u001b[1m12/12\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m4s\u001b[0m 209ms/step - accuracy: 0.9031 - loss: 0.3000 - val_accuracy: 0.7417 - val_loss: 0.5620\n", "Epoch 23/50\n", "\u001b[1m12/12\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m5s\u001b[0m 185ms/step - accuracy: 0.8956 - loss: 0.2904 - val_accuracy: 0.7333 - val_loss: 0.5560\n", "Epoch 24/50\n", "\u001b[1m12/12\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m4s\u001b[0m 186ms/step - accuracy: 0.9194 - loss: 0.2869 - val_accuracy: 0.7417 - val_loss: 0.5498\n", "Epoch 25/50\n", "\u001b[1m12/12\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m4s\u001b[0m 250ms/step - accuracy: 0.9128 - loss: 0.2674 - val_accuracy: 0.7333 - val_loss: 0.5458\n", "Epoch 26/50\n", "\u001b[1m12/12\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m5s\u001b[0m 201ms/step - accuracy: 0.9213 - loss: 0.2319 - val_accuracy: 0.7333 - val_loss: 0.5432\n", "Epoch 27/50\n", "\u001b[1m12/12\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m4s\u001b[0m 189ms/step - accuracy: 0.9412 - loss: 0.2338 - val_accuracy: 0.7500 - val_loss: 0.5397\n", "Epoch 28/50\n", "\u001b[1m12/12\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m6s\u001b[0m 259ms/step - accuracy: 0.9427 - loss: 0.2247 - val_accuracy: 0.7500 - val_loss: 0.5345\n", "Epoch 29/50\n", "\u001b[1m12/12\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m4s\u001b[0m 195ms/step - accuracy: 0.9304 - loss: 0.2206 - val_accuracy: 0.7500 - val_loss: 0.5316\n", "Epoch 30/50\n", "\u001b[1m12/12\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m4s\u001b[0m 201ms/step - accuracy: 0.9419 - loss: 0.2098 - val_accuracy: 0.7500 - val_loss: 0.5289\n", "Epoch 31/50\n", "\u001b[1m12/12\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m5s\u001b[0m 248ms/step - accuracy: 0.9420 - loss: 0.1824 - val_accuracy: 0.7500 - val_loss: 0.5273\n", "Epoch 32/50\n", "\u001b[1m12/12\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m4s\u001b[0m 198ms/step - accuracy: 0.9590 - loss: 0.1871 - val_accuracy: 0.7500 - val_loss: 0.5244\n", "Epoch 33/50\n", "\u001b[1m12/12\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m4s\u001b[0m 223ms/step - accuracy: 0.9613 - loss: 0.1816 - val_accuracy: 0.7417 - val_loss: 0.5233\n", "Epoch 34/50\n", "\u001b[1m12/12\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m6s\u001b[0m 258ms/step - accuracy: 0.9629 - loss: 0.1428 - val_accuracy: 0.7417 - val_loss: 0.5217\n", "Epoch 35/50\n", "\u001b[1m12/12\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m4s\u001b[0m 167ms/step - accuracy: 0.9606 - loss: 0.1835 - val_accuracy: 0.7583 - val_loss: 0.5231\n", "Epoch 36/50\n", "\u001b[1m12/12\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m5s\u001b[0m 234ms/step - accuracy: 0.9366 - loss: 0.1920 - val_accuracy: 0.7500 - val_loss: 0.5246\n", "Epoch 37/50\n", "\u001b[1m12/12\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m6s\u001b[0m 238ms/step - accuracy: 0.9464 - loss: 0.1747 - val_accuracy: 0.7583 - val_loss: 0.5184\n", "Epoch 38/50\n", "\u001b[1m12/12\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m4s\u001b[0m 187ms/step - accuracy: 0.9601 - loss: 0.1621 - val_accuracy: 0.7583 - val_loss: 0.5132\n", "Epoch 39/50\n", "\u001b[1m12/12\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m5s\u001b[0m 184ms/step - accuracy: 0.9691 - loss: 0.1530 - val_accuracy: 0.7583 - val_loss: 0.5097\n", "Epoch 40/50\n", "\u001b[1m12/12\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m5s\u001b[0m 207ms/step - accuracy: 0.9655 - loss: 0.1480 - val_accuracy: 0.7667 - val_loss: 0.5113\n", "Epoch 41/50\n", "\u001b[1m12/12\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m4s\u001b[0m 184ms/step - accuracy: 0.9671 - loss: 0.1483 - val_accuracy: 0.7583 - val_loss: 0.5122\n", "Epoch 42/50\n", "\u001b[1m12/12\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m5s\u001b[0m 207ms/step - accuracy: 0.9775 - loss: 0.1268 - val_accuracy: 0.7583 - val_loss: 0.5124\n", "\u001b[1m4/4\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m1s\u001b[0m 284ms/step - accuracy: 0.7763 - loss: 0.4887\n", "Validation Loss: 0.509696900844574\n", "Validation Accuracy: 0.7583333253860474\n" ] } ] }, { "cell_type": "code", "source": [ "import os\n", "import numpy as np\n", "import pandas as pd\n", "import tensorflow as tf\n", "from tensorflow.keras.utils import load_img, img_to_array\n", "\n", "# Load the file containing test image names\n", "test_images = pd.read_csv('/content/drive/MyDrive/Bacterial Classification/test_filenames.txt', header=None)\n", "test_images.columns = ['Image Name']\n", "\n", "# Path to the test folder containing the images\n", "test_dir = '/content/drive/MyDrive/Bacterial Classification/test'\n", "\n", "# Placeholder for predictions\n", "predictions = []\n", "\n", "# Process each image and predict\n", "for img_name in test_images['Image Name']:\n", " # Construct the full path to the image\n", " img_path = os.path.join(test_dir, img_name)\n", "\n", " # Load and preprocess the image\n", " img = load_img(img_path, target_size=(224, 224)) # Resize image to match the model's input size\n", " img_array = img_to_array(img) / 255.0 # Normalize pixel values\n", " img_array = np.expand_dims(img_array, axis=0) # Add batch dimension\n", "\n", " # Make a prediction using the trained model\n", " prediction = model.predict(img_array, verbose=0) # Suppress verbose output\n", " predictions.append(prediction.argmax()) # Append the predicted class index (0, 1, 2)\n", "\n", "# Add predictions to the DataFrame\n", "test_images['Predicted Class'] = predictions" ], "metadata": { "id": "Wy-i6rizMrt9" }, "execution_count": null, "outputs": [] }, { "cell_type": "code", "source": [ "predictions" ], "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "Pt1zSfXsTIlt", "outputId": "145ef195-25ca-450b-bd05-bae27efe6fc5" }, "execution_count": null, "outputs": [ { "output_type": "execute_result", "data": { "text/plain": [ "[0,\n", " 0,\n", " 0,\n", " 0,\n", " 0,\n", " 0,\n", " 0,\n", " 1,\n", " 0,\n", " 0,\n", " 0,\n", " 0,\n", " 0,\n", " 0,\n", " 0,\n", " 0,\n", " 0,\n", " 0,\n", " 0,\n", " 0,\n", " 0,\n", " 0,\n", " 0,\n", " 0,\n", " 0,\n", " 0,\n", " 0,\n", " 0,\n", " 1,\n", " 0,\n", " 0,\n", " 0,\n", " 0,\n", " 0,\n", " 0,\n", " 0,\n", " 0,\n", " 0,\n", " 0,\n", " 1,\n", " 1,\n", " 1,\n", " 2,\n", " 1,\n", " 1,\n", " 1,\n", " 1,\n", " 1,\n", " 1,\n", " 1,\n", " 1,\n", " 1,\n", " 0,\n", " 1,\n", " 1,\n", " 2,\n", " 0,\n", " 1,\n", " 1,\n", " 1,\n", " 1,\n", " 1,\n", " 1,\n", " 1,\n", " 1,\n", " 1,\n", " 1,\n", " 2,\n", " 1,\n", " 1,\n", " 1,\n", " 1,\n", " 0,\n", " 1,\n", " 1,\n", " 1,\n", " 1,\n", " 1,\n", " 1,\n", " 1,\n", " 2,\n", " 2,\n", " 2,\n", " 2,\n", " 0,\n", " 2,\n", " 2,\n", " 2,\n", " 2,\n", " 2,\n", " 2,\n", " 2,\n", " 2,\n", " 1,\n", " 2,\n", " 2,\n", " 1,\n", " 2,\n", " 2,\n", " 2,\n", " 2,\n", " 2,\n", " 2,\n", " 1,\n", " 1,\n", " 2,\n", " 1,\n", " 2,\n", " 1,\n", " 2,\n", " 2,\n", " 2,\n", " 1,\n", " 1,\n", " 2,\n", " 2,\n", " 2,\n", " 2,\n", " 2,\n", " 2]" ] }, "metadata": {}, "execution_count": 9 } ] }, { "cell_type": "code", "source": [ "model.save('/content/drive/MyDrive/Bacterial Classification/saved_model.keras')" ], "metadata": { "id": "RfyBMOReTZfR" }, "execution_count": null, "outputs": [] } ] }