{"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":"nvidiaTeslaT4","dataSources":[],"dockerImageVersionId":31329,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import numpy as np\nimport matplotlib.pyplot as plt\nimport tensorflow as tf\nfrom tensorflow import keras\nfrom tensorflow.keras import layers, models, callbacks\nfrom tensorflow.keras.datasets import cifar10\nfrom tensorflow.keras.utils import to_categorical\nfrom sklearn.metrics import confusion_matrix, classification_report\nimport seaborn as sns\nimport time","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2026-04-18T08:13:56.762853Z","iopub.execute_input":"2026-04-18T08:13:56.763701Z","iopub.status.idle":"2026-04-18T08:14:20.973657Z","shell.execute_reply.started":"2026-04-18T08:13:56.763651Z","shell.execute_reply":"2026-04-18T08:14:20.973073Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"np.random.seed(42)\ntf.random.set_seed(42)\n\nCLASS_NAMES = ['airplane','automobile','bird','cat','deer',\n'dog','frog','horse','ship','truck']\n\n(x_train_full, y_train_full), (x_test, y_test) = cifar10.load_data()\n\nx_train = x_train_full[:40000].astype('float32')\ny_train = y_train_full[:40000]\nx_val = x_train_full[40000:].astype('float32')\ny_val = y_train_full[40000:]\nx_test = x_test.astype('float32')\nprint(f\"Train: {x_train.shape} | Val: {x_val.shape} | Test: {x_test.shape}\")\nprint(f\"Pixel range: [{x_train.min()}, {x_train.max()}]\")\nprint(f\"Image shape: {x_train[0].shape}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-18T08:14:20.974855Z","iopub.execute_input":"2026-04-18T08:14:20.975235Z","iopub.status.idle":"2026-04-18T08:14:27.100412Z","shell.execute_reply.started":"2026-04-18T08:14:20.975211Z","shell.execute_reply":"2026-04-18T08:14:27.099788Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def train_and_evaluate(model, x_tr, y_tr, x_v, y_v, x_te, y_te, epochs=20, batch_size=128, extra_callbacks=None):\n    cb = extra_callbacks if extra_callbacks else []\n    start = time.time()\n    \n    history = model.fit(\n        x_tr, to_categorical(y_tr, 10),\n        validation_data=(x_v, to_categorical(y_v, 10)),\n        epochs=epochs, \n        batch_size=batch_size,\n        callbacks=cb, \n        verbose=0\n    )\n    \n    elapsed = time.time() - start\n    test_loss, test_acc = model.evaluate(x_te, to_categorical(y_te, 10), verbose=0)\n    print(f\"Test Acc: {test_acc:.4f} | Test Loss: {test_loss:.4f} | Time: {elapsed:.1f}s\")\n    \n    return history, test_acc, test_loss, elapsed\n\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-18T08:14:27.101351Z","iopub.execute_input":"2026-04-18T08:14:27.101587Z","iopub.status.idle":"2026-04-18T08:14:27.106530Z","shell.execute_reply.started":"2026-04-18T08:14:27.101565Z","shell.execute_reply":"2026-04-18T08:14:27.105916Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def plot_curves(histories, labels, metric='val_accuracy', title='', ylabel=''):\n    plt.figure(figsize=(10, 6))\n    for h, lbl in zip(histories, labels):\n        plt.plot(h.history[metric], label=lbl)\n    plt.xlabel('Epoch')\n    plt.ylabel(ylabel if ylabel else metric)\n    plt.title(title)\n    plt.legend()\n    plt.grid(True)\n    plt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-18T08:14:27.108232Z","iopub.execute_input":"2026-04-18T08:14:27.108818Z","iopub.status.idle":"2026-04-18T08:14:27.120548Z","shell.execute_reply.started":"2026-04-18T08:14:27.108796Z","shell.execute_reply":"2026-04-18T08:14:27.119894Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def build_baseline_cnn():\n    model = models.Sequential([\n        layers.Conv2D(32, (3, 3), activation='relu', padding='same', input_shape=(32, 32, 3)),\n        layers.MaxPooling2D((2, 2)),\n        layers.Conv2D(64, (3, 3), activation='relu', padding='same'),\n        layers.MaxPooling2D((2, 2)),\n        layers.Flatten(),\n        layers.Dense(128, activation='relu'),\n        layers.Dense(10, activation='softmax')\n    ])\n    model.compile(optimizer=keras.optimizers.Adam(learning_rate=0.001),\n                  loss='categorical_crossentropy',\n                  metrics=['accuracy'])\n    return model","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-18T08:14:27.121401Z","iopub.execute_input":"2026-04-18T08:14:27.121705Z","iopub.status.idle":"2026-04-18T08:14:27.132312Z","shell.execute_reply.started":"2026-04-18T08:14:27.121674Z","shell.execute_reply":"2026-04-18T08:14:27.131621Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"\nx_train_A, x_val_A, x_test_A = x_train, x_val, x_test\n\nx_train_B, x_val_B, x_test_B = x_train / 255.0, x_val / 255.0, x_test / 255.0\n\n\nmean = np.mean(x_train, axis=(0, 1, 2, 3))\nstd = np.std(x_train, axis=(0, 1, 2, 3))\nx_train_C = (x_train - mean) / (std + 1e-7)\nx_val_C = (x_val - mean) / (std + 1e-7)\nx_test_C = (x_test - mean) / (std + 1e-7)\n\nexperiments_1a = {\n    'None (0-255)': (x_train_A, x_val_A, x_test_A),\n    'Min-Max [0,1]': (x_train_B, x_val_B, x_test_B),\n    'Standardized': (x_train_C, x_val_C, x_test_C)\n}\n\n\nhistories_1a = []\nlabels_1a = []\n\nfor name, (x_tr, x_v, x_te) in experiments_1a.items():\n    print(f\"\\n--- Running Task 1A: {name} ---\")\n    model = build_baseline_cnn()\n    hist, test_acc, test_loss, elapsed = train_and_evaluate(model, x_tr, y_train, x_v, y_val, x_te, y_test)\n    histories_1a.append(hist)\n    labels_1a.append(name)\n\n\nplot_curves(histories_1a, labels_1a, metric='loss', title='Training Loss - Preprocessing Comparison')\nplot_curves(histories_1a, labels_1a, metric='val_accuracy', title='Val Accuracy - Preprocessing Comparison')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-18T08:14:27.133203Z","iopub.execute_input":"2026-04-18T08:14:27.133458Z","iopub.status.idle":"2026-04-18T08:16:42.510905Z","shell.execute_reply.started":"2026-04-18T08:14:27.133430Z","shell.execute_reply":"2026-04-18T08:16:42.510415Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"x_train_std, x_val_std, x_test_std = x_train_C, x_val_C, x_test_C\n\n\nprint(\"\\n--- Running : No Augmentation ---\")\nmodel_no_aug = build_baseline_cnn()\nhist_no_aug, _, _, _ = train_and_evaluate(\n    model_no_aug, x_train_std, y_train, x_val_std, y_val, x_test_std, y_test, epochs=40\n)\n\n\nprint(\"\\n--- Running : With Augmentation ---\")\ndatagen = keras.preprocessing.image.ImageDataGenerator(\n    rotation_range=15,\n    width_shift_range=0.1,\n    height_shift_range=0.1,\n    horizontal_flip=True,\n    zoom_range=0.1\n)\n\nmodel_with_aug = build_baseline_cnn()\nstart_aug = time.time()\n\nhist_with_aug = model_with_aug.fit(\n    datagen.flow(x_train_std, to_categorical(y_train, 10), batch_size=128),\n    validation_data=(x_val_std, to_categorical(y_val, 10)),\n    epochs=40,\n    verbose=0\n)\nelapsed_aug = time.time() - start_aug\ntest_loss_aug, test_acc_aug = model_with_aug.evaluate(x_test_std, to_categorical(y_test, 10), verbose=0)\nprint(f\"Test Acc (Aug): {test_acc_aug:.4f} | Time: {elapsed_aug:.1f}s\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-18T08:16:42.511937Z","iopub.execute_input":"2026-04-18T08:16:42.512278Z","iopub.status.idle":"2026-04-18T08:30:41.286950Z","shell.execute_reply.started":"2026-04-18T08:16:42.512253Z","shell.execute_reply":"2026-04-18T08:30:41.286281Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"plt.figure(figsize=(10, 6))\nplt.plot(hist_no_aug.history['accuracy'], label='Train Acc (No Aug)', linestyle='--')\nplt.plot(hist_no_aug.history['val_accuracy'], label='Val Acc (No Aug)')\nplt.plot(hist_with_aug.history['accuracy'], label='Train Acc (With Aug)', linestyle='--')\nplt.plot(hist_with_aug.history['val_accuracy'], label='Val Acc (With Aug)')\nplt.title('Data Augmentation Comparison')\nplt.xlabel('Epoch')\nplt.ylabel('Accuracy')\nplt.legend()\nplt.grid(True)\nplt.show()\n\n\ngap_no_aug = hist_no_aug.history['accuracy'][-1] - hist_no_aug.history['val_accuracy'][-1]\ngap_with_aug = hist_with_aug.history['accuracy'][-1] - hist_with_aug.history['val_accuracy'][-1]\nprint(f\"Overfit Gap (No Aug): {gap_no_aug:.4f}\")\nprint(f\"Overfit Gap (With Aug): {gap_with_aug:.4f}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-18T08:30:41.287851Z","iopub.execute_input":"2026-04-18T08:30:41.288068Z","iopub.status.idle":"2026-04-18T08:30:41.468791Z","shell.execute_reply.started":"2026-04-18T08:30:41.288047Z","shell.execute_reply":"2026-04-18T08:30:41.468066Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ==========================================\n# Task 2: CNN Architecture Experiments\n# ==========================================\nprint(\"=\"*50)\nprint(\"STARTING : FILTER COUNT COMPARISON\")\nprint(\"=\"*50)\n\ndef build_filter_model(f1, f2, f3, f4):\n    model = models.Sequential([\n        layers.Conv2D(f1, (3, 3), activation='relu', padding='same', input_shape=(32, 32, 3)),\n        layers.Conv2D(f2, (3, 3), activation='relu', padding='same'),\n        layers.MaxPooling2D((2, 2)),\n        layers.Conv2D(f3, (3, 3), activation='relu', padding='same'),\n        layers.Conv2D(f4, (3, 3), activation='relu', padding='same'),\n        layers.MaxPooling2D((2, 2)),\n        layers.Flatten(),\n        layers.Dense(256, activation='relu'),\n        layers.Dense(10, activation='softmax')\n    ])\n    \n    model.compile(optimizer=keras.optimizers.Adam(learning_rate=0.001),\n                  loss='categorical_crossentropy',\n                  metrics=['accuracy'])\n    return model\n\n\nfilter_configs = {\n    'Small': (8, 8, 16, 16),\n    'Medium': (32, 32, 64, 64),\n    'Large': (64, 64, 128, 128)\n}\n\nhistories_2a = []\nlabels_2a = []\n\nfor name, filters in filter_configs.items():\n    print(f\"\\n--- Running Task 2A: {name} Model ---\")\n    model = build_filter_model(*filters)\n    \n    \n    print(f\"\\nModel Summary for {name}:\")\n    model.summary() \n    \n    hist, test_acc, test_loss, elapsed = train_and_evaluate(\n        model, x_train_std, y_train, x_val_std, y_val, x_test_std, y_test, epochs=20\n    )\n    \n    histories_2a.append(hist)\n    labels_2a.append(name)\n\n\nplot_curves(histories_2a, labels_2a, metric='val_accuracy', title='Task 2A: Val Accuracy Comparison (Filters)')\n\n\n\nprint(\"\\n\" + \"=\"*50)\nprint(\"STARTING : NETWORK DEPTH COMPARISON\")\nprint(\"=\"*50)\n\n\ndef build_shallow_model():\n    model = models.Sequential([\n        layers.Conv2D(32, (3,3), activation='relu', padding='same', input_shape=(32,32,3)),\n        layers.Conv2D(32, (3,3), activation='relu', padding='same'),\n        layers.MaxPooling2D((2,2)),\n        layers.Conv2D(32, (3,3), activation='relu', padding='same'),\n        layers.Conv2D(32, (3,3), activation='relu', padding='same'),\n        layers.MaxPooling2D((2,2)),\n        layers.Flatten(),\n        layers.Dense(256, activation='relu'),\n        layers.Dense(10, activation='softmax')\n    ])\n    model.compile(optimizer=keras.optimizers.Adam(learning_rate=0.001), loss='categorical_crossentropy', metrics=['accuracy'])\n    return model\n\n\ndef build_medium_depth_model():\n    model = models.Sequential([\n        layers.Conv2D(32, (3,3), activation='relu', padding='same', input_shape=(32,32,3)),\n        layers.Conv2D(32, (3,3), activation='relu', padding='same'),\n        layers.MaxPooling2D((2,2)),\n        layers.Conv2D(32, (3,3), activation='relu', padding='same'),\n        layers.Conv2D(32, (3,3), activation='relu', padding='same'),\n        layers.MaxPooling2D((2,2)),\n        layers.Conv2D(32, (3,3), activation='relu', padding='same'),\n        layers.Conv2D(32, (3,3), activation='relu', padding='same'),\n        layers.GlobalAveragePooling2D(), \n        layers.Dense(256, activation='relu'),\n        layers.Dense(10, activation='softmax')\n    ])\n    model.compile(optimizer=keras.optimizers.Adam(learning_rate=0.001), loss='categorical_crossentropy', metrics=['accuracy'])\n    return model\n\n\ndef build_deep_model():\n    model = models.Sequential([\n        layers.Conv2D(32, (3,3), activation='relu', padding='same', input_shape=(32,32,3)),\n        layers.Conv2D(32, (3,3), activation='relu', padding='same'),\n        layers.MaxPooling2D((2,2)),\n        layers.Conv2D(32, (3,3), activation='relu', padding='same'),\n        layers.Conv2D(32, (3,3), activation='relu', padding='same'),\n        layers.MaxPooling2D((2,2)),\n        layers.Conv2D(32, (3,3), activation='relu', padding='same'),\n        layers.Conv2D(32, (3,3), activation='relu', padding='same'),\n        layers.MaxPooling2D((2,2)),\n        layers.Conv2D(32, (3,3), activation='relu', padding='same'),\n        layers.Conv2D(32, (3,3), activation='relu', padding='same'),\n        layers.GlobalAveragePooling2D(),\n        layers.Dense(256, activation='relu'),\n        layers.Dense(10, activation='softmax')\n    ])\n    model.compile(optimizer=keras.optimizers.Adam(learning_rate=0.001), loss='categorical_crossentropy', metrics=['accuracy'])\n    return model\n\n\ndepth_models = {\n    'Shallow': build_shallow_model(),\n    'Medium Depth': build_medium_depth_model(),\n    'Deep': build_deep_model()\n}\n\nfor name, model in depth_models.items():\n    print(f\"\\n--- Running Task 2C: {name} Model ---\")\n    model.summary()\n    hist, test_acc, test_loss, elapsed = train_and_evaluate(\n        model, x_train_std, y_train, x_val_std, y_val, x_test_std, y_test, epochs=20\n    )\n    \n   \n    plt.figure(figsize=(8, 5))\n    plt.plot(hist.history['loss'], label='Train Loss')\n    plt.plot(hist.history['val_loss'], label='Val Loss')\n    plt.title(f'Task 2C: Loss Curve - {name} Model')\n    plt.xlabel('Epoch')\n    plt.ylabel('Loss')\n    plt.legend()\n    plt.grid(True)\n    plt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-18T08:30:41.469814Z","iopub.execute_input":"2026-04-18T08:30:41.470158Z","iopub.status.idle":"2026-04-18T08:38:34.871827Z","shell.execute_reply.started":"2026-04-18T08:30:41.470135Z","shell.execute_reply":"2026-04-18T08:38:34.871140Z"}},"outputs":[],"execution_count":null}]}