{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.11.13","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"none","dataSources":[{"sourceId":3004,"databundleVersionId":861823,"sourceType":"competition"}],"dockerImageVersionId":31192,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"# ==============================\n# Digit Recognizer - Deep CNN with Augmentation\n# Target: push past ~99% accuracy\n# ==============================\n\nimport numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\n\nimport tensorflow as tf\nfrom tensorflow.keras import layers, models\nfrom tensorflow.keras.preprocessing.image import ImageDataGenerator\nfrom sklearn.model_selection import train_test_split\n\nprint(\"TensorFlow version:\", tf.__version__)\n\n# ---------------------------\n# 1. Load Kaggle competition data\n# ---------------------------\n\ntrain_path = \"/kaggle/input/digit-recognizer/train.csv\"\ntest_path  = \"/kaggle/input/digit-recognizer/test.csv\"\n\ntrain_df = pd.read_csv(train_path)\ntest_df  = pd.read_csv(test_path)\n\n# Split into features and labels\ny_train = train_df[\"label\"].values\nx_train = train_df.drop(\"label\", axis=1).values\nx_test  = test_df.values\n\nprint(\"Raw x_train shape:\", x_train.shape)  # (42000, 784)\nprint(\"Raw x_test shape:\", x_test.shape)    # (28000, 784)\n\n# ---------------------------\n# 2. Reshape and normalize\n# ---------------------------\n\n# Reshape from (N, 784) -> (N, 28, 28)\nx_train = x_train.reshape(-1, 28, 28)\nx_test  = x_test.reshape(-1, 28, 28)\n\n# Normalize to [0, 1]\nx_train = x_train.astype(\"float32\") / 255.0\nx_test  = x_test.astype(\"float32\") / 255.0\n\n# Add channel dimension: (28, 28) -> (28, 28, 1)\nx_train = np.expand_dims(x_train, -1)\nx_test  = np.expand_dims(x_test, -1)\n\nprint(\"Processed x_train shape:\", x_train.shape)  # (42000, 28, 28, 1)\nprint(\"Processed x_test shape:\", x_test.shape)    # (28000, 28, 28, 1)\n\n# ---------------------------\n# 3. (Optional) visualize a few digits\n# ---------------------------\n\nplt.figure(figsize=(6, 6))\nindices = np.random.choice(len(x_train), 9, replace=False)\nfor i, idx in enumerate(indices):\n    plt.subplot(3, 3, i + 1)\n    plt.imshow(x_train[idx].squeeze(), cmap='gray')\n    plt.title(f\"Label: {y_train[idx]}\")\n    plt.axis('off')\nplt.tight_layout()\nplt.show()\n\n# ---------------------------\n# 4. Train/validation split\n# ---------------------------\n\nx_train_sub, x_val, y_train_sub, y_val = train_test_split(\n    x_train,\n    y_train,\n    test_size=0.1,\n    random_state=42,\n    stratify=y_train\n)\n\nprint(\"Train subset shape:\", x_train_sub.shape)\nprint(\"Validation shape:\", x_val.shape)\n\n# ---------------------------\n# 5. Data augmentation setup\n# ---------------------------\n\ndatagen = ImageDataGenerator(\n    rotation_range=10,\n    width_shift_range=0.1,\n    height_shift_range=0.1,\n    zoom_range=0.1\n    # you can add shear_range=0.1 if you want\n)\n\ndatagen.fit(x_train_sub)\n\n# ---------------------------\n# 6. Deeper CNN model (added layers, BN, Dropout)\n# ---------------------------\n\nmodel = models.Sequential([\n    layers.Input(shape=(28, 28, 1)),\n\n    # --- Block 1 ---\n    layers.Conv2D(32, (3, 3), padding='same', activation='relu'),\n    layers.BatchNormalization(),\n    layers.Conv2D(32, (3, 3), padding='same', activation='relu'),\n    layers.BatchNormalization(),\n    layers.MaxPooling2D((2, 2)),\n    layers.Dropout(0.25),\n\n    # --- Block 2 ---\n    layers.Conv2D(64, (3, 3), padding='same', activation='relu'),\n    layers.BatchNormalization(),\n    layers.Conv2D(64, (3, 3), padding='same', activation='relu'),\n    layers.BatchNormalization(),\n    layers.MaxPooling2D((2, 2)),\n    layers.Dropout(0.25),\n\n    # --- Block 3 \n    layers.Conv2D(128, (3, 3), padding='same', activation='relu'),\n    layers.BatchNormalization(),\n    layers.MaxPooling2D((2, 2)),\n    layers.Dropout(0.25),\n\n    # --- Classifier ---\n    layers.Flatten(),\n    layers.Dense(256, activation='relu'),\n    layers.BatchNormalization(),\n    layers.Dropout(0.5),\n    layers.Dense(10, activation='softmax')\n])\n\nmodel.summary()\n\n# ---------------------------\n# 7. Compile and train (with augmentation)\n# ---------------------------\n\nmodel.compile(\n    optimizer='adam',\n    loss='sparse_categorical_crossentropy',\n    metrics=['accuracy']\n)\n\nbatch_size = 128\nepochs = 20  \nhistory = model.fit(\n    datagen.flow(x_train_sub, y_train_sub, batch_size=batch_size),\n    epochs=epochs,\n    validation_data=(x_val, y_val),\n    verbose=1\n)\n\n# Optional: print final val accuracy\nval_loss, val_acc = model.evaluate(x_val, y_val, verbose=0)\nprint(\"Final validation accuracy:\", val_acc)\n\n# ---------------------------\n# 8. Predict on Kaggle test set and create submission.csv\n# ---------------------------\n\npredictions = model.predict(x_test)\npred_labels = np.argmax(predictions, axis=1)\n\nsubmission = pd.DataFrame({\n    \"ImageId\": np.arange(1, len(pred_labels) + 1),\n    \"Label\": pred_labels\n})\n\nsubmission.to_csv(\"submission.csv\", index=False)\nprint(\"submission.csv saved with shape:\", submission.shape)\n","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2025-12-04T21:58:05.369366Z","iopub.execute_input":"2025-12-04T21:58:05.369645Z"}},"outputs":[],"execution_count":null}]}