{"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":16017,"databundleVersionId":708189,"sourceType":"competition"}],"dockerImageVersionId":31089,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"# ==============================\n# Assignment 1 - Kannada MNIST\n# Neural Network (Fully Connected)\n# Author: Tinsae Abdeta\n# ==============================\n\nimport numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\nimport seaborn as sns\n\nfrom sklearn.model_selection import train_test_split\nfrom tensorflow.keras.models import Sequential\nfrom tensorflow.keras.layers import Dense, Input\nfrom tensorflow.keras.utils import to_categorical\nfrom sklearn.metrics import confusion_matrix, classification_report\n\n# --------------------------\n# 1. Load the dataset (Kaggle path)\n# --------------------------\ntrain_df = pd.read_csv(\"/kaggle/input/Kannada-MNIST/train.csv\")\ntest_df  = pd.read_csv(\"/kaggle/input/Kannada-MNIST/test.csv\")\n\n# Training features and labels\nX = train_df.drop(\"label\", axis=1).values\ny = train_df[\"label\"].values\n\n# Handle test set (drop 'id' if present)\nif \"id\" in test_df.columns:\n    X_test = test_df.drop(\"id\", axis=1).values\nelse:\n    X_test = test_df.values\n\nprint(\"Train shape:\", X.shape)\nprint(\"Test shape:\", X_test.shape)\n\n# --------------------------\n# 2. Preprocess the data\n# --------------------------\n# Normalize pixel values to [0,1]\nX = X / 255.0\nX_test = X_test / 255.0\n\n# Split train/validation\nX_train, X_val, y_train, y_val = train_test_split(\n    X, y, test_size=0.2, random_state=42, stratify=y\n)\n\n# One-hot encode labels\ny_train_encoded = to_categorical(y_train, num_classes=10)\ny_val_encoded   = to_categorical(y_val, num_classes=10)\n\n# --------------------------\n# 3. Build the model\n# --------------------------\nmodel = Sequential([\n    Input(shape=(784,)),  # Explicit input layer\n    Dense(256, activation='relu'),\n    Dense(128, activation='relu'),\n    Dense(10, activation='softmax')  # 10 classes (digits 0–9)\n])\n\nmodel.compile(\n    loss='categorical_crossentropy',\n    optimizer='adam',\n    metrics=['accuracy']\n)\n\nmodel.summary()\n\n# --------------------------\n# 4. Train the model\n# --------------------------\nhistory = model.fit(\n    X_train, y_train_encoded,\n    validation_data=(X_val, y_val_encoded),\n    epochs=20,\n    batch_size=128,\n    verbose=2\n)\n\n# --------------------------\n# 5. Evaluate performance\n# --------------------------\nval_loss, val_acc = model.evaluate(X_val, y_val_encoded, verbose=0)\nprint(f\"Validation accuracy: {val_acc:.4f}\")\n\n# Plot accuracy and loss\nplt.figure(figsize=(12,5))\nplt.subplot(1,2,1)\nplt.plot(history.history['accuracy'], label='Train')\nplt.plot(history.history['val_accuracy'], label='Validation')\nplt.title(\"Model Accuracy\")\nplt.xlabel(\"Epochs\"); plt.ylabel(\"Accuracy\")\nplt.legend()\n\nplt.subplot(1,2,2)\nplt.plot(history.history['loss'], label='Train')\nplt.plot(history.history['val_loss'], label='Validation')\nplt.title(\"Model Loss\")\nplt.xlabel(\"Epochs\"); plt.ylabel(\"Loss\")\nplt.legend()\nplt.show()\n\n# Confusion matrix on validation set\ny_val_pred = np.argmax(model.predict(X_val), axis=1)\nconf_matrix = confusion_matrix(y_val, y_val_pred)\n\nplt.figure(figsize=(6,5))\nsns.heatmap(conf_matrix, annot=True, fmt=\"d\", cmap=\"Blues\")\nplt.xlabel(\"Predicted\")\nplt.ylabel(\"True\")\nplt.title(\"Validation Confusion Matrix\")\nplt.show()\n\nprint(\"Classification Report:\\n\", classification_report(y_val, y_val_pred))\n\n# --------------------------\n# 6. Kaggle Submission\n# --------------------------\npred_probs = model.predict(X_test)\npred_labels = np.argmax(pred_probs, axis=1)\n\n# If test set has 'id' column, use it, else generate sequential IDs\nif \"id\" in test_df.columns:\n    submission = pd.DataFrame({\n        \"id\": test_df[\"id\"],\n        \"label\": pred_labels\n    })\nelse:\n    submission = pd.DataFrame({\n        \"id\": np.arange(len(pred_labels)),\n        \"label\": pred_labels\n    })\n\nsubmission.to_csv(\"submission.csv\", index=False)\nprint(\"Saved submission.csv for Kaggle upload!\")\n","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2025-09-13T02:36:27.264231Z","iopub.execute_input":"2025-09-13T02:36:27.264526Z","iopub.status.idle":"2025-09-13T02:37:43.565013Z","shell.execute_reply.started":"2025-09-13T02:36:27.264474Z","shell.execute_reply":"2025-09-13T02:37:43.564121Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"","metadata":{}}]}