{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.11.11","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"gpu","dataSources":[{"sourceId":3362,"databundleVersionId":31148,"sourceType":"competition"}],"dockerImageVersionId":31012,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# **Deep Learning Project: Cat vs Dog Image Classification**\n\nThis notebook contains an end-to-end deep learning project for binary classification\nof cats and dogs using convolutional neural networks (CNNs).","metadata":{}},{"cell_type":"markdown","source":"# Read and Prepare our Images Dataset\n> Import The Neede libraries for Prepare our Data","metadata":{}},{"cell_type":"code","source":"!pip install split-folders","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-15T09:58:03.852072Z","iopub.execute_input":"2025-05-15T09:58:03.852273Z","iopub.status.idle":"2025-05-15T09:58:08.721213Z","shell.execute_reply.started":"2025-05-15T09:58:03.852256Z","shell.execute_reply":"2025-05-15T09:58:08.720164Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Import essential libraries\nimport numpy as np\nimport pandas as pd\nimport seaborn as sns\nimport matplotlib.pyplot as plt\nimport matplotlib.image as mpimg\nimport os\nimport random\nimport zipfile\nfrom sklearn.model_selection import train_test_split\nimport splitfolders\nimport warnings\n\n# Basic warnings filter\nwarnings.filterwarnings('ignore')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-15T09:58:12.100797Z","iopub.execute_input":"2025-05-15T09:58:12.101043Z","iopub.status.idle":"2025-05-15T09:58:13.297206Z","shell.execute_reply.started":"2025-05-15T09:58:12.101022Z","shell.execute_reply":"2025-05-15T09:58:13.296474Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Unzip dataset files (Kaggle stores them as zip files)\nwith zipfile.ZipFile('/kaggle/input/dogs-vs-cats/train.zip', 'r') as zip_ref:\n    zip_ref.extractall('/kaggle/working/temp_train')\nwith zipfile.ZipFile('/kaggle/input/dogs-vs-cats/test1.zip', 'r') as zip_ref:\n    zip_ref.extractall('/kaggle/working/temp_test')\n\n# Verify extraction\nprint(\"Train files:\", len(os.listdir('/kaggle/working/temp_train/train')))\nprint(\"Test files:\", len(os.listdir('/kaggle/working/temp_test/test1')))\n\n# Create organized directory structure\nos.makedirs('/kaggle/working/data/train/cats', exist_ok=True)\nos.makedirs('/kaggle/working/data/train/dogs', exist_ok=True)\nos.makedirs('/kaggle/working/data/val/cats', exist_ok=True)\nos.makedirs('/kaggle/working/data/val/dogs', exist_ok=True)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-15T09:58:14.751770Z","iopub.execute_input":"2025-05-15T09:58:14.752488Z","iopub.status.idle":"2025-05-15T09:58:28.682642Z","shell.execute_reply.started":"2025-05-15T09:58:14.752460Z","shell.execute_reply":"2025-05-15T09:58:28.681743Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## Show Some random Samples of data","metadata":{}},{"cell_type":"code","source":"# Display sample images function\ndef display_samples(folder, num_samples=5):\n    plt.figure(figsize=(15, 3))\n    plt.suptitle(f\"Sample {folder.split('/')[-1]} Images\", fontsize=16)\n    \n    # Get random samples\n    samples = random.sample(os.listdir(folder), num_samples)\n    \n    for i, img_name in enumerate(samples):\n        img_path = os.path.join(folder, img_name)\n        img = mpimg.imread(img_path)\n        \n        plt.subplot(1, num_samples, i+1)\n        plt.imshow(img)\n        plt.axis('off')\n    plt.tight_layout()\n    plt.show()\n\n# Display cat and dog samples\ntrain_dir = '/kaggle/working/temp_train/train'\ndisplay_samples(train_dir)  # Will show mixed samples","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-13T23:17:57.535368Z","iopub.execute_input":"2025-05-13T23:17:57.535580Z","iopub.status.idle":"2025-05-13T23:17:57.893146Z","shell.execute_reply.started":"2025-05-13T23:17:57.535564Z","shell.execute_reply":"2025-05-13T23:17:57.892346Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## Splting The data & Create directory structure for organized dataset storage","metadata":{}},{"cell_type":"code","source":"# Organize files into class folders\nfor filename in os.listdir('/kaggle/working/temp_train/train'):\n    src = os.path.join('/kaggle/working/temp_train/train', filename)\n    \n    if filename.startswith('cat'):\n        dst = os.path.join('/kaggle/working/data/train/cats', filename)\n    elif filename.startswith('dog'):\n        dst = os.path.join('/kaggle/working/data/train/dogs', filename)\n    \n    os.rename(src, dst)\n\n# Split into train/validation sets\nsplitfolders.ratio(\n    '/kaggle/working/data/train',  # Source folder\n    output='/kaggle/working/data/split',  # Output folder\n    seed=42,\n    ratio=(0.9, 0.1),  # Train/val ratio\n    group_prefix=None\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-15T09:58:30.165083Z","iopub.execute_input":"2025-05-15T09:58:30.165605Z","iopub.status.idle":"2025-05-15T09:58:34.387867Z","shell.execute_reply.started":"2025-05-15T09:58:30.165578Z","shell.execute_reply":"2025-05-15T09:58:34.387181Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Remove temporary files (optional)\n!rm -r /kaggle/working/temp_train\n!rm -r /kaggle/working/temp_test","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-15T09:58:36.757561Z","iopub.execute_input":"2025-05-15T09:58:36.758133Z","iopub.status.idle":"2025-05-15T09:58:37.285149Z","shell.execute_reply.started":"2025-05-15T09:58:36.758109Z","shell.execute_reply":"2025-05-15T09:58:37.284325Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## Show Some Samples from The new directory","metadata":{}},{"cell_type":"code","source":"# Display samples from the organized dataset\ndef display_organized_samples(folder, title, num_samples=5):\n    plt.figure(figsize=(15, 3))\n    plt.suptitle(title, fontsize=16)\n    \n    # Get random samples\n    samples = random.sample(os.listdir(folder), num_samples)\n    \n    for i, img_name in enumerate(samples):\n        img_path = os.path.join(folder, img_name)\n        img = mpimg.imread(img_path)\n        \n        plt.subplot(1, num_samples, i+1)\n        plt.imshow(img)\n        plt.axis('off')\n    plt.tight_layout()\n    plt.show()\n\n# Display samples from each category\nprint(\"\\n\" + \"=\"*50)\nprint(\"Training Samples After Organization\")\nprint(\"=\"*50)\n\n# Cat samples\ndisplay_organized_samples(\n    '/kaggle/working/data/split/train/cats',\n    \"Sample Training Cat Images\"\n)\n\n# Dog samples\ndisplay_organized_samples(\n    '/kaggle/working/data/split/train/dogs', \n    \"Sample Training Dog Images\"\n)\n\n# Validation samples\nprint(\"\\n\" + \"=\"*50)\nprint(\"Validation Samples\")\nprint(\"=\"*50)\n\n# Validation cats\ndisplay_organized_samples(\n    '/kaggle/working/data/split/val/cats',\n    \"Sample Validation Cat Images\"\n)\n\n# Validation dogs\ndisplay_organized_samples(\n    '/kaggle/working/data/split/val/dogs',\n    \"Sample Validation Dog Images\"\n)\n\n# Show counts\nprint(\"\\nFinal Counts:\")\nprint(f\"Training Cats: {len(os.listdir('/kaggle/working/data/split/train/cats'))}\")\nprint(f\"Training Dogs: {len(os.listdir('/kaggle/working/data/split/train/dogs'))}\")\nprint(f\"Validation Cats: {len(os.listdir('/kaggle/working/data/split/val/cats'))}\")\nprint(f\"Validation Dogs: {len(os.listdir('/kaggle/working/data/split/val/dogs'))}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-15T09:58:47.134822Z","iopub.execute_input":"2025-05-15T09:58:47.135473Z","iopub.status.idle":"2025-05-15T09:58:48.649243Z","shell.execute_reply.started":"2025-05-15T09:58:47.135445Z","shell.execute_reply":"2025-05-15T09:58:48.648682Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"Now After the directory organization and file movement is complete...\n\n------","metadata":{}},{"cell_type":"markdown","source":"# Image Data Generator With Data Augmentation","metadata":{}},{"cell_type":"code","source":"import tensorflow as tf\nfrom tensorflow.keras.preprocessing.image import ImageDataGenerator\n\n# Identify new paths\ntrain_dir = '/kaggle/working/data/split/train'  \nval_dir = '/kaggle/working/data/split/val'      \n\n# Training data generator with augmentation\ntrain_datagen = ImageDataGenerator(\n    rescale=1./255,\n    rotation_range=20,\n    width_shift_range=0.1,\n    height_shift_range=0.1,\n    shear_range=0.1,\n    zoom_range=0.1,\n    horizontal_flip=True,\n    fill_mode='reflect'\n)\n\n# Validation data generator (only normalization)\nval_datagen = ImageDataGenerator(rescale=1./255)\n\n# Generate training batches from directory\ntrain_generator = train_datagen.flow_from_directory(\n    train_dir,\n    target_size=(150, 150),\n    batch_size=32,\n    class_mode='binary',\n    classes=['cats', 'dogs'] \n)\n\n# Generate validation batches from directory\nval_generator = val_datagen.flow_from_directory(\n    val_dir,\n    target_size=(150, 150),\n    batch_size=32,\n    class_mode='binary',\n    classes=['cats', 'dogs'],\n    shuffle=False\n)\n\n# Print a summary of the data\nprint(\"\\nTraining Class Indices:\", train_generator.class_indices)\nprint(\"Validation Class Indices:\", val_generator.class_indices)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-15T09:58:56.816154Z","iopub.execute_input":"2025-05-15T09:58:56.816698Z","iopub.status.idle":"2025-05-15T09:59:11.725559Z","shell.execute_reply.started":"2025-05-15T09:58:56.816673Z","shell.execute_reply":"2025-05-15T09:59:11.724851Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"val_generator.class_indices","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-15T09:59:11.726781Z","iopub.execute_input":"2025-05-15T09:59:11.727278Z","iopub.status.idle":"2025-05-15T09:59:11.732463Z","shell.execute_reply.started":"2025-05-15T09:59:11.727251Z","shell.execute_reply":"2025-05-15T09:59:11.731533Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# CNN Model","metadata":{}},{"cell_type":"code","source":"# Import Our Model Libraries\nfrom tensorflow.keras.models import Sequential\nfrom tensorflow.keras.layers import Conv2D, MaxPooling2D, Flatten, Dense, Dropout, BatchNormalization\nfrom tensorflow.keras.callbacks import EarlyStopping, ModelCheckpoint, ReduceLROnPlateau\nfrom tensorflow.keras.regularizers import L2\nimport os\n\n# Enhanced Callbacks Configuration\ncallbacks = [\n    EarlyStopping(patience=10, restore_best_weights=True),\n    ModelCheckpoint('/kaggle/working/best_model.keras', save_best_only=True), \n    ReduceLROnPlateau(factor=0.5, patience=5)\n]\n\n# Create model \nmodel = Sequential([\n    # Block 1\n    Conv2D(32, (3,3), activation='relu', padding='same', input_shape=(150,150,3)),\n    BatchNormalization(),\n    Conv2D(32, (3,3), activation='relu', padding='same'),\n    BatchNormalization(),\n    MaxPooling2D(2,2),\n    Dropout(0.25),\n\n    # Block 2\n    Conv2D(64, (3,3), activation='relu', padding='same'),\n    BatchNormalization(),\n    Conv2D(64, (3,3), activation='relu', padding='same'),\n    BatchNormalization(),\n    MaxPooling2D(2,2),\n    Dropout(0.25),\n\n    # Block 3\n    Conv2D(128, (3,3), activation='relu', padding='same'),\n    BatchNormalization(),\n    Conv2D(128, (3,3), activation='relu', padding='same'),\n    BatchNormalization(),\n    MaxPooling2D(2,2),\n    Dropout(0.25),\n\n    # Classifier\n    Flatten(),\n    Dense(256, activation='relu', kernel_regularizer=L2(0.01)),\n    BatchNormalization(),\n    Dropout(0.5),\n    Dense(1, activation='sigmoid')\n])\n\n# Load pre-trained weights if available \nos.makedirs('/kaggle/working/output', exist_ok=True)\nif os.path.exists(\"/kaggle/working/output/weights.best.hdf5\"):\n    model.load_weights(\"/kaggle/working/output/weights.best.hdf5\")\n    print(\"Loaded pre-trained weights successfully!\")\n\noptimizer = tf.keras.optimizers.Adam(learning_rate=0.0001)\n\n# Compile model \nmodel.compile(optimizer=optimizer,\n              loss='binary_crossentropy',\n              metrics=['accuracy',\n                      tf.keras.metrics.Precision(),\n                      tf.keras.metrics.Recall()])\nmodel.summary()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-13T23:18:36.541660Z","iopub.execute_input":"2025-05-13T23:18:36.542216Z","iopub.status.idle":"2025-05-13T23:18:36.686084Z","shell.execute_reply.started":"2025-05-13T23:18:36.542196Z","shell.execute_reply":"2025-05-13T23:18:36.685396Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Training Configuration\nhistory = model.fit(\n    train_generator,\n    epochs=50,\n    validation_data=val_generator,\n    callbacks=callbacks,\n    verbose=1\n)\n\n# Save Final Model\nmodel.save('/kaggle/working/output/dogs_vs_cats_model.h5')\nprint(\"Training completed and model saved in \")\n!ls -lh /kaggle/working/output/","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-13T23:18:40.888052Z","iopub.execute_input":"2025-05-13T23:18:40.888571Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Evaluation\ntrain_acc = model.evaluate(train_generator)[1]\nvalid_acc = model.evaluate(val_generator)[1]\nprint(\"Our New Model Accuracy on Training Data: \", train_acc)\nprint(\"Our New Model Accuracy on Validation Data: \", valid_acc)","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## Loss & Accuracy Plotting","metadata":{}},{"cell_type":"code","source":"import pandas as pd\nimport matplotlib.pyplot as plt\n\n# Convert training history to DataFrame for easier manipulation\nhistory_df = pd.DataFrame(history.history)\n\n# Create figure with 2 subplots (side by side)\nplt.figure(figsize=(12, 5))\n\n# 1. Loss Subplot (Left)\nplt.subplot(1, 2, 1)\nplt.plot(history_df['loss'], 'b-', label='Training Loss')\nplt.plot(history_df['val_loss'], 'r--', label='Validation Loss')\nplt.title('Model Loss Over Epochs')\nplt.xlabel('Training Epoch')\nplt.ylabel('Loss Value')\nplt.grid(True)\nplt.legend()\n\n# 2. Accuracy Subplot (Right)\nplt.subplot(1, 2, 2)\nplt.plot(history_df['accuracy'], 'g-', label='Training Accuracy')\nplt.plot(history_df['val_accuracy'], 'm--', label='Validation Accuracy')\nplt.title('Model Accuracy Over Epochs')\nplt.xlabel('Training Epoch')\nplt.ylabel('Accuracy Score')\nplt.grid(True)\nplt.ylim(0, 1)\nplt.legend()\n\n# Adjust layout to prevent overlapping\nplt.tight_layout()\nplt.show()","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"* Sounds Good!\n* We can go farther use More Epochs\n* As we use ModelCheckpoint callback, the model will start from the final best weights stoed before","metadata":{}},{"cell_type":"code","source":"# Training Configuration With More Epochs\nhistory = model.fit(\n    train_generator,\n    epochs=100,\n    validation_data=val_generator,\n    callbacks=callbacks,\n    verbose=1\n)\n\n# Save Final Model \nmodel.save('/kaggle/working/output/dogs_vs_cats_model.h5')\nprint(\"Training completed and model saved in \")\n!ls -lh /kaggle/working/output/","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Evaluation\ntrain_acc = model.evaluate(train_generator)[1]\nvalid_acc = model.evaluate(val_generator)[1]\nprint(\"Our New Model Accuracy on Training Data: \", train_acc)\nprint(\"Our New Model Accuracy on Validation Data: \", valid_acc)","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"* Training 98%\n* Validation 96%\nThats Good","metadata":{}},{"cell_type":"markdown","source":"## Classification Matrics For Evulate our CNN Model","metadata":{}},{"cell_type":"code","source":"from sklearn.metrics import confusion_matrix, classification_report\n\n# 1. Get model predictions\nval_preds = model.predict(val_generator)\nval_preds = (val_preds > 0.5).astype(int)  # Convert probabilities to binary predictions (0 or 1)\n\n# 2. Get true labels\nval_true = val_generator.classes\n\n# 3. Generate Confusion Matrix\ncm = confusion_matrix(val_true, val_preds)\nplt.figure(figsize=(8, 6))\nsns.heatmap(cm, annot=True, fmt='d', cmap='Blues',\n            xticklabels=['Cats', 'Dogs'],\n            yticklabels=['Cats', 'Dogs'])\nplt.title('Confusion Matrix')\nplt.xlabel('Predicted Label')\nplt.ylabel('True Label')\nplt.show()\n\n# 4. Generate Classification Report\nprint(\"\\nDetailed Classification Report:\")\nprint(classification_report(val_true, val_preds,\n                          target_names=['Cats', 'Dogs']))\n\n# 5. Calculate Overall Accuracy\nval_acc = np.sum(val_preds == val_true) / len(val_true)\nprint(f\"\\nFinal Validation Accuracy: {val_acc:.4f}\")","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Load Our Model\nfrom tensorflow.keras.models import load_model\nmodel = load_model('/kaggle/working/output/dogs_vs_cats_model.h5')","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## CNN Model Testing On data From Internet","metadata":{}},{"cell_type":"code","source":"import requests\nfrom PIL import Image\n\ndef predict_from_url(image_url):\n    try:\n        # Download The Image From URL\n        response = requests.get(image_url, stream=True)\n        img = Image.open(response.raw)\n\n        # Processing\n        img = img.convert('RGB')\n        img = img.resize((150, 150))\n        img_array = np.array(img) / 255.0\n        img_array = np.expand_dims(img_array, axis=0)\n        \n        # Predicition\n        pred = model.predict(img_array)[0][0]\n        confidence = pred if pred > 0.5 else 1 - pred\n        return {\n            'prediction': 'Dog' if pred > 0.5 else 'Cat',\n            'confidence': float(confidence * 100)\n        }\n    \n    except Exception as e:\n        return {'error': str(e)}\n\n# The Link URL\nurl = \"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQZ0L7ciOGctocVYVpcLUIxcjI5Or3tj-e_jQ&s\"  \nresult = predict_from_url(url)\n\n# Show Result\nif 'error' in result:\n    print(f\"Error: {result['error']}\")\nelse:\n    print(f\"Predicition: {result['prediction']}\")\n    print(f\"confidence: {result['confidence']:.2f}%\")","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"* Nice!\n* Let's try Transfer Learning","metadata":{}},{"cell_type":"markdown","source":"# Transfer Learning\n* A technique where knowledge learned from a task is re-used in order to boost performance on a related task.\n* The pre-trained models are usually trained on massive datasets that are a standard benchmark. The weights obtained from the models can be reused in other tasks.\n* Transfer learning is particularly very useful when you have a small training dataset.","metadata":{}},{"cell_type":"markdown","source":"There are three ways to use a pre-trained model:\n\n* Prediction.\n* Feature Extraction.\n* Fine-tuning.\n> Here, we will use it for Feature Extraction","metadata":{}},{"cell_type":"markdown","source":"We will use pre-trained VGG16 model","metadata":{}},{"cell_type":"code","source":"from tensorflow.keras.applications import VGG16\nfrom tensorflow.keras.optimizers import Adam, RMSprop\nfrom tensorflow.keras.layers import Dense, Dropout, Flatten, BatchNormalization\nfrom tensorflow.keras.models import Sequential\nfrom tensorflow.keras.regularizers import l2\nimport tensorflow as tf\n\n# 1. Load pre-trained VGG16 model\nbase_model = VGG16(\n    weights='imagenet',\n    include_top=False,\n    input_shape=(150, 150, 3)\n)\n\n# 2. Partial freezing - unfreeze last 10 layers for fine-tuning\nfor layer in base_model.layers[:-10]:\n    layer.trainable = False\nfor layer in base_model.layers[-10:]:\n    layer.trainable = True\nprint(\"Last 10 layers of VGG16 unfrozen for fine-tuning\")\n\n# 3. Build enhanced model on top\nVGG16_model = Sequential([\n    base_model,\n    Flatten(),\n    Dense(512, activation='relu', kernel_regularizer=l2(0.001)),\n    BatchNormalization(),\n    Dropout(0.5),\n    Dense(256, activation='relu', kernel_regularizer=l2(0.001)),\n    BatchNormalization(),\n    Dropout(0.3),\n    Dense(1, activation='sigmoid')\n])\nprint(\"Enhanced classification head with more layers and regularization\")\n\n# 4. Compile with different optimizer options\n# Option 1: Adam with lower learning rate (good default)\n# VGG16_model.compile(\n#     optimizer=Adam(learning_rate=1e-5),\n#     loss='binary_crossentropy',\n#     metrics=['accuracy', tf.keras.metrics.Precision(), tf.keras.metrics.Recall()]\n# )\n\n# Option 2: RMSprop (often works well for fine-tuning)\nVGG16_model.compile(\n    optimizer=RMSprop(learning_rate=1e-5),\n    loss='binary_crossentropy',\n    metrics=['accuracy', tf.keras.metrics.Precision(), tf.keras.metrics.Recall()]\n)\n\n# Display model architecture\nVGG16_model.summary()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-15T10:03:23.560491Z","iopub.execute_input":"2025-05-15T10:03:23.560851Z","iopub.status.idle":"2025-05-15T10:03:29.032338Z","shell.execute_reply.started":"2025-05-15T10:03:23.560829Z","shell.execute_reply":"2025-05-15T10:03:29.031672Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Declare Needed Callbacks Before Fitting\ncallbacks = [\n    ModelCheckpoint(\n        '/kaggle/working/output/vgg16_best_weights.weights.h5',\n        monitor='val_accuracy',\n        save_best_only=True,\n        save_weights_only=True\n    ),\n    EarlyStopping(\n        monitor='val_loss',\n        patience=5,\n        restore_best_weights=True\n    )\n]\n\n# Training\nVGG16_history = VGG16_model.fit(\n    train_generator,\n    steps_per_epoch=100,\n    epochs=100,\n    validation_data=val_generator,\n    validation_steps=50\n)\n\n# Save our VGG16 Model\nVGG16_model.save('/kaggle/working/output/vgg16_dogs_vs_cats_model.h5')\nVGG16_model.save_weights('/kaggle/working/output/vgg16_dogs_vs_cats_weights.weights.h5')\nprint(\"Training completed and model saved in \")\n!ls -lh /kaggle/working/output/","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-15T10:05:45.360995Z","iopub.execute_input":"2025-05-15T10:05:45.361846Z","iopub.status.idle":"2025-05-15T10:33:59.032619Z","shell.execute_reply.started":"2025-05-15T10:05:45.361796Z","shell.execute_reply":"2025-05-15T10:33:59.031576Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Evaluation\ntrain_acc = VGG16_model.evaluate(train_generator)[1]\nvalid_acc = VGG16_model.evaluate(val_generator)[1]\nprint(\"VGG16 Model Accuracy on Training Data: \", train_acc)\nprint(\"VGG16 Model Accuracy on Validation Data: \", valid_acc)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-15T10:35:37.738628Z","iopub.execute_input":"2025-05-15T10:35:37.739611Z","iopub.status.idle":"2025-05-15T10:37:43.892570Z","shell.execute_reply.started":"2025-05-15T10:35:37.739580Z","shell.execute_reply":"2025-05-15T10:37:43.891647Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"* Sounds Good!\n* We can go farther use More Epochs","metadata":{}},{"cell_type":"code","source":"# Training\nVGG16_history = VGG16_model.fit(\n    train_generator,\n    steps_per_epoch=200,\n    epochs=100,\n    validation_data=val_generator,\n    validation_steps=50\n)\n\n# Save our VGG16 Model\nVGG16_model.save('/kaggle/working/output/vgg16_dogs_vs_cats_model.h5')\nVGG16_model.save_weights('/kaggle/working/output/vgg16_dogs_vs_cats_weights.weights.h5')\nprint(\"Training completed and model saved in \")\n!ls -lh /kaggle/working/output/","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-15T10:44:58.904394Z","iopub.execute_input":"2025-05-15T10:44:58.904707Z","iopub.status.idle":"2025-05-15T11:39:39.947257Z","shell.execute_reply.started":"2025-05-15T10:44:58.904683Z","shell.execute_reply":"2025-05-15T11:39:39.946437Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"we can go with more epochs But i will stop there","metadata":{}},{"cell_type":"code","source":"# Evaluation\ntrain_acc = VGG16_model.evaluate(train_generator)[1]\nvalid_acc = VGG16_model.evaluate(val_generator)[1]\nprint(\"VGG16 Model Accuracy on Training Data: \", train_acc)\nprint(\"VGG16 Model Accuracy on Validation Data: \", valid_acc)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-15T11:40:09.739926Z","iopub.execute_input":"2025-05-15T11:40:09.740209Z","iopub.status.idle":"2025-05-15T11:42:18.355307Z","shell.execute_reply.started":"2025-05-15T11:40:09.740186Z","shell.execute_reply":"2025-05-15T11:42:18.354717Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"* Very Good The Cnn Model have a good very acc with 96% on Validition\n* But The Transfer Learning achieve a Better Performance With 98%","metadata":{}},{"cell_type":"markdown","source":"## Loss & Accuracy Plotting for VGG16 Model","metadata":{}},{"cell_type":"code","source":"# Convert training history to DataFrame for easier manipulation\nVGG16_history_df = pd.DataFrame(VGG16_history.history)\n\n# Create figure with 2 subplots (side by side)\nplt.figure(figsize=(12, 5))\n\n# 1. Loss Subplot (Left)\nplt.subplot(1, 2, 1)\nplt.plot(VGG16_history_df['loss'], 'b-', label='Training Loss')\nplt.plot(VGG16_history_df['val_loss'], 'r--', label='Validation Loss')\nplt.title('Model Loss Over Epochs')\nplt.xlabel('Training Epoch')\nplt.ylabel('Loss Value')\nplt.legend()\n\n# 2. Accuracy Subplot (Right)\nplt.subplot(1, 2, 2)\nplt.plot(VGG16_history_df['accuracy'], 'g-', label='Training Accuracy')\nplt.plot(VGG16_history_df['val_accuracy'], 'm--', label='Validation Accuracy')\nplt.title('Model Accuracy Over Epochs')\nplt.xlabel('Training Epoch')\nplt.ylabel('Accuracy Score')\nplt.ylim(0, 1)\nplt.legend()\n\n# Adjust layout to prevent overlapping\nplt.tight_layout()\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-15T11:43:54.733591Z","iopub.execute_input":"2025-05-15T11:43:54.734221Z","iopub.status.idle":"2025-05-15T11:43:55.139682Z","shell.execute_reply.started":"2025-05-15T11:43:54.734201Z","shell.execute_reply":"2025-05-15T11:43:55.138898Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## Classification Matrics For Evulate VGG16 Model","metadata":{}},{"cell_type":"code","source":"# 1. Get model predictions\nval_preds = VGG16_model.predict(val_generator)\nval_preds = (val_preds > 0.5).astype(int)  # Convert probabilities to binary predictions (0 or 1)\n\n# 2. Get true labels\nval_true = val_generator.classes\n\n# 3. Generate Confusion Matrix\ncm = confusion_matrix(val_true, val_preds)\nplt.figure(figsize=(8, 6))\nsns.heatmap(cm, annot=True, fmt='d', cmap='Blues',\n            xticklabels=['Cats', 'Dogs'],\n            yticklabels=['Cats', 'Dogs'])\nplt.title('Confusion Matrix')\nplt.xlabel('Predicted Label')\nplt.ylabel('True Label')\nplt.show()\n\n# 4. Generate Classification Report\nprint(\"\\nDetailed Classification Report:\")\nprint(classification_report(val_true, val_preds,\n                          target_names=['Cats', 'Dogs']))\n\n# 5. Calculate Overall Accuracy\nval_acc = np.sum(val_preds == val_true) / len(val_true)\nprint(f\"\\nFinal Validation Accuracy for VGG16 model: {val_acc:.4f}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-15T11:44:51.614236Z","iopub.execute_input":"2025-05-15T11:44:51.614552Z","iopub.status.idle":"2025-05-15T11:44:55.338768Z","shell.execute_reply.started":"2025-05-15T11:44:51.614531Z","shell.execute_reply":"2025-05-15T11:44:55.337981Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"* This is The Best Model We Got (VGG16)","metadata":{}},{"cell_type":"markdown","source":"# Evaulate Our Best Model on Testing","metadata":{}},{"cell_type":"code","source":"# Extract the test zip file\ntest_zip_path = '/kaggle/input/dogs-vs-cats/test1.zip'\nextract_path = '/kaggle/working/test_data'\n\n# Create extraction directory if it doesn't exist\nos.makedirs(extract_path, exist_ok=True)\n\n# Unzip the test files\nwith zipfile.ZipFile(test_zip_path, 'r') as zip_ref:\n    zip_ref.extractall(extract_path)\n    \nprint(f\"Test files extracted to: {extract_path}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-15T11:44:58.614144Z","iopub.execute_input":"2025-05-15T11:44:58.614422Z","iopub.status.idle":"2025-05-15T11:45:01.013199Z","shell.execute_reply.started":"2025-05-15T11:44:58.614402Z","shell.execute_reply":"2025-05-15T11:45:01.012537Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Verify the extracted files\ntest_files = os.listdir(os.path.join(extract_path, 'test1'))\nprint(f\"\\nNumber of test images: {len(test_files)}\")\nprint(\"First 5 files:\", test_files[:5])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-15T11:45:02.018952Z","iopub.execute_input":"2025-05-15T11:45:02.019193Z","iopub.status.idle":"2025-05-15T11:45:02.030544Z","shell.execute_reply.started":"2025-05-15T11:45:02.019177Z","shell.execute_reply":"2025-05-15T11:45:02.029772Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Prepare ImageDataGenerator for test images\ntest_datagen = ImageDataGenerator(rescale=1./255)  # Normalize pixel values\n\ntest_generator = test_datagen.flow_from_directory(\n    extract_path,               \n    target_size=(150, 150),     \n    batch_size=32,             \n    class_mode=None,            \n    shuffle=False               \n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-15T11:45:02.565362Z","iopub.execute_input":"2025-05-15T11:45:02.565641Z","iopub.status.idle":"2025-05-15T11:45:02.664148Z","shell.execute_reply.started":"2025-05-15T11:45:02.565622Z","shell.execute_reply":"2025-05-15T11:45:02.663602Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Make predictions on test data\nprint(\"\\nRunning predictions on test data...\")\npredictions = VGG16_model.predict(test_generator)\n\n# Convert probability predictions to labels\npredicted_labels = ['dog' if pred > 0.5 else 'cat' for pred in predictions]\n\n# Display random prediction samples\nsample_indices = random.sample(range(len(predicted_labels)), 5)\n\nprint(\"\\nRandom prediction samples:\")\nfor idx in sample_indices:\n    confidence = max(predictions[idx][0], 1-predictions[idx][0]) * 100\n    print(f\"Image: {test_generator.filenames[idx]} - Prediction: {predicted_labels[idx]} (Confidence: {confidence:.1f}%)\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-15T11:45:05.236885Z","iopub.execute_input":"2025-05-15T11:45:05.237167Z","iopub.status.idle":"2025-05-15T11:45:27.020234Z","shell.execute_reply.started":"2025-05-15T11:45:05.237148Z","shell.execute_reply":"2025-05-15T11:45:27.019502Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"Create DataFrame Similar to Submission CSV File","metadata":{}},{"cell_type":"code","source":"# Save predictions for competition submission\nsubmission = pd.DataFrame({\n    'id': [os.path.splitext(f)[0] for f in test_generator.filenames],  # Remove file extension\n    'label': [1 if pred > 0.5 else 0 for pred in predictions]  # 1=dog, 0=cat\n})\n\nsubmission_path = '/kaggle/working/output/test_predictions.csv'\nsubmission.to_csv(submission_path, index=False)\nprint(f\"\\nPredictions saved to: {submission_path}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-15T11:45:27.021509Z","iopub.execute_input":"2025-05-15T11:45:27.021728Z","iopub.status.idle":"2025-05-15T11:45:27.080065Z","shell.execute_reply.started":"2025-05-15T11:45:27.021711Z","shell.execute_reply":"2025-05-15T11:45:27.079333Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"Hossam Taha\n* LinkedIn : https://linkedin.com/in/hossam-taha-41b724288","metadata":{}}]}