{"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":[{"sourceType":"competition","sourceId":3004,"databundleVersionId":861823,"isSourceIdPinned":false}],"dockerImageVersionId":31287,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# **1-Import of Main libraries & Load Dataset**","metadata":{}},{"cell_type":"code","source":"import warnings\nwarnings.filterwarnings(\"ignore\", category=FutureWarning)\nimport numpy as np\nimport keras\nimport matplotlib.pyplot as plt\nfrom tensorflow.keras.models import Sequential\nfrom tensorflow.keras.layers import Dense, Flatten ,Dropout\nfrom tensorflow.keras.utils import to_categorical\nfrom sklearn.metrics import confusion_matrix, ConfusionMatrixDisplay, classification_report\nfrom keras.callbacks import EarlyStopping\nimport pandas as pd\nfrom sklearn.model_selection import train_test_split\nfrom tensorflow.keras.callbacks import ReduceLROnPlateau","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"_kg_hide-output":true,"execution":{"iopub.status.busy":"2026-03-06T00:06:15.225210Z","iopub.execute_input":"2026-03-06T00:06:15.225523Z","iopub.status.idle":"2026-03-06T00:06:21.001085Z","shell.execute_reply.started":"2026-03-06T00:06:15.225491Z","shell.execute_reply":"2026-03-06T00:06:21.000165Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train = pd.read_csv(\"/kaggle/input/competitions/digit-recognizer/train.csv\")\ntest = pd.read_csv(\"/kaggle/input/competitions/digit-recognizer/test.csv\")\n\nx_train = train.drop(columns=\"label\")\ny_train = train[\"label\"]\n\nx_test = test","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-06T00:06:21.003889Z","iopub.execute_input":"2026-03-06T00:06:21.004428Z","iopub.status.idle":"2026-03-06T00:06:24.383906Z","shell.execute_reply.started":"2026-03-06T00:06:21.004399Z","shell.execute_reply":"2026-03-06T00:06:24.383184Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print(f\"x_train shape: {x_train.shape}\")\nprint(f\"y_train shape: {y_train.shape}\")\nprint(f\"x_test shape: {x_test.shape}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-06T00:06:24.384840Z","iopub.execute_input":"2026-03-06T00:06:24.385083Z","iopub.status.idle":"2026-03-06T00:06:24.389657Z","shell.execute_reply.started":"2026-03-06T00:06:24.385061Z","shell.execute_reply":"2026-03-06T00:06:24.389099Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# **2-Scalling for images**","metadata":{}},{"cell_type":"code","source":"x_train = x_train.astype('float32') / 255.0\nx_test = x_test.astype('float32') / 255.0","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-06T00:06:24.390672Z","iopub.execute_input":"2026-03-06T00:06:24.391087Z","iopub.status.idle":"2026-03-06T00:06:24.576957Z","shell.execute_reply.started":"2026-03-06T00:06:24.391052Z","shell.execute_reply":"2026-03-06T00:06:24.576322Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# **3-Splitting Validation**","metadata":{}},{"cell_type":"code","source":"x_train , x_val , y_train , y_val = train_test_split(x_train ,\n                                                     y_train ,\n                                                     test_size=.2 ,\n                                                     stratify=y_train ,\n                                                     random_state=42\n                                                    )","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-06T00:06:24.577894Z","iopub.execute_input":"2026-03-06T00:06:24.578165Z","iopub.status.idle":"2026-03-06T00:06:24.793484Z","shell.execute_reply.started":"2026-03-06T00:06:24.578130Z","shell.execute_reply":"2026-03-06T00:06:24.792882Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# **4-One Hot Encoding**","metadata":{}},{"cell_type":"code","source":"y_train = to_categorical(y_train, num_classes=10)\ny_val   = to_categorical(y_val, num_classes=10)\nprint(f\"x_train shape: {x_train.shape}\")\nprint(f\"y_train shape: {y_train.shape}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-06T00:06:24.794480Z","iopub.execute_input":"2026-03-06T00:06:24.794707Z","iopub.status.idle":"2026-03-06T00:06:24.800860Z","shell.execute_reply.started":"2026-03-06T00:06:24.794685Z","shell.execute_reply":"2026-03-06T00:06:24.800218Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# **5-Model Architecture**","metadata":{}},{"cell_type":"code","source":"model = Sequential([\n    Dense(1024 , activation=\"relu\" , input_shape=(784,)),\n    Dropout(0.4),\n    Dense(512 , activation=\"relu\"),\n    Dropout(0.4),\n    Dense(256 , activation=\"relu\"),\n    Dropout(0.3),\n    Dense(128 , activation=\"relu\"),\n    Dropout(0.3),\n    Dense(64 , activation=\"relu\"),\n    Dense(32 , activation=\"relu\"),\n    Dense(10 , activation=\"softmax\")\n    \n])\nmodel.summary()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-06T00:06:24.801595Z","iopub.execute_input":"2026-03-06T00:06:24.801839Z","iopub.status.idle":"2026-03-06T00:06:26.374891Z","shell.execute_reply.started":"2026-03-06T00:06:24.801818Z","shell.execute_reply":"2026-03-06T00:06:26.374279Z"},"_kg_hide-output":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# **6-Compiling & CallBacks**","metadata":{}},{"cell_type":"code","source":"model.compile(\n    optimizer=\"adam\",\n    loss=\"categorical_crossentropy\",\n    metrics=[\"accuracy\"]\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-06T00:06:26.375646Z","iopub.execute_input":"2026-03-06T00:06:26.375904Z","iopub.status.idle":"2026-03-06T00:06:26.387115Z","shell.execute_reply.started":"2026-03-06T00:06:26.375864Z","shell.execute_reply":"2026-03-06T00:06:26.386512Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"early_stop = EarlyStopping(\n    monitor='val_loss',\n    patience=20,\n    restore_best_weights=True\n)\n\nreduce_lr = ReduceLROnPlateau(\n    monitor='val_loss',\n    factor=0.5,\n    patience=2,\n    min_lr=1e-6,\n    verbose=1\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-06T00:06:26.387896Z","iopub.execute_input":"2026-03-06T00:06:26.388087Z","iopub.status.idle":"2026-03-06T00:06:26.392107Z","shell.execute_reply.started":"2026-03-06T00:06:26.388068Z","shell.execute_reply":"2026-03-06T00:06:26.391357Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# **7-Model Training**","metadata":{}},{"cell_type":"code","source":"history=model.fit(x_train,\n                  y_train,\n                 epochs=50,\n                 validation_data=(x_val, y_val),\n                 batch_size=128,\n                 callbacks=[early_stop,reduce_lr])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-06T00:06:26.393059Z","iopub.execute_input":"2026-03-06T00:06:26.393420Z","iopub.status.idle":"2026-03-06T00:07:10.793927Z","shell.execute_reply.started":"2026-03-06T00:06:26.393397Z","shell.execute_reply":"2026-03-06T00:07:10.793285Z"},"_kg_hide-output":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# **8-Evaluation and Confusion matrix**","metadata":{}},{"cell_type":"code","source":"y_pred = model.predict(x_val)\npredicted_labels = np.argmax(y_pred, axis=1)\ntrue_labels      = np.argmax(y_val, axis=1)\n\n# ===== Confusion Matrix =====\ncm = confusion_matrix(true_labels, predicted_labels)\nplt.figure(figsize=(10, 8))\ndisp = ConfusionMatrixDisplay(confusion_matrix=cm)\ndisp.plot(cmap='Blues', xticks_rotation='vertical')\nplt.title(\"Confusion Matrix\")\nplt.show()\n\n# ===== Classification Report =====\nreport = classification_report(true_labels, predicted_labels)\nprint(\"Classification Report:\\n\")\nprint(report)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-06T00:07:10.794854Z","iopub.execute_input":"2026-03-06T00:07:10.795161Z","iopub.status.idle":"2026-03-06T00:07:12.699630Z","shell.execute_reply.started":"2026-03-06T00:07:10.795124Z","shell.execute_reply":"2026-03-06T00:07:12.698888Z"},"_kg_hide-input":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# -- Plot training vs validation accuracy --\nplt.plot(history.history['accuracy'], label='Train Accuracy')\nplt.plot(history.history['val_accuracy'], label='Val Accuracy')\n\nplt.xlim(0, len(history.history['accuracy']))\nplt.ylim(0.8, 1)\n\nplt.legend()\nplt.title('Accuracy over epochs')\nplt.xlabel('Epochs')\nplt.ylabel('Accuracy')\nplt.show()\n\n\n# -- Plot training vs validation loss --\nplt.plot(history.history['loss'], label='Train Loss')\nplt.plot(history.history['val_loss'], label='Val Loss')\n\nplt.xlim(0, len(history.history['loss']))\n\nplt.legend()\nplt.title('Loss over epochs')\nplt.xlabel('Epochs')\nplt.ylabel('Loss')\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-06T00:07:12.700697Z","iopub.execute_input":"2026-03-06T00:07:12.701011Z","iopub.status.idle":"2026-03-06T00:07:12.974371Z","shell.execute_reply.started":"2026-03-06T00:07:12.700982Z","shell.execute_reply":"2026-03-06T00:07:12.973705Z"},"_kg_hide-input":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# **9-Test Model With Images**","metadata":{}},{"cell_type":"code","source":"num_images = 10\nrandom_indices = np.random.choice(len(x_val), size=num_images, replace=False)\n\nX_input = x_val.iloc[random_indices].to_numpy()\n\n\nif y_val.ndim == 2:\n    y_true_labels = np.argmax(y_val[random_indices], axis=1)\nelse:\n    y_true_labels = y_val[random_indices]\n\n\nplt.figure(figsize=(20,5))\nfor i in range(num_images):\n    plt.subplot(1, num_images, i+1)\n    plt.imshow(X_input[i].reshape(28,28), cmap='gray')\n    plt.title(f\"True: {y_true_labels[i]}\")\n    plt.axis('off')\nplt.tight_layout()\nplt.show()\n\nfor i in range(num_images):\n    print(f\"\\nImage {i+1} (True: {y_true_labels[i]}):\")\n    y_pred = model.predict(X_input[i:i+1], verbose=0)\n    pred_class = np.argmax(y_pred, axis=1)[0]\n    emoji = \"✅\" if pred_class == y_true_labels[i] else \"❌\"\n    print(f\"  MLP predicts: {pred_class} {emoji}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-06T00:07:12.976549Z","iopub.execute_input":"2026-03-06T00:07:12.976965Z","iopub.status.idle":"2026-03-06T00:07:14.619705Z","shell.execute_reply.started":"2026-03-06T00:07:12.976942Z","shell.execute_reply":"2026-03-06T00:07:14.618898Z"},"_kg_hide-input":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# **Submission**","metadata":{}},{"cell_type":"code","source":"y_test_pred = model.predict(x_test, verbose=0)\npredicted_labels = np.argmax(y_test_pred, axis=1)\n\nsubmission = pd.DataFrame({\n    \"ImageId\": np.arange(1,len(predicted_labels)+1),\n    \"Label\": predicted_labels\n})\n\n# ====== حفظ CSV ======\nsubmission.to_csv(\"submission.csv\", index=False)\nprint(\"submission.csv saved successfully!\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-06T00:07:14.620881Z","iopub.execute_input":"2026-03-06T00:07:14.621226Z","iopub.status.idle":"2026-03-06T00:07:16.503979Z","shell.execute_reply.started":"2026-03-06T00:07:14.621192Z","shell.execute_reply":"2026-03-06T00:07:16.503221Z"}},"outputs":[],"execution_count":null}]}