{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.12.13","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"none","dataSources":[],"dockerImageVersionId":28755,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"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\n\n# Use the kagglehub client library to attach Kaggle resources like competitions, datasets, and models to your session\n# Learn more about kagglehub: https://github.com/Kaggle/kagglehub/blob/main/README.md\n\nimport kagglehub\n# kagglehub.dataset_download('<owner>/<dataset-slug>')","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2026-06-07T20:44:27.092899Z","iopub.execute_input":"2026-06-07T20:44:27.093081Z","iopub.status.idle":"2026-06-07T20:44:29.021356Z","shell.execute_reply.started":"2026-06-07T20:44:27.093060Z","shell.execute_reply":"2026-06-07T20:44:29.020414Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"\"\"\"\nCIFAR-10 Image Classification CNN \n\"\"\"\n\n# ============================================================\n# 1. IMPORTS\n# ============================================================\nimport os\nimport numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\nimport seaborn as sns\nfrom PIL import Image\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.metrics import confusion_matrix, classification_report\n\nimport tensorflow as tf\nfrom tensorflow.keras import layers, models, optimizers\nfrom tensorflow.keras.callbacks import EarlyStopping, ReduceLROnPlateau, ModelCheckpoint\nfrom tensorflow.keras.utils import to_categorical\nfrom tensorflow.keras.preprocessing.image import ImageDataGenerator\n\n# Set seeds for reproducibility\nnp.random.seed(42)\ntf.random.set_seed(42)\n\nprint(f\"TensorFlow version: {tf.__version__}\")\nprint(f\"Num GPUs Available: {len(tf.config.list_physical_devices('GPU'))}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-06-07T20:44:29.022820Z","iopub.execute_input":"2026-06-07T20:44:29.023293Z","iopub.status.idle":"2026-06-07T20:44:45.264683Z","shell.execute_reply.started":"2026-06-07T20:44:29.023267Z","shell.execute_reply":"2026-06-07T20:44:45.263815Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ============================================================\n# 2. CONFIGURATION\n# ============================================================\nIMG_SIZE = 32\nCHANNELS = 3\nNUM_CLASSES = 10\nBATCH_SIZE = 128\nEPOCHS = 100\nLEARNING_RATE = 0.001\n\nCLASS_NAMES = [\n    'airplane', 'automobile', 'bird', 'cat', 'deer',\n    'dog', 'frog', 'horse', 'ship', 'truck'\n]\n\n# File Paths\nINPUT_DIR = '/kaggle/input/competitions/cifar-10'\nWORKING_DIR = '/kaggle/working/'\nTRAIN_7Z = os.path.join(INPUT_DIR, 'train.7z')\nTEST_7Z = os.path.join(INPUT_DIR, 'test.7z')\nLABELS_CSV = os.path.join(INPUT_DIR, 'trainLabels.csv')\nSAMPLE_SUBMISSION = os.path.join(INPUT_DIR, 'sampleSubmission.csv')\n\nTRAIN_EXTRACT = os.path.join(WORKING_DIR, 'train')\nTEST_EXTRACT = os.path.join(WORKING_DIR, 'test')\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-06-07T20:44:45.265740Z","iopub.execute_input":"2026-06-07T20:44:45.266649Z","iopub.status.idle":"2026-06-07T20:44:45.271924Z","shell.execute_reply.started":"2026-06-07T20:44:45.266593Z","shell.execute_reply":"2026-06-07T20:44:45.271205Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ============================================================\n# 3. EXTRACT 7Z ARCHIVES\n# ============================================================\n# Kaggle CIFAR-10 dataset comes as .7z files. We extract them to working dir.\n# Install py7zr if not available: !pip install py7zr -q\n\ntry:\n    import py7zr\nexcept ImportError:\n    print(\"Installing py7zr...\")\n    os.system(\"pip install py7zr -q\")\n    import py7zr\n\ndef extract_7z(archive_path, extract_to):\n    if os.path.exists(extract_to) and len(os.listdir(extract_to)) > 0:\n        print(f\"Already extracted: {extract_to}\")\n        return\n    os.makedirs(extract_to, exist_ok=True)\n    print(f\"Extracting {archive_path} ...\")\n    with py7zr.SevenZipFile(archive_path, mode='r') as z:\n        z.extractall(path=extract_to)\n    print(f\"Extracted to {extract_to}\")\n\nextract_7z(TRAIN_7Z, TRAIN_EXTRACT)\nextract_7z(TEST_7Z, TEST_EXTRACT)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-06-07T20:44:45.273073Z","iopub.execute_input":"2026-06-07T20:44:45.273367Z","iopub.status.idle":"2026-06-07T20:47:37.920303Z","shell.execute_reply.started":"2026-06-07T20:44:45.273334Z","shell.execute_reply":"2026-06-07T20:47:37.919565Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ============================================================\n# 4. LOAD LABELS AND IMAGE PATHS\n# ============================================================\nlabels_df = pd.read_csv(LABELS_CSV)\nprint(f\"Training labels shape: {labels_df.shape}\")\nprint(labels_df.head())\n\n# Map class names to integers\nclass_to_idx = {name: idx for idx, name in enumerate(CLASS_NAMES)}\nlabels_df['label_idx'] = labels_df['label'].map(class_to_idx)\n\n# Build file paths \ntrain_img_dir = os.path.join(TRAIN_EXTRACT, 'train') if os.path.exists(os.path.join(TRAIN_EXTRACT, 'train')) else TRAIN_EXTRACT\ntest_img_dir = os.path.join(TEST_EXTRACT, 'test') if os.path.exists(os.path.join(TEST_EXTRACT, 'test')) else TEST_EXTRACT\n\nlabels_df['filepath'] = labels_df['id'].apply(lambda x: os.path.join(train_img_dir, f\"{x}.png\"))\n\n# Verify a sample path exists\nprint(\"Sample path:\", labels_df['filepath'].iloc[0], \"Exists:\", os.path.exists(labels_df['filepath'].iloc[0]))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-06-07T20:47:37.922090Z","iopub.execute_input":"2026-06-07T20:47:37.922300Z","iopub.status.idle":"2026-06-07T20:47:38.013484Z","shell.execute_reply.started":"2026-06-07T20:47:37.922279Z","shell.execute_reply":"2026-06-07T20:47:38.012714Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ============================================================\n# 5. LOAD AND PREPROCESS IMAGES\n# ============================================================\ndef load_image(path, size=IMG_SIZE):\n    \"\"\"Load image and resize to target size.\"\"\"\n    img = Image.open(path).convert('RGB')\n    img = img.resize((size, size))\n    return np.array(img)\n\n# Load training images into memory (CIFAR-10 train is 50,000 images, manageable)\nprint(\"Loading training images...\")\ntrain_images = np.array([load_image(fp) for fp in labels_df['filepath']], dtype=np.float32)\ntrain_labels = labels_df['label_idx'].values.astype(np.int32)\n\nprint(f\"Train images shape: {train_images.shape}\")\n\n# Normalize pixel values to [0, 1]\ntrain_images /= 255.0\n\n# One-hot encode labels\ntrain_labels_cat = to_categorical(train_labels, NUM_CLASSES)\n\n# Split into train/validation (Kaggle test set has no labels; we hold out validation)\nX_train, X_val, y_train, y_val = train_test_split(\n    train_images, train_labels_cat, test_size=0.1, random_state=42, stratify=train_labels\n)\n\nprint(f\"X_train: {X_train.shape}, X_val: {X_val.shape}\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-06-07T20:47:38.014446Z","iopub.execute_input":"2026-06-07T20:47:38.014858Z","iopub.status.idle":"2026-06-07T20:47:47.350058Z","shell.execute_reply.started":"2026-06-07T20:47:38.014823Z","shell.execute_reply":"2026-06-07T20:47:47.349199Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ============================================================\n# 6. DATA AUGMENTATION\n# ============================================================\ndatagen = 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)\ndatagen.fit(X_train)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-06-07T20:47:47.351124Z","iopub.execute_input":"2026-06-07T20:47:47.351437Z","iopub.status.idle":"2026-06-07T20:47:47.542158Z","shell.execute_reply.started":"2026-06-07T20:47:47.351401Z","shell.execute_reply":"2026-06-07T20:47:47.541303Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ============================================================\n# 7. BUILD CNN MODEL\n# ============================================================\ndef build_cnn(input_shape=(IMG_SIZE, IMG_SIZE, CHANNELS), num_classes=NUM_CLASSES):\n    model = models.Sequential([\n        # Block 1\n        layers.Conv2D(32, (3, 3), padding='same', input_shape=input_shape),\n        layers.BatchNormalization(),\n        layers.Activation('relu'),\n        layers.Conv2D(32, (3, 3), padding='same'),\n        layers.BatchNormalization(),\n        layers.Activation('relu'),\n        layers.MaxPooling2D((2, 2)),\n        layers.Dropout(0.25),\n\n        # Block 2\n        layers.Conv2D(64, (3, 3), padding='same'),\n        layers.BatchNormalization(),\n        layers.Activation('relu'),\n        layers.Conv2D(64, (3, 3), padding='same'),\n        layers.BatchNormalization(),\n        layers.Activation('relu'),\n        layers.MaxPooling2D((2, 2)),\n        layers.Dropout(0.25),\n\n        # Block 3\n        layers.Conv2D(128, (3, 3), padding='same'),\n        layers.BatchNormalization(),\n        layers.Activation('relu'),\n        layers.Conv2D(128, (3, 3), padding='same'),\n        layers.BatchNormalization(),\n        layers.Activation('relu'),\n        layers.MaxPooling2D((2, 2)),\n        layers.Dropout(0.25),\n\n        # Classifier\n        layers.Flatten(),\n        layers.Dense(512),\n        layers.BatchNormalization(),\n        layers.Activation('relu'),\n        layers.Dropout(0.5),\n        layers.Dense(num_classes, activation='softmax')\n    ])\n    return model\n\nmodel = build_cnn()\nmodel.compile(\n    optimizer=optimizers.Adam(learning_rate=LEARNING_RATE),\n    loss='categorical_crossentropy',\n    metrics=['accuracy']\n)\n\nmodel.summary()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-06-07T20:47:47.543419Z","iopub.execute_input":"2026-06-07T20:47:47.544267Z","iopub.status.idle":"2026-06-07T20:47:49.125006Z","shell.execute_reply.started":"2026-06-07T20:47:47.544241Z","shell.execute_reply":"2026-06-07T20:47:49.124343Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ============================================================\n# 8. CALLBACKS\n# ============================================================\ncheckpoint_path = os.path.join(WORKING_DIR, 'best_cifar10_model.keras')\ncallbacks = [\n    EarlyStopping(monitor='val_accuracy', patience=15, restore_best_weights=True, verbose=1),\n    ReduceLROnPlateau(monitor='val_loss', factor=0.5, patience=5, min_lr=1e-7, verbose=1),\n    ModelCheckpoint(checkpoint_path, monitor='val_accuracy', save_best_only=True, verbose=1)\n]","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-06-07T20:47:49.126044Z","iopub.execute_input":"2026-06-07T20:47:49.126420Z","iopub.status.idle":"2026-06-07T20:47:49.130770Z","shell.execute_reply.started":"2026-06-07T20:47:49.126396Z","shell.execute_reply":"2026-06-07T20:47:49.130111Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ============================================================\n# 9. TRAIN MODEL\n# ============================================================\nhistory = model.fit(\n    datagen.flow(X_train, y_train, batch_size=BATCH_SIZE),\n    steps_per_epoch=len(X_train) // BATCH_SIZE,\n    epochs=EPOCHS,\n    validation_data=(X_val, y_val),\n    callbacks=callbacks,\n    verbose=1\n)\n\n# Save final model\nmodel.save(os.path.join(WORKING_DIR, 'cifar10_final_model.keras'))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-06-07T20:47:49.131934Z","iopub.execute_input":"2026-06-07T20:47:49.132570Z","iopub.status.idle":"2026-06-07T20:58:59.439810Z","shell.execute_reply.started":"2026-06-07T20:47:49.132545Z","shell.execute_reply":"2026-06-07T20:58:59.438843Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ============================================================\n# 10. PLOT TRAINING HISTORY\n# ============================================================\nfig, axes = plt.subplots(1, 2, figsize=(14, 5))\n\naxes[0].plot(history.history['accuracy'], label='Train Acc', linewidth=2)\naxes[0].plot(history.history['val_accuracy'], label='Val Acc', linewidth=2)\naxes[0].set_title('Accuracy')\naxes[0].set_xlabel('Epoch')\naxes[0].set_ylabel('Accuracy')\naxes[0].legend()\naxes[0].grid(True, alpha=0.3)\n\naxes[1].plot(history.history['loss'], label='Train Loss', linewidth=2)\naxes[1].plot(history.history['val_loss'], label='Val Loss', linewidth=2)\naxes[1].set_title('Loss')\naxes[1].set_xlabel('Epoch')\naxes[1].set_ylabel('Loss')\naxes[1].legend()\naxes[1].grid(True, alpha=0.3)\n\nplt.tight_layout()\nplt.savefig(os.path.join(WORKING_DIR, 'training_history.png'), dpi=150)\nplt.show()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-06-07T20:58:59.441030Z","iopub.execute_input":"2026-06-07T20:58:59.441336Z","iopub.status.idle":"2026-06-07T20:59:00.057714Z","shell.execute_reply.started":"2026-06-07T20:58:59.441304Z","shell.execute_reply":"2026-06-07T20:59:00.057054Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ============================================================\n# 11. EVALUATE ON VALIDATION SET\n# ============================================================\nval_loss, val_acc = model.evaluate(X_val, y_val, verbose=0)\nprint(f\"\\nValidation Loss: {val_loss:.4f}\")\nprint(f\"Validation Accuracy: {val_acc:.4f}\")\n\ny_pred = model.predict(X_val, verbose=0)\ny_pred_classes = np.argmax(y_pred, axis=1)\ny_true_classes = np.argmax(y_val, axis=1)\n\nprint(\"\\nClassification Report:\")\nprint(classification_report(y_true_classes, y_pred_classes, target_names=CLASS_NAMES))\n\n# Confusion Matrix\ncm = confusion_matrix(y_true_classes, y_pred_classes)\nplt.figure(figsize=(10, 8))\nsns.heatmap(cm, annot=True, fmt='d', cmap='Blues', xticklabels=CLASS_NAMES, yticklabels=CLASS_NAMES)\nplt.title('Confusion Matrix')\nplt.xlabel('Predicted')\nplt.ylabel('True')\nplt.tight_layout()\nplt.savefig(os.path.join(WORKING_DIR, 'confusion_matrix.png'), dpi=150)\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-06-07T20:59:00.058544Z","iopub.execute_input":"2026-06-07T20:59:00.059159Z","iopub.status.idle":"2026-06-07T20:59:03.287519Z","shell.execute_reply.started":"2026-06-07T20:59:00.059134Z","shell.execute_reply":"2026-06-07T20:59:03.286853Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ============================================================\n# 12. PREPARE KAGGLE TEST SET AND PREDICT\n# ============================================================\n# Load test image filenames from sample submission to preserve order\nsample_sub = pd.read_csv(SAMPLE_SUBMISSION)\ntest_ids = sample_sub['id'].values\n\nprint(f\"Test set size from sample submission: {len(test_ids)}\")\n\n# Load test images\ntest_images = []\nfor img_id in test_ids:\n    path = os.path.join(test_img_dir, f\"{img_id}.png\")\n    if os.path.exists(path):\n        img = load_image(path)\n        test_images.append(img)\n    else:\n        # If missing, append a blank image (should not happen)\n        test_images.append(np.zeros((IMG_SIZE, IMG_SIZE, 3), dtype=np.float32))\n\ntest_images = np.array(test_images, dtype=np.float32) / 255.0\nprint(f\"Test images shape: {test_images.shape}\")\n\n# Predict\nprint(\"Generating test predictions...\")\ntest_preds = model.predict(test_images, batch_size=BATCH_SIZE, verbose=1)\ntest_pred_labels = np.argmax(test_preds, axis=1)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-06-07T20:59:03.288561Z","iopub.execute_input":"2026-06-07T20:59:03.289257Z","iopub.status.idle":"2026-06-07T21:00:18.365469Z","shell.execute_reply.started":"2026-06-07T20:59:03.289231Z","shell.execute_reply":"2026-06-07T21:00:18.364555Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ============================================================\n# 13. CREATE SUBMISSION FILE\n# ============================================================\n\n# CREATE SUBMISSION FILE\nsample_sub = pd.read_csv(SAMPLE_SUBMISSION)\n\n# Convert predicted class indices back to class names\npred_class_names = [CLASS_NAMES[i] for i in test_pred_labels]\n\nsubmission = pd.DataFrame({\n    \"id\": sample_sub[\"id\"],\n    \"label\": pred_class_names\n})\n\nsubmission_path = os.path.join(WORKING_DIR, \"submission.csv\")\nsubmission.to_csv(submission_path, index=False)\n\nprint(f\"Submission saved to {submission_path}\")\nsubmission.head(10)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-06-07T21:35:39.276737Z","iopub.execute_input":"2026-06-07T21:35:39.277180Z","iopub.status.idle":"2026-06-07T21:35:39.611417Z","shell.execute_reply.started":"2026-06-07T21:35:39.277150Z","shell.execute_reply":"2026-06-07T21:35:39.610588Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ============================================================\n# 14. VISUALIZE SAMPLE PREDICTIONS (Optional)\n# ============================================================\nfig, axes = plt.subplots(3, 5, figsize=(15, 9))\nfig.suptitle('Sample Test Predictions')\nindices = np.random.choice(len(test_images), 15, replace=False)\nfor idx, ax in zip(indices, axes.flat):\n    ax.imshow(test_images[idx])\n    pred_label = CLASS_NAMES[test_pred_labels[idx]]\n    ax.set_title(f\"Pred: {pred_label}\", fontsize=9)\n    ax.axis('off')\nplt.tight_layout()\nplt.savefig(os.path.join(WORKING_DIR, 'sample_test_predictions.png'), dpi=150)\nplt.show()\n\nprint(\"\\nDone! Upload submission.csv to Kaggle.\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-06-07T21:00:18.404534Z","iopub.status.idle":"2026-06-07T21:00:18.404830Z","shell.execute_reply.started":"2026-06-07T21:00:18.404694Z","shell.execute_reply":"2026-06-07T21:00:18.404709Z"}},"outputs":[],"execution_count":null}]}