{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.12.12","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"gpu","dataSources":[{"sourceType":"competition","sourceId":3362,"databundleVersionId":31148}],"dockerImageVersionId":31287,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"# This Python 3 environment comes with many helpful analytics libraries installed\n# It is defined by the kaggle/python Docker image: https://github.com/kaggle/docker-python\n# For example, here's several helpful packages to load\n\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n\n# Input data files are available in the read-only \"../input/\" directory\n# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory\n\nimport os\nfor dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n        print(os.path.join(dirname, filename))\n\n# You can write up to 20GB to the current directory (/kaggle/working/) that gets preserved as output when you create a version using \"Save & Run All\" \n# You can also write temporary files to /kaggle/temp/, but they won't be saved outside of the current session","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2026-03-02T18:48:21.338994Z","iopub.execute_input":"2026-03-02T18:48:21.339258Z","iopub.status.idle":"2026-03-02T18:48:22.40416Z","shell.execute_reply.started":"2026-03-02T18:48:21.339227Z","shell.execute_reply":"2026-03-02T18:48:22.403368Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"\"\"\"\nCats vs Dogs CNN Training with Different Regularization Techniques\n===================================================================\nThis script trains CNNs using:\n1. Baseline (no regularization)\n2. L1 regularization\n3. L2 regularization\n4. Dropout\n5. Data augmentation\n6. Combined (Dropout + Data augmentation)\n\nThen compares their performance.\n\"\"\"\n\nimport numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\nimport seaborn as sns\nfrom sklearn.model_selection import train_test_split\nimport os\nimport zipfile\nfrom pathlib import Path\nimport warnings\nwarnings.filterwarnings('ignore')\n\nimport tensorflow as tf\nfrom tensorflow import keras\nfrom tensorflow.keras import layers, models, regularizers\nfrom tensorflow.keras.preprocessing.image import ImageDataGenerator\nfrom tensorflow.keras.callbacks import EarlyStopping, ReduceLROnPlateau, ModelCheckpoint","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-02T18:48:22.406117Z","iopub.execute_input":"2026-03-02T18:48:22.406862Z","iopub.status.idle":"2026-03-02T18:48:48.987508Z","shell.execute_reply.started":"2026-03-02T18:48:22.406825Z","shell.execute_reply":"2026-03-02T18:48:48.98671Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Set random seeds for reproducibility\nnp.random.seed(42)\ntf.random.set_seed(42)\n\nprint(\"TensorFlow version:\", tf.__version__)\nprint(\"GPU Available:\", tf.config.list_physical_devices('GPU'))\n\n# ============================================================================\n# CONFIGURATION\n# ============================================================================\n\nIMG_SIZE = 150\nBATCH_SIZE = 32\nEPOCHS = 30\nVALIDATION_SPLIT = 0.2\n\n# Dataset paths for Kaggle\nDATASET_PATH = '/kaggle/input/competitions/dogs-vs-cats/train.zip'\nWORKING_DIR = '/kaggle/working'\n\n# ============================================================================\n# DATA PREPARATION\n# ============================================================================\n\ndef prepare_dataset():\n    \"\"\"Extract and organize the Kaggle dataset\"\"\"\n    print(\"Preparing dataset...\")\n    \n    # Create directories\n    train_dir = os.path.join(WORKING_DIR, 'train')\n    os.makedirs(os.path.join(train_dir, 'cats'), exist_ok=True)\n    os.makedirs(os.path.join(train_dir, 'dogs'), exist_ok=True)\n    \n    # Extract zip file\n    with zipfile.ZipFile(DATASET_PATH, 'r') as zip_ref:\n        zip_ref.extractall(WORKING_DIR)\n    \n    # Organize files into cats and dogs folders\n    source_dir = os.path.join(WORKING_DIR, 'train')\n    \n    # Move files to respective folders\n    for filename in os.listdir(source_dir):\n        if filename.startswith('cat.'):\n            src = os.path.join(source_dir, filename)\n            dst = os.path.join(train_dir, 'cats', filename)\n            if not os.path.exists(dst) and os.path.isfile(src):\n                os.rename(src, dst)\n        elif filename.startswith('dog.'):\n            src = os.path.join(source_dir, filename)\n            dst = os.path.join(train_dir, 'dogs', filename)\n            if not os.path.exists(dst) and os.path.isfile(src):\n                os.rename(src, dst)\n    \n    # Count images\n    num_cats = len(os.listdir(os.path.join(train_dir, 'cats')))\n    num_dogs = len(os.listdir(os.path.join(train_dir, 'dogs')))\n    print(f\"Dataset prepared: {num_cats} cat images, {num_dogs} dog images\")\n    \n    return train_dir\n\n# ============================================================================\n# DATA GENERATORS\n# ============================================================================","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-02T18:48:48.988539Z","iopub.execute_input":"2026-03-02T18:48:48.989083Z","iopub.status.idle":"2026-03-02T18:48:49.535293Z","shell.execute_reply.started":"2026-03-02T18:48:48.989059Z","shell.execute_reply":"2026-03-02T18:48:49.534449Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def create_data_generators(train_dir, augmentation=False):\n    \"\"\"Create data generators with optional augmentation\"\"\"\n    \n    if augmentation:\n        # Data augmentation for training\n        train_datagen = ImageDataGenerator(\n            rescale=1./255,\n            rotation_range=40,\n            width_shift_range=0.2,\n            height_shift_range=0.2,\n            shear_range=0.2,\n            zoom_range=0.2,\n            horizontal_flip=True,\n            fill_mode='nearest',\n            validation_split=VALIDATION_SPLIT\n        )\n        print(\"Using data augmentation\")\n    else:\n        # No augmentation\n        train_datagen = ImageDataGenerator(\n            rescale=1./255,\n            validation_split=VALIDATION_SPLIT\n        )\n        print(\"No data augmentation\")\n    \n    # Validation data generator (no augmentation)\n    val_datagen = ImageDataGenerator(\n        rescale=1./255,\n        validation_split=VALIDATION_SPLIT\n    )\n    \n    # Create generators\n    train_generator = train_datagen.flow_from_directory(\n        train_dir,\n        target_size=(IMG_SIZE, IMG_SIZE),\n        batch_size=BATCH_SIZE,\n        class_mode='binary',\n        subset='training',\n        shuffle=True,\n        seed=42\n    )\n    \n    validation_generator = val_datagen.flow_from_directory(\n        train_dir,\n        target_size=(IMG_SIZE, IMG_SIZE),\n        batch_size=BATCH_SIZE,\n        class_mode='binary',\n        subset='validation',\n        shuffle=False,\n        seed=42\n    )\n    \n    return train_generator, validation_generator","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-02T18:48:49.536432Z","iopub.execute_input":"2026-03-02T18:48:49.536931Z","iopub.status.idle":"2026-03-02T18:48:49.566364Z","shell.execute_reply.started":"2026-03-02T18:48:49.5369Z","shell.execute_reply":"2026-03-02T18:48:49.565601Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def build_baseline_model():\n    \"\"\"Baseline CNN without regularization\"\"\"\n    model = models.Sequential([\n        layers.Conv2D(32, (3, 3), activation='relu', input_shape=(IMG_SIZE, IMG_SIZE, 3)),\n        layers.MaxPooling2D(2, 2),\n        \n        layers.Conv2D(64, (3, 3), activation='relu'),\n        layers.MaxPooling2D(2, 2),\n        \n        layers.Conv2D(128, (3, 3), activation='relu'),\n        layers.MaxPooling2D(2, 2),\n        \n        layers.Conv2D(128, (3, 3), activation='relu'),\n        layers.MaxPooling2D(2, 2),\n        \n        layers.Flatten(),\n        layers.Dense(512, activation='relu'),\n        layers.Dense(1, activation='sigmoid')\n    ])\n    \n    model.compile(\n        optimizer='adam',\n        loss='binary_crossentropy',\n        metrics=['accuracy']\n    )\n    \n    return model\n\ndef build_l1_model():\n    \"\"\"CNN with L1 weight regularization\"\"\"\n    model = models.Sequential([\n        layers.Conv2D(32, (3, 3), activation='relu', \n                     kernel_regularizer=regularizers.l1(0.001),\n                     input_shape=(IMG_SIZE, IMG_SIZE, 3)),\n        layers.MaxPooling2D(2, 2),\n        \n        layers.Conv2D(64, (3, 3), activation='relu',\n                     kernel_regularizer=regularizers.l1(0.001)),\n        layers.MaxPooling2D(2, 2),\n        \n        layers.Conv2D(128, (3, 3), activation='relu',\n                     kernel_regularizer=regularizers.l1(0.001)),\n        layers.MaxPooling2D(2, 2),\n        \n        layers.Conv2D(128, (3, 3), activation='relu',\n                     kernel_regularizer=regularizers.l1(0.001)),\n        layers.MaxPooling2D(2, 2),\n        \n        layers.Flatten(),\n        layers.Dense(512, activation='relu',\n                    kernel_regularizer=regularizers.l1(0.001)),\n        layers.Dense(1, activation='sigmoid')\n    ])\n    \n    model.compile(\n        optimizer='adam',\n        loss='binary_crossentropy',\n        metrics=['accuracy']\n    )\n    \n    return model\n\ndef build_l2_model():\n    \"\"\"CNN with L2 weight regularization\"\"\"\n    model = models.Sequential([\n        layers.Conv2D(32, (3, 3), activation='relu', \n                     kernel_regularizer=regularizers.l2(0.001),\n                     input_shape=(IMG_SIZE, IMG_SIZE, 3)),\n        layers.MaxPooling2D(2, 2),\n        \n        layers.Conv2D(64, (3, 3), activation='relu',\n                     kernel_regularizer=regularizers.l2(0.001)),\n        layers.MaxPooling2D(2, 2),\n        \n        layers.Conv2D(128, (3, 3), activation='relu',\n                     kernel_regularizer=regularizers.l2(0.001)),\n        layers.MaxPooling2D(2, 2),\n        \n        layers.Conv2D(128, (3, 3), activation='relu',\n                     kernel_regularizer=regularizers.l2(0.001)),\n        layers.MaxPooling2D(2, 2),\n        \n        layers.Flatten(),\n        layers.Dense(512, activation='relu',\n                    kernel_regularizer=regularizers.l2(0.001)),\n        layers.Dense(1, activation='sigmoid')\n    ])\n    \n    model.compile(\n        optimizer='adam',\n        loss='binary_crossentropy',\n        metrics=['accuracy']\n    )\n    \n    return model\n\ndef build_dropout_model():\n    \"\"\"CNN with Dropout regularization\"\"\"\n    model = models.Sequential([\n        layers.Conv2D(32, (3, 3), activation='relu', input_shape=(IMG_SIZE, IMG_SIZE, 3)),\n        layers.MaxPooling2D(2, 2),\n        layers.Dropout(0.25),\n        \n        layers.Conv2D(64, (3, 3), activation='relu'),\n        layers.MaxPooling2D(2, 2),\n        layers.Dropout(0.25),\n        \n        layers.Conv2D(128, (3, 3), activation='relu'),\n        layers.MaxPooling2D(2, 2),\n        layers.Dropout(0.25),\n        \n        layers.Conv2D(128, (3, 3), activation='relu'),\n        layers.MaxPooling2D(2, 2),\n        layers.Dropout(0.25),\n        \n        layers.Flatten(),\n        layers.Dense(512, activation='relu'),\n        layers.Dropout(0.5),\n        layers.Dense(1, activation='sigmoid')\n    ])\n    \n    model.compile(\n        optimizer='adam',\n        loss='binary_crossentropy',\n        metrics=['accuracy']\n    )\n    \n    return model\n\ndef build_combined_model():\n    \"\"\"CNN with Dropout (to be used with data augmentation)\"\"\"\n    model = models.Sequential([\n        layers.Conv2D(32, (3, 3), activation='relu', input_shape=(IMG_SIZE, IMG_SIZE, 3)),\n        layers.MaxPooling2D(2, 2),\n        layers.Dropout(0.25),\n        \n        layers.Conv2D(64, (3, 3), activation='relu'),\n        layers.MaxPooling2D(2, 2),\n        layers.Dropout(0.25),\n        \n        layers.Conv2D(128, (3, 3), activation='relu'),\n        layers.MaxPooling2D(2, 2),\n        layers.Dropout(0.25),\n        \n        layers.Conv2D(128, (3, 3), activation='relu'),\n        layers.MaxPooling2D(2, 2),\n        layers.Dropout(0.25),\n        \n        layers.Flatten(),\n        layers.Dense(512, activation='relu'),\n        layers.Dropout(0.5),\n        layers.Dense(1, activation='sigmoid')\n    ])\n    \n    model.compile(\n        optimizer='adam',\n        loss='binary_crossentropy',\n        metrics=['accuracy']\n    )\n    \n    return model","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-02T18:48:49.567363Z","iopub.execute_input":"2026-03-02T18:48:49.567649Z","iopub.status.idle":"2026-03-02T18:48:49.586022Z","shell.execute_reply.started":"2026-03-02T18:48:49.567623Z","shell.execute_reply":"2026-03-02T18:48:49.585273Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def train_model(model, train_gen, val_gen, model_name):\n    \"\"\"Train a model with callbacks\"\"\"\n    print(f\"\\n{'='*60}\")\n    print(f\"Training: {model_name}\")\n    print(f\"{'='*60}\")\n    \n    # Callbacks\n    early_stop = EarlyStopping(\n        monitor='val_loss',\n        patience=5,\n        restore_best_weights=True,\n        verbose=1\n    )\n    \n    reduce_lr = ReduceLROnPlateau(\n        monitor='val_loss',\n        factor=0.5,\n        patience=3,\n        min_lr=1e-7,\n        verbose=1\n    )\n    \n    # Train\n    history = model.fit(\n        train_gen,\n        epochs=EPOCHS,\n        validation_data=val_gen,\n        callbacks=[early_stop, reduce_lr],\n        verbose=1\n    )\n    \n    return history","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-02T18:48:49.58701Z","iopub.execute_input":"2026-03-02T18:48:49.58732Z","iopub.status.idle":"2026-03-02T18:48:49.605733Z","shell.execute_reply.started":"2026-03-02T18:48:49.587298Z","shell.execute_reply":"2026-03-02T18:48:49.605126Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def plot_training_history(histories, model_names):\n    \"\"\"Plot training and validation accuracy/loss for all models\"\"\"\n    fig, axes = plt.subplots(2, 3, figsize=(18, 10))\n    fig.suptitle('Training History Comparison', fontsize=16, fontweight='bold')\n    \n    colors = ['blue', 'green', 'red', 'purple', 'orange', 'brown']\n    \n    for idx, (history, name, color) in enumerate(zip(histories, model_names, colors)):\n        row = idx // 3\n        col = idx % 3\n        \n        ax = axes[row, col]\n        \n        # Plot accuracy\n        ax.plot(history.history['accuracy'], label='Train Acc', color=color, linewidth=2)\n        ax.plot(history.history['val_accuracy'], label='Val Acc', \n                color=color, linestyle='--', linewidth=2)\n        \n        # Mark best validation accuracy\n        best_val_acc = max(history.history['val_accuracy'])\n        best_epoch = history.history['val_accuracy'].index(best_val_acc)\n        ax.scatter(best_epoch, best_val_acc, color='red', s=100, \n                  zorder=5, marker='*', edgecolors='black', linewidths=1.5)\n        \n        ax.set_title(f'{name}\\nBest Val Acc: {best_val_acc:.4f}', \n                    fontsize=12, fontweight='bold')\n        ax.set_xlabel('Epoch')\n        ax.set_ylabel('Accuracy')\n        ax.legend(loc='lower right')\n        ax.grid(True, alpha=0.3)\n    \n    plt.tight_layout()\n    plt.savefig('training_history_comparison.png', dpi=150, bbox_inches='tight')\n    plt.show()\n\ndef plot_accuracy_comparison(histories, model_names):\n    \"\"\"Bar plot comparing final validation accuracies\"\"\"\n    val_accs = [max(h.history['val_accuracy']) for h in histories]\n    train_accs = [max(h.history['accuracy']) for h in histories]\n    \n    x = np.arange(len(model_names))\n    width = 0.35\n    \n    fig, ax = plt.subplots(figsize=(14, 7))\n    bars1 = ax.bar(x - width/2, train_accs, width, label='Train Accuracy', \n                   color='skyblue', edgecolor='black', linewidth=1.5)\n    bars2 = ax.bar(x + width/2, val_accs, width, label='Validation Accuracy', \n                   color='lightcoral', edgecolor='black', linewidth=1.5)\n    \n    ax.set_xlabel('Model', fontsize=12, fontweight='bold')\n    ax.set_ylabel('Accuracy', fontsize=12, fontweight='bold')\n    ax.set_title('Final Model Performance Comparison', fontsize=14, fontweight='bold')\n    ax.set_xticks(x)\n    ax.set_xticklabels(model_names, rotation=45, ha='right')\n    ax.legend()\n    ax.grid(True, alpha=0.3, axis='y')\n    ax.set_ylim([0.5, 1.0])\n    \n    # Add value labels on bars\n    for bars in [bars1, bars2]:\n        for bar in bars:\n            height = bar.get_height()\n            ax.text(bar.get_x() + bar.get_width()/2., height,\n                   f'{height:.4f}',\n                   ha='center', va='bottom', fontsize=9, fontweight='bold')\n    \n    plt.tight_layout()\n    plt.savefig('accuracy_comparison.png', dpi=150, bbox_inches='tight')\n    plt.show()\n\ndef plot_overfitting_analysis(histories, model_names):\n    \"\"\"Analyze overfitting by comparing train-val gap\"\"\"\n    gaps = []\n    for history in histories:\n        final_train_acc = history.history['accuracy'][-1]\n        final_val_acc = history.history['val_accuracy'][-1]\n        gap = final_train_acc - final_val_acc\n        gaps.append(gap)\n    \n    fig, ax = plt.subplots(figsize=(12, 7))\n    colors = ['red' if gap > 0.1 else 'orange' if gap > 0.05 else 'green' for gap in gaps]\n    bars = ax.bar(model_names, gaps, color=colors, edgecolor='black', linewidth=1.5)\n    \n    ax.set_xlabel('Model', fontsize=12, fontweight='bold')\n    ax.set_ylabel('Train-Val Accuracy Gap', fontsize=12, fontweight='bold')\n    ax.set_title('Overfitting Analysis (Lower is Better)', fontsize=14, fontweight='bold')\n    ax.axhline(y=0.05, color='blue', linestyle='--', linewidth=2, label='Acceptable Gap (5%)')\n    ax.axhline(y=0.1, color='red', linestyle='--', linewidth=2, label='High Overfitting (10%)')\n    ax.legend()\n    ax.grid(True, alpha=0.3, axis='y')\n    \n    # Rotate x-axis labels\n    plt.xticks(rotation=45, ha='right')\n    \n    # Add value labels\n    for bar, gap in zip(bars, gaps):\n        height = bar.get_height()\n        ax.text(bar.get_x() + bar.get_width()/2., height,\n               f'{gap:.4f}',\n               ha='center', va='bottom', fontsize=10, fontweight='bold')\n    \n    plt.tight_layout()\n    plt.savefig('overfitting_analysis.png', dpi=150, bbox_inches='tight')\n    plt.show()\n\ndef create_results_table(histories, model_names):\n    \"\"\"Create a summary table of results\"\"\"\n    results = []\n    \n    for history, name in zip(histories, model_names):\n        best_val_acc = max(history.history['val_accuracy'])\n        best_epoch = history.history['val_accuracy'].index(best_val_acc) + 1\n        final_train_acc = history.history['accuracy'][-1]\n        final_val_acc = history.history['val_accuracy'][-1]\n        train_val_gap = final_train_acc - final_val_acc\n        \n        results.append({\n            'Model': name,\n            'Best Val Acc': f'{best_val_acc:.4f}',\n            'Best Epoch': best_epoch,\n            'Final Train Acc': f'{final_train_acc:.4f}',\n            'Final Val Acc': f'{final_val_acc:.4f}',\n            'Train-Val Gap': f'{train_val_gap:.4f}'\n        })\n    \n    df = pd.DataFrame(results)\n    \n    print(\"\\n\" + \"=\"*80)\n    print(\"RESULTS SUMMARY\")\n    print(\"=\"*80)\n    print(df.to_string(index=False))\n    print(\"=\"*80)\n    \n    # Save to CSV\n    df.to_csv('results_summary.csv', index=False)\n    \n    return df","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-02T18:48:49.607752Z","iopub.execute_input":"2026-03-02T18:48:49.607979Z","iopub.status.idle":"2026-03-02T18:48:49.625854Z","shell.execute_reply.started":"2026-03-02T18:48:49.607959Z","shell.execute_reply":"2026-03-02T18:48:49.625213Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"\n\"\"\"Main execution function\"\"\"\n\n# Prepare dataset\ntrain_dir = prepare_dataset()\n\n# Store all histories and names\nhistories = []\nmodel_names = []\n\n# ========================================================================\n# 1. BASELINE MODEL (No Regularization)\n# ========================================================================\nprint(\"\\n\" + \"=\"*80)\nprint(\"1. BASELINE MODEL - No Regularization\")\nprint(\"=\"*80)\n\ntrain_gen, val_gen = create_data_generators(train_dir, augmentation=False)\nmodel_baseline = build_baseline_model()\nmodel_baseline.summary()\n\nhistory_baseline = train_model(model_baseline, train_gen, val_gen, \"Baseline\")\nhistories.append(history_baseline)\nmodel_names.append(\"Baseline\")\n\n# ========================================================================\n# 2. L1 REGULARIZATION\n# ========================================================================\nprint(\"\\n\" + \"=\"*80)\nprint(\"2. L1 REGULARIZATION\")\nprint(\"=\"*80)\n\ntrain_gen, val_gen = create_data_generators(train_dir, augmentation=False)\nmodel_l1 = build_l1_model()\n\nhistory_l1 = train_model(model_l1, train_gen, val_gen, \"L1 Regularization\")\nhistories.append(history_l1)\nmodel_names.append(\"L1 Reg\")\n\n# ========================================================================\n# 3. L2 REGULARIZATION\n# ========================================================================\nprint(\"\\n\" + \"=\"*80)\nprint(\"3. L2 REGULARIZATION\")\nprint(\"=\"*80)\n\ntrain_gen, val_gen = create_data_generators(train_dir, augmentation=False)\nmodel_l2 = build_l2_model()\n\nhistory_l2 = train_model(model_l2, train_gen, val_gen, \"L2 Regularization\")\nhistories.append(history_l2)\nmodel_names.append(\"L2 Reg\")\n\n# ========================================================================\n# 4. DROPOUT\n# ========================================================================\nprint(\"\\n\" + \"=\"*80)\nprint(\"4. DROPOUT REGULARIZATION\")\nprint(\"=\"*80)\n\ntrain_gen, val_gen = create_data_generators(train_dir, augmentation=False)\nmodel_dropout = build_dropout_model()\n\nhistory_dropout = train_model(model_dropout, train_gen, val_gen, \"Dropout\")\nhistories.append(history_dropout)\nmodel_names.append(\"Dropout\")\n\n# ========================================================================\n# 5. DATA AUGMENTATION (without dropout)\n# ========================================================================\nprint(\"\\n\" + \"=\"*80)\nprint(\"5. DATA AUGMENTATION\")\nprint(\"=\"*80)\n\ntrain_gen, val_gen = create_data_generators(train_dir, augmentation=True)\nmodel_augmentation = build_baseline_model()  # Use baseline architecture\n\nhistory_augmentation = train_model(model_augmentation, train_gen, val_gen, \n                                  \"Data Augmentation\")\nhistories.append(history_augmentation)\nmodel_names.append(\"Data Aug\")\n\n# ========================================================================\n# 6. COMBINED (Dropout + Data Augmentation)\n# ========================================================================\nprint(\"\\n\" + \"=\"*80)\nprint(\"6. COMBINED (Dropout + Data Augmentation)\")\nprint(\"=\"*80)\n\ntrain_gen, val_gen = create_data_generators(train_dir, augmentation=True)\nmodel_combined = build_combined_model()\n\nhistory_combined = train_model(model_combined, train_gen, val_gen, \n                               \"Combined (Dropout + Aug)\")\nhistories.append(history_combined)\nmodel_names.append(\"Combined\")\n\n# ========================================================================\n# RESULTS ANALYSIS\n# ========================================================================\nprint(\"\\n\" + \"=\"*80)\nprint(\"GENERATING ANALYSIS AND VISUALIZATIONS\")\nprint(\"=\"*80)\n\n# Create visualizations\nplot_training_history(histories, model_names)\nplot_accuracy_comparison(histories, model_names)\nplot_overfitting_analysis(histories, model_names)\n\n# Create results table\nresults_df = create_results_table(histories, model_names)\n\n# Print analysis\nprint(\"\\n\" + \"=\"*80)\nprint(\"ANALYSIS OF REGULARIZATION TECHNIQUES\")\nprint(\"=\"*80)\n\nprint(\"\"\"\nKEY FINDINGS:\n\n1. L1 REGULARIZATION:\n   - Adds penalty proportional to absolute value of weights\n   - Encourages sparsity (many weights become exactly 0)\n   - Effect: Feature selection, simpler models\n   - Best for: Models with many irrelevant features\n\n2. L2 REGULARIZATION:\n   - Adds penalty proportional to square of weights\n   - Encourages small weights but not exactly 0\n   - Effect: Weight decay, prevents large weight values\n   - Best for: General overfitting reduction\n\n3. DROPOUT:\n   - Randomly drops neurons during training\n   - Forces network to learn redundant representations\n   - Effect: Prevents co-adaptation of neurons\n   - Best for: Deep networks, strong regularization\n\n4. DATA AUGMENTATION:\n   - Artificially increases training data diversity\n   - No architectural changes needed\n   - Effect: Model sees more variations, better generalization\n   - Best for: Limited data, image classification\n\n5. COMBINED APPROACH:\n   - Leverages multiple regularization techniques\n   - Often achieves best generalization\n   - Effect: Robust model with reduced overfitting\n   - Best for: Production models, complex tasks\n\nRECOMMENDATIONS:\n- Start with data augmentation for image tasks\n- Add dropout for deep networks\n- Use L2 for general weight control\n- Combine techniques for best results\n- Monitor train-val gap to detect overfitting\n\"\"\")\n\nprint(\"\\nAll visualizations saved:\")\nprint(\"  - training_history_comparison.png\")\nprint(\"  - accuracy_comparison.png\")\nprint(\"  - overfitting_analysis.png\")\nprint(\"  - results_summary.csv\")\n\nprint(\"\\n\" + \"=\"*80)\nprint(\"TRAINING COMPLETE!\")\nprint(\"=\"*80)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-02T18:48:49.626753Z","iopub.execute_input":"2026-03-02T18:48:49.627026Z"}},"outputs":[],"execution_count":null}]}