{"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":"gpu","dataSources":[{"sourceType":"competition","sourceId":3004,"databundleVersionId":861823}],"dockerImageVersionId":31329,"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,Conv2D ,MaxPooling2D , BatchNormalization , ReLU,MaxPooling2D,Flatten,AveragePooling2D\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,"execution":{"iopub.status.busy":"2026-04-15T06:53:25.265646Z","iopub.execute_input":"2026-04-15T06:53:25.266365Z","iopub.status.idle":"2026-04-15T06:53:25.271708Z","shell.execute_reply.started":"2026-04-15T06:53:25.266333Z","shell.execute_reply":"2026-04-15T06:53:25.270767Z"},"_kg_hide-output":true},"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-04-15T06:47:34.586780Z","iopub.execute_input":"2026-04-15T06:47:34.587246Z","iopub.status.idle":"2026-04-15T06:47:37.705921Z","shell.execute_reply.started":"2026-04-15T06:47:34.587221Z","shell.execute_reply":"2026-04-15T06:47:37.705319Z"}},"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-04-15T06:47:37.706799Z","iopub.execute_input":"2026-04-15T06:47:37.707011Z","iopub.status.idle":"2026-04-15T06:47:37.711741Z","shell.execute_reply.started":"2026-04-15T06:47:37.706990Z","shell.execute_reply":"2026-04-15T06:47:37.711049Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"x_train = x_train.values\nx_test  = x_test.values\n\nx_train = x_train.reshape(-1, 28, 28, 1)\nx_test  = x_test.reshape(-1, 28, 28, 1)\n\nprint(f\"x_train shape: {x_train.shape}\")\nprint(f\"x_test shape: {x_test.shape}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-15T06:47:37.712669Z","iopub.execute_input":"2026-04-15T06:47:37.712928Z","iopub.status.idle":"2026-04-15T06:47:37.728421Z","shell.execute_reply.started":"2026-04-15T06:47:37.712907Z","shell.execute_reply":"2026-04-15T06:47:37.727712Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# **2-Showing All Labels of Data**","metadata":{}},{"cell_type":"code","source":"import matplotlib.pyplot as plt\n\nplt.figure(figsize=(12, 5))\n\nfor i in range(10):\n    plt.subplot(2, 5, i + 1)\n    plt.imshow(x_train[i].squeeze(), cmap='gray')\n    plt.title(f\"Label: {y_train[i]}\")\n    plt.axis('off')\n\nplt.tight_layout()\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-15T06:47:37.729254Z","iopub.execute_input":"2026-04-15T06:47:37.729494Z","iopub.status.idle":"2026-04-15T06:47:38.176926Z","shell.execute_reply.started":"2026-04-15T06:47:37.729472Z","shell.execute_reply":"2026-04-15T06:47:38.176139Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# **3-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-04-15T06:47:38.178005Z","iopub.execute_input":"2026-04-15T06:47:38.178642Z","iopub.status.idle":"2026-04-15T06:47:38.353593Z","shell.execute_reply.started":"2026-04-15T06:47:38.178609Z","shell.execute_reply":"2026-04-15T06:47:38.352768Z"}},"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-04-15T06:47:38.354565Z","iopub.execute_input":"2026-04-15T06:47:38.354865Z","iopub.status.idle":"2026-04-15T06:47:38.699159Z","shell.execute_reply.started":"2026-04-15T06:47:38.354829Z","shell.execute_reply":"2026-04-15T06:47:38.698510Z"}},"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-04-15T06:47:38.700084Z","iopub.execute_input":"2026-04-15T06:47:38.700321Z","iopub.status.idle":"2026-04-15T06:47:38.706515Z","shell.execute_reply.started":"2026-04-15T06:47:38.700299Z","shell.execute_reply":"2026-04-15T06:47:38.705765Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# **5-CNN Scratch Model Structure**","metadata":{}},{"cell_type":"code","source":"model = Sequential([\n    \n    Conv2D(32 , (3,3),padding=\"valid\",input_shape=(28,28,1)),\n    BatchNormalization(),\n    ReLU(),\n    MaxPooling2D((2,2)),\n    \n    Conv2D(64 , (3,3),padding=\"same\",),\n    BatchNormalization(),\n    ReLU(),\n    MaxPooling2D((2,2)),\n    \n    Conv2D(128 , (3,3),padding=\"valid\",),\n    BatchNormalization(),\n    ReLU(),\n    MaxPooling2D((2,2)),\n\n    Flatten(),\n    \n    Dense(128),\n    BatchNormalization(),\n    ReLU(),\n    Dropout(0.5),\n    \n    Dense(10 , activation=\"softmax\")\n    \n])\nmodel.summary()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-15T06:47:38.708217Z","iopub.execute_input":"2026-04-15T06:47:38.708844Z","iopub.status.idle":"2026-04-15T06:47:39.748851Z","shell.execute_reply.started":"2026-04-15T06:47:38.708817Z","shell.execute_reply":"2026-04-15T06:47:39.748220Z"}},"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-04-15T06:47:39.749720Z","iopub.execute_input":"2026-04-15T06:47:39.749961Z","iopub.status.idle":"2026-04-15T06:47:39.761969Z","shell.execute_reply.started":"2026-04-15T06:47:39.749937Z","shell.execute_reply":"2026-04-15T06:47:39.761411Z"}},"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-04-15T06:47:39.762922Z","iopub.execute_input":"2026-04-15T06:47:39.763281Z","iopub.status.idle":"2026-04-15T06:47:39.768289Z","shell.execute_reply.started":"2026-04-15T06:47:39.763241Z","shell.execute_reply":"2026-04-15T06:47:39.767766Z"}},"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-04-15T06:47:39.769121Z","iopub.execute_input":"2026-04-15T06:47:39.769564Z","iopub.status.idle":"2026-04-15T06:48:37.030257Z","shell.execute_reply.started":"2026-04-15T06:47:39.769526Z","shell.execute_reply":"2026-04-15T06:48:37.029650Z"},"_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-04-15T06:48:37.032533Z","iopub.execute_input":"2026-04-15T06:48:37.032860Z","iopub.status.idle":"2026-04-15T06:48:38.989474Z","shell.execute_reply.started":"2026-04-15T06:48:37.032837Z","shell.execute_reply":"2026-04-15T06:48:38.988863Z"},"_kg_hide-input":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"","metadata":{}},{"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-04-15T06:48:38.990369Z","iopub.execute_input":"2026-04-15T06:48:38.990607Z","iopub.status.idle":"2026-04-15T06:48:39.246406Z","shell.execute_reply.started":"2026-04-15T06:48:38.990556Z","shell.execute_reply":"2026-04-15T06:48:39.245644Z"},"_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[random_indices]\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-04-15T07:03:49.895200Z","iopub.execute_input":"2026-04-15T07:03:49.895949Z","iopub.status.idle":"2026-04-15T07:03:51.342950Z","shell.execute_reply.started":"2026-04-15T07:03:49.895915Z","shell.execute_reply":"2026-04-15T07:03:51.342295Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# **10-Model Scratch 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_CNN.csv\", index=False)\nprint(\"submission.csv saved successfully!\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-15T07:04:33.157210Z","iopub.execute_input":"2026-04-15T07:04:33.157536Z","iopub.status.idle":"2026-04-15T07:04:35.127422Z","shell.execute_reply.started":"2026-04-15T07:04:33.157507Z","shell.execute_reply":"2026-04-15T07:04:35.126464Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# **11-LeNet-5 Structure Experment**","metadata":{}},{"cell_type":"code","source":"Le_Net_model = Sequential([\n    \n    Conv2D(6, (5,5), activation='relu', input_shape=(28,28,1)),\n    AveragePooling2D((2,2)),\n    \n    Conv2D(16, (5,5), activation='relu'),\n    AveragePooling2D((2,2)),\n    \n    Flatten(),\n    \n    Dense(120, activation='relu'),\n    Dense(84, activation='relu'),\n    Dense(10, activation='softmax')\n])\n\nmodel.summary()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-15T06:55:18.167575Z","iopub.execute_input":"2026-04-15T06:55:18.168386Z","iopub.status.idle":"2026-04-15T06:55:18.260082Z","shell.execute_reply.started":"2026-04-15T06:55:18.168355Z","shell.execute_reply":"2026-04-15T06:55:18.258487Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# **12-LeNet Compiling and CallBacks**","metadata":{}},{"cell_type":"code","source":"Le_Net_model.compile(\n    optimizer=\"adam\",\n    loss=\"categorical_crossentropy\",\n    metrics=[\"accuracy\"]\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-15T06:55:40.254940Z","iopub.execute_input":"2026-04-15T06:55:40.255731Z","iopub.status.idle":"2026-04-15T06:55:40.263428Z","shell.execute_reply.started":"2026-04-15T06:55:40.255700Z","shell.execute_reply":"2026-04-15T06:55:40.262673Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"early_stop_Le_Net_model = EarlyStopping(\n    monitor='val_loss',\n    patience=20,\n    restore_best_weights=True\n)\n\nreduce_lr_Le_Net_model = 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-04-15T06:55:40.821929Z","iopub.execute_input":"2026-04-15T06:55:40.822244Z","iopub.status.idle":"2026-04-15T06:55:40.826767Z","shell.execute_reply.started":"2026-04-15T06:55:40.822215Z","shell.execute_reply":"2026-04-15T06:55:40.825935Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# **13-LeNet Training**","metadata":{}},{"cell_type":"code","source":"history_Le_Net_model=Le_Net_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_Le_Net_model,reduce_lr_Le_Net_model])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-15T06:55:42.261282Z","iopub.execute_input":"2026-04-15T06:55:42.261911Z","iopub.status.idle":"2026-04-15T06:56:15.844499Z","shell.execute_reply.started":"2026-04-15T06:55:42.261881Z","shell.execute_reply":"2026-04-15T06:56:15.843675Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# **14-Le Net Evaluation**","metadata":{}},{"cell_type":"code","source":"y_pred = Le_Net_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-04-15T06:56:15.845684Z","iopub.execute_input":"2026-04-15T06:56:15.845964Z","iopub.status.idle":"2026-04-15T06:56:17.351335Z","shell.execute_reply.started":"2026-04-15T06:56:15.845935Z","shell.execute_reply":"2026-04-15T06:56:17.350754Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# -- Plot training vs validation accuracy --\nplt.plot(history_Le_Net_model.history['accuracy'], label='Train Accuracy')\nplt.plot(history_Le_Net_model.history['val_accuracy'], label='Val Accuracy')\n\nplt.xlim(0, len(history_Le_Net_model.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_Le_Net_model.history['loss'], label='Train Loss')\nplt.plot(history_Le_Net_model.history['val_loss'], label='Val Loss')\n\nplt.xlim(0, len(history_Le_Net_model.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-04-15T06:56:25.296751Z","iopub.execute_input":"2026-04-15T06:56:25.297058Z","iopub.status.idle":"2026-04-15T06:56:25.553008Z","shell.execute_reply.started":"2026-04-15T06:56:25.297032Z","shell.execute_reply":"2026-04-15T06:56:25.552306Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# **15-LeNet Submission**","metadata":{}},{"cell_type":"code","source":"y_test_pred = Le_Net_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_LeNet-5.csv\", index=False)\nprint(\"submission.csv saved successfully!\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-15T07:06:55.282044Z","iopub.execute_input":"2026-04-15T07:06:55.282430Z","iopub.status.idle":"2026-04-15T07:06:56.966092Z","shell.execute_reply.started":"2026-04-15T07:06:55.282399Z","shell.execute_reply":"2026-04-15T07:06:56.965346Z"}},"outputs":[],"execution_count":null}]}