{"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":[{"sourceId":84896,"databundleVersionId":10305135,"sourceType":"competition"}],"dockerImageVersionId":31234,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"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","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2025-12-24T00:10:59.937818Z","iopub.execute_input":"2025-12-24T00:10:59.938133Z","iopub.status.idle":"2025-12-24T00:10:59.94617Z","shell.execute_reply.started":"2025-12-24T00:10:59.938106Z","shell.execute_reply":"2025-12-24T00:10:59.945477Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## 1 Data Loading","metadata":{}},{"cell_type":"code","source":"import pandas as pd\n\ntrain = pd.read_csv(\"/kaggle/input/playground-series-s4e12/train.csv\")\ntest  = pd.read_csv(\"/kaggle/input/playground-series-s4e12/test.csv\")\nsample = pd.read_csv(\"/kaggle/input/playground-series-s4e12/sample_submission.csv\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-24T00:10:59.94745Z","iopub.execute_input":"2025-12-24T00:10:59.947719Z","iopub.status.idle":"2025-12-24T00:11:07.415807Z","shell.execute_reply.started":"2025-12-24T00:10:59.947698Z","shell.execute_reply":"2025-12-24T00:11:07.414927Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## 2 Dadta Overview","metadata":{}},{"cell_type":"code","source":"train.head()\ntrain.info()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-24T00:11:07.416832Z","iopub.execute_input":"2025-12-24T00:11:07.417076Z","iopub.status.idle":"2025-12-24T00:11:08.032113Z","shell.execute_reply.started":"2025-12-24T00:11:07.417046Z","shell.execute_reply":"2025-12-24T00:11:08.031369Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"يحتوي ملف train على 1,200,000 سجل و 21 عمودًا.\n\nالمتغير الهدف هو: Premium Amount (متغير عددي مستمر → Regression).\n\nأنواع البيانات:\n\nNumerical: 9 أعمدة (float + int)\n\nCategorical: 11 أعمدة (object)\n\nحجم البيانات كبير نسبيًا (~192 MB)، مما يتطلب معالجة فعّالة.\n\n📌 Missing Values\n\nتوجد قيم مفقودة في عدة أعمدة مهمة مثل:\n\nAge\n\nAnnual Income\n\nNumber of Dependents\n\nHealth Score\n\nPrevious Claims\n\nCredit Score\n\nلا توجد قيم مفقودة في المتغير الهدف Premium Amount ✅ (نقطة قوة).\n\n\nالداتا غنية ومتنوعة (سلوك، صحة، دخل، نمط حياة).\n\nوجود أعمدة فئوية كثيرة → Encoding سيكون خطوة محورية.\n\nوجود تاريخ (Policy Start Date) → يمكن استخراج Features زمنية لاحقًا.\n\nبما أن التقييم RMSLE، يجب الانتباه للتعامل مع القيم المتطرفة.","metadata":{}},{"cell_type":"markdown","source":"## 3 Exploratory Data Analysis","metadata":{}},{"cell_type":"code","source":"train[\"Premium Amount\"].describe()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-24T00:11:08.033856Z","iopub.execute_input":"2025-12-24T00:11:08.034107Z","iopub.status.idle":"2025-12-24T00:11:08.080702Z","shell.execute_reply.started":"2025-12-24T00:11:08.034084Z","shell.execute_reply":"2025-12-24T00:11:08.080081Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import matplotlib.pyplot as plt\nimport seaborn as sns\n\nsns.histplot(train[\"Premium Amount\"], bins=50)\nplt.show()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-24T00:11:08.081518Z","iopub.execute_input":"2025-12-24T00:11:08.081734Z","iopub.status.idle":"2025-12-24T00:11:09.821134Z","shell.execute_reply.started":"2025-12-24T00:11:08.081714Z","shell.execute_reply":"2025-12-24T00:11:09.820541Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"missing = train.isnull().sum().sort_values(ascending=False)\nmissing[missing > 0]\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-24T00:11:09.821959Z","iopub.execute_input":"2025-12-24T00:11:09.822291Z","iopub.status.idle":"2025-12-24T00:11:10.423862Z","shell.execute_reply.started":"2025-12-24T00:11:09.822268Z","shell.execute_reply":"2025-12-24T00:11:10.423077Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"num_cols = train.select_dtypes(include=[\"int64\", \"float64\"]).columns\ncat_cols = train.select_dtypes(include=[\"object\"]).columns\n\nnum_cols, cat_cols\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-24T00:11:10.424723Z","iopub.execute_input":"2025-12-24T00:11:10.424953Z","iopub.status.idle":"2025-12-24T00:11:10.609174Z","shell.execute_reply.started":"2025-12-24T00:11:10.424932Z","shell.execute_reply":"2025-12-24T00:11:10.608433Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"تم تحميل البيانات وفحص بنيتها بشكل كامل باستخدام info و describe.\n\nالمتغير الهدف Premium Amount يُظهر توزيعًا منحرفًا لليمين، مما يشير إلى الحاجة لتحويل لوغاريتمي لاحقًا.\n\nالتحليل الاستكشافي أوضح وجود تباين مرتفع وقيم متطرفة في القيم العليا.\n\nتم اكتشاف قيم مفقودة بعدة متغيرات رقمية وفئوية بنسب مؤثرة.\n\nجرى تصنيف المتغيرات إلى رقمية و فئوية تمهيدًا لمعالجتها بشكل مناسب.\n\nنتائج EDA تؤكد ضرورة تنفيذ خطوات تنظيف بيانات منظمة قبل النمذجة.\n\nهذه المرحلة تمثل نقطة الانتقال من التحليل الاستكشافي إلى تنظيف البيانات وبناء الميزات.","metadata":{}},{"cell_type":"markdown","source":"## 4 Data Cleaning ","metadata":{}},{"cell_type":"code","source":"num_cols = num_cols.drop(['Premium Amount', 'id'])\nnum_cols\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-24T00:11:10.610215Z","iopub.execute_input":"2025-12-24T00:11:10.610592Z","iopub.status.idle":"2025-12-24T00:11:10.616517Z","shell.execute_reply.started":"2025-12-24T00:11:10.610563Z","shell.execute_reply":"2025-12-24T00:11:10.6156Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"for col in num_cols:\n    median_value = train[col].median()\n    train[col].fillna(median_value, inplace=True)\n    test[col].fillna(median_value, inplace=True)\ntrain[num_cols].isnull().sum()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-24T00:11:10.617322Z","iopub.execute_input":"2025-12-24T00:11:10.617637Z","iopub.status.idle":"2025-12-24T00:11:10.847233Z","shell.execute_reply.started":"2025-12-24T00:11:10.617606Z","shell.execute_reply":"2025-12-24T00:11:10.846693Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"1️⃣ Handling Missing Values\n\nتم التعامل مع القيم المفقودة بطريقة مناسبة لطبيعة البيانات:\n\nالمتغيرات الرقمية تم تعويض القيم المفقودة فيها باستخدام الوسيط (Median) لتقليل تأثير القيم المتطرفة.\n\nالمتغيرات الفئوية (Categorical) تم تعويض القيم المفقودة فيها بالقيمة \"Unknown\" للحفاظ على جميع السجلات.\n\nبعد المعالجة، لم يعد هناك أي قيم مفقودة في البيانات.","metadata":{}},{"cell_type":"code","source":"for col in cat_cols:\n    train[col].fillna(\"Unknown\", inplace=True)\n    test[col].fillna(\"Unknown\", inplace=True)\ntrain[cat_cols].isnull().sum()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-24T00:11:10.849913Z","iopub.execute_input":"2025-12-24T00:11:10.850153Z","iopub.status.idle":"2025-12-24T00:11:12.824134Z","shell.execute_reply.started":"2025-12-24T00:11:10.85013Z","shell.execute_reply":"2025-12-24T00:11:12.823516Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"2️⃣ Data Type Correction & Feature Engineering\n\nتم تحويل متغير Policy Start Date إلى نوع تاريخ (datetime).\n\nتم استخراج ميزات جديدة مفيدة للنمذجة:\n\nPolicy Start Year\n\nPolicy Start Month\n\nبعد استخراج الميزات، تم حذف عمود التاريخ الأصلي لتفادي استخدام بيانات غير رقمية في النماذ","metadata":{}},{"cell_type":"code","source":"train[\"Policy Start Date\"] = pd.to_datetime(train[\"Policy Start Date\"])\ntest[\"Policy Start Date\"] = pd.to_datetime(test[\"Policy Start Date\"])\n\ntrain[\"Policy Start Year\"] = train[\"Policy Start Date\"].dt.year\ntrain[\"Policy Start Month\"] = train[\"Policy Start Date\"].dt.month\n\ntest[\"Policy Start Year\"] = test[\"Policy Start Date\"].dt.year\ntest[\"Policy Start Month\"] = test[\"Policy Start Date\"].dt.month\n\ntrain.drop(columns=[\"Policy Start Date\"], inplace=True)\ntest.drop(columns=[\"Policy Start Date\"], inplace=True)\ntrain[[\"Policy Start Year\", \"Policy Start Month\"]].head()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-24T00:11:12.825071Z","iopub.execute_input":"2025-12-24T00:11:12.825327Z","iopub.status.idle":"2025-12-24T00:11:13.986291Z","shell.execute_reply.started":"2025-12-24T00:11:12.825296Z","shell.execute_reply":"2025-12-24T00:11:13.985693Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"3️⃣ Feature Selection (Initial Cleaning)\n\nتم حذف الأعمدة غير المفيدة للنمذجة:\n\nid لأنه معرّف فقط ولا يحمل قيمة تنبؤية.\n\nPremium Amount من مجموعة الخصائص لأنه المتغير الهدف.\n\nتم فصل المتغيرات إلى:\n\nمتغيرات رقمية (Numerical)\n\nمتغيرات فئوية (Categorical)\n\nالبيانات الآن نظيفة، متسقة، وجاهزة لمرحلة Encoding و Modeling.","metadata":{}},{"cell_type":"code","source":"cat_cols = train.select_dtypes(include=[\"object\"]).columns\ncat_cols\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-24T00:11:13.987115Z","iopub.execute_input":"2025-12-24T00:11:13.987393Z","iopub.status.idle":"2025-12-24T00:11:14.482197Z","shell.execute_reply.started":"2025-12-24T00:11:13.987357Z","shell.execute_reply":"2025-12-24T00:11:14.481505Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## 5 One-Hot Encoding categorical columns","metadata":{}},{"cell_type":"code","source":"train_encoded = pd.get_dummies(train, columns=cat_cols, drop_first=True)\ntest_encoded  = pd.get_dummies(test,  columns=cat_cols, drop_first=True)\ntrain_encoded.shape, test_encoded.shape\n\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-24T00:11:14.483175Z","iopub.execute_input":"2025-12-24T00:11:14.483729Z","iopub.status.idle":"2025-12-24T00:11:16.15402Z","shell.execute_reply.started":"2025-12-24T00:11:14.483705Z","shell.execute_reply":"2025-12-24T00:11:16.153416Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_encoded, test_encoded = train_encoded.align(\n    test_encoded,\n    join='left',\n    axis=1,\n    fill_value=0\n)\n\ntrain_encoded.shape, test_encoded.shape\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-24T00:11:16.154747Z","iopub.execute_input":"2025-12-24T00:11:16.154954Z","iopub.status.idle":"2025-12-24T00:11:16.255474Z","shell.execute_reply.started":"2025-12-24T00:11:16.154935Z","shell.execute_reply":"2025-12-24T00:11:16.2548Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"بعد One-Hot Encoding ممكن يصير اختلاف بالأعمدة لأن في فئات ظهرت في Train وما ظهرت في Test.\nلذلك عملنا Column Alignment حتى يصير عندنا نفس الـ feature space:","metadata":{}},{"cell_type":"markdown","source":"##  6 odeling (Regression","metadata":{}},{"cell_type":"code","source":"X = train_encoded.drop(columns=[\"Premium Amount\"])\ny = train_encoded[\"Premium Amount\"]\n\nX_test_final = test_encoded.copy()\n\nX.shape, y.shape, X_test_final.shape\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-24T00:11:16.256246Z","iopub.execute_input":"2025-12-24T00:11:16.256502Z","iopub.status.idle":"2025-12-24T00:11:16.347622Z","shell.execute_reply.started":"2025-12-24T00:11:16.256469Z","shell.execute_reply":"2025-12-24T00:11:16.34686Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"\"Premium Amount\" in test_encoded.columns","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-24T00:11:16.348481Z","iopub.execute_input":"2025-12-24T00:11:16.348721Z","iopub.status.idle":"2025-12-24T00:11:16.353613Z","shell.execute_reply.started":"2025-12-24T00:11:16.3487Z","shell.execute_reply":"2025-12-24T00:11:16.352893Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"لازم عمود الهدف Premium Amount يكون موجود فقط في train وليس في test.\nإذا ظهر في test فهذا يعني Data Leakage (تسريب معلومات الهدف)، ويؤدي لتقييم مضلل أو خطأ في الـ submission.\nلذلك نحذفه فورًا من test قبل التدريب/التنبؤ.","metadata":{}},{"cell_type":"code","source":"X_test_final = test_encoded.drop(columns=[\"Premium Amount\"])\nX_test_final.shape\n\n\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-24T00:11:16.354513Z","iopub.execute_input":"2025-12-24T00:11:16.354766Z","iopub.status.idle":"2025-12-24T00:11:16.402062Z","shell.execute_reply.started":"2025-12-24T00:11:16.354735Z","shell.execute_reply":"2025-12-24T00:11:16.401431Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"X.shape, X_test_final.shape\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-24T00:11:16.402866Z","iopub.execute_input":"2025-12-24T00:11:16.403135Z","iopub.status.idle":"2025-12-24T00:11:16.408757Z","shell.execute_reply.started":"2025-12-24T00:11:16.403107Z","shell.execute_reply":"2025-12-24T00:11:16.408045Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"set(X.columns) == set(X_test_final.columns)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-24T00:11:16.409592Z","iopub.execute_input":"2025-12-24T00:11:16.409806Z","iopub.status.idle":"2025-12-24T00:11:16.419944Z","shell.execute_reply.started":"2025-12-24T00:11:16.409787Z","shell.execute_reply":"2025-12-24T00:11:16.419229Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## 7 Train/Validation split","metadata":{}},{"cell_type":"code","source":"from sklearn.model_selection import train_test_split\n\nX_train, X_val, y_train, y_val = train_test_split(\n    X, y, test_size=0.2, random_state=42\n)\n\nX_train.shape, X_val.shape, y_train.shape, y_val.shape\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-24T00:11:16.420817Z","iopub.execute_input":"2025-12-24T00:11:16.421043Z","iopub.status.idle":"2025-12-24T00:11:16.843728Z","shell.execute_reply.started":"2025-12-24T00:11:16.421014Z","shell.execute_reply":"2025-12-24T00:11:16.842958Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import numpy as np\n\ndef rmsle(y_true, y_pred):\n    y_pred = np.maximum(y_pred, 0)  # تمنع القيم السالبة (مهم)\n    return np.sqrt(np.mean((np.log1p(y_pred) - np.log1p(y_true))**2))\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-24T00:11:16.844646Z","iopub.execute_input":"2025-12-24T00:11:16.845625Z","iopub.status.idle":"2025-12-24T00:11:16.849253Z","shell.execute_reply.started":"2025-12-24T00:11:16.845597Z","shell.execute_reply":"2025-12-24T00:11:16.848595Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from sklearn.linear_model import Ridge\n\nmodel = Ridge(alpha=1.0, random_state=42)\nmodel.fit(X_train, y_train)\n\nval_pred = model.predict(X_val)\nprint(\"RMSLE:\", rmsle(y_val, val_pred))\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-24T00:11:16.850148Z","iopub.execute_input":"2025-12-24T00:11:16.85047Z","iopub.status.idle":"2025-12-24T00:11:17.524992Z","shell.execute_reply.started":"2025-12-24T00:11:16.850446Z","shell.execute_reply":"2025-12-24T00:11:17.524299Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## 8 LightGBM (Baseline)","metadata":{}},{"cell_type":"code","source":"from lightgbm import LGBMRegressor\n\nlgb_model = LGBMRegressor(\n    n_estimators=300,\n    learning_rate=0.05,\n    max_depth=-1,\n    num_leaves=31,\n    random_state=42,\n    n_jobs=-1\n)\n\nlgb_model.fit(X_train, y_train)\n\nval_pred_lgb = lgb_model.predict(X_val)\n\nprint(\"RMSLE (LightGBM):\", rmsle(y_val, val_pred_lgb))\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-24T00:11:17.526068Z","iopub.execute_input":"2025-12-24T00:11:17.526923Z","iopub.status.idle":"2025-12-24T00:11:33.938043Z","shell.execute_reply.started":"2025-12-24T00:11:17.52689Z","shell.execute_reply":"2025-12-24T00:11:33.93729Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import numpy as np\nfrom sklearn.model_selection import train_test_split\n\n# 1) target log\ny_log = np.log1p(y)\n\n# 2) split على y_log\nX_train, X_val, y_train_log, y_val_log = train_test_split(\n    X, y_log, test_size=0.2, random_state=42\n)\n\nX_train.shape, X_val.shape, y_train_log.shape, y_val_log.shape\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-24T00:11:33.939361Z","iopub.execute_input":"2025-12-24T00:11:33.940017Z","iopub.status.idle":"2025-12-24T00:11:34.199379Z","shell.execute_reply.started":"2025-12-24T00:11:33.939988Z","shell.execute_reply":"2025-12-24T00:11:34.198596Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from lightgbm import LGBMRegressor\nimport numpy as np\n\n# RMSLE على القيم الأصلية\ndef rmsle_original(y_true, y_pred):\n    y_pred = np.maximum(y_pred, 0)\n    return np.sqrt(np.mean((np.log1p(y_pred) - np.log1p(y_true))**2))\n\nlgb_model = LGBMRegressor(\n    n_estimators=2000,\n    learning_rate=0.05,\n    num_leaves=64,\n    max_depth=-1,\n    subsample=0.8,\n    colsample_bytree=0.8,\n    random_state=42,\n    n_jobs=-1\n)\n\n# تدريب على اللوغ\nlgb_model.fit(X_train, y_train_log)\n\n# تنبؤ على اللوغ\nval_pred_log = lgb_model.predict(X_val)\n\n# رجّع للأصل\nval_pred = np.expm1(val_pred_log)\ny_val_original = np.expm1(y_val_log)\n\nprint(\"RMSLE (original scale):\", rmsle_original(y_val_original, val_pred))\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-24T00:11:34.200451Z","iopub.execute_input":"2025-12-24T00:11:34.200762Z","iopub.status.idle":"2025-12-24T00:12:31.456771Z","shell.execute_reply.started":"2025-12-24T00:11:34.20073Z","shell.execute_reply":"2025-12-24T00:12:31.455988Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import numpy as np\nimport pandas as pd\n\n# 1) توقع على test (log)\ntest_pred_log = lgb_model.predict(X_test_final)\n\n# 2) رجّع للأصل\ntest_pred = np.expm1(test_pred_log)\n\n# (اختياري) تأكد ما في سالب\ntest_pred = np.maximum(test_pred, 0)\n\n# 3) اعمل submission\nsubmission = pd.DataFrame({\n    \"id\": test[\"id\"],\n    \"Premium Amount\": test_pred\n})\n\nsubmission.to_csv(\"submission.csv\", index=False)\nsubmission.head()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-24T00:13:59.458229Z","iopub.execute_input":"2025-12-24T00:13:59.458964Z","iopub.status.idle":"2025-12-24T00:14:35.042398Z","shell.execute_reply.started":"2025-12-24T00:13:59.458934Z","shell.execute_reply":"2025-12-24T00:14:35.041627Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import numpy as np\nimport pandas as pd\n\nfrom sklearn.model_selection import train_test_split, RandomizedSearchCV\nfrom sklearn.metrics import mean_squared_error\nfrom lightgbm import LGBMRegressor\n\ndef rmsle(y_true, y_pred):\n    y_pred = np.maximum(y_pred, 0)\n    return np.sqrt(np.mean((np.log1p(y_pred) - np.log1p(y_true))**2))\n\n# --- X, y لازم يكونوا جاهزين من قبل ---\n# X = train_encoded.drop(columns=[\"Premium Amount\"])\n# y = train_encoded[\"Premium Amount\"]\n\n# جهّز X_test_final\nif \"Premium Amount\" in test_encoded.columns:\n    X_test_final = test_encoded.drop(columns=[\"Premium Amount\"])\nelse:\n    X_test_final = test_encoded.copy()\n\n# (مهم) شيل id من الميزات إذا موجود\nif \"id\" in X.columns:\n    X = X.drop(columns=[\"id\"])\nif \"id\" in X_test_final.columns:\n    X_test_final = X_test_final.drop(columns=[\"id\"])\n\n# (الأهم) نفس الأعمدة + نفس الترتيب\nX_test_final = X_test_final.reindex(columns=X.columns, fill_value=0)\n\n# نظّف أسماء الأعمدة من المسافات (اختياري لكن مفيد)\nX.columns = X.columns.str.replace(\" \", \"_\")\nX_test_final.columns = X_test_final.columns.str.replace(\" \", \"_\")\n\n# log target\ny_log = np.log1p(y)\n\n# split على y_log\nX_train, X_val, y_train_log, y_val_log = train_test_split(\n    X, y_log, test_size=0.2, random_state=42\n)\n\nprint(\"Shapes:\", X_train.shape, X_val.shape, y_train_log.shape, y_val_log.shape)\n\nlgb_base = LGBMRegressor(\n    objective=\"regression\",\n    random_state=42,\n    n_jobs=-1\n)\n\nparam_dist = {\n    \"n_estimators\": [200, 300, 500, 800],\n    \"learning_rate\": [0.01, 0.03, 0.05, 0.1],\n    \"num_leaves\": [31, 50, 70, 100],\n    \"max_depth\": [-1, 10, 20, 30],\n    \"subsample\": [0.8, 0.9, 1.0],\n    \"colsample_bytree\": [0.8, 0.9, 1.0],\n    \"min_child_samples\": [10, 20, 40, 60],\n    \"reg_alpha\": [0.0, 0.1, 0.5, 1.0],\n    \"reg_lambda\": [0.0, 0.1, 0.5, 1.0]\n}\n\nrandom_search = RandomizedSearchCV(\n    estimator=lgb_base,\n    param_distributions=param_dist,\n    n_iter=25,\n    scoring=\"neg_mean_squared_error\",   # ✅ بدل neg_mean_squared_log_error\n    cv=3,\n    verbose=1,\n    random_state=42,\n    n_jobs=-1\n)\n\nrandom_search.fit(X_train, y_train_log)\n\nbest_model = random_search.best_estimator_\nprint(\"\\nBest Params:\\n\", random_search.best_params_)\n\n# Validate: log -> expm1 -> RMSLE الحقيقي\nval_pred_log = best_model.predict(X_val)\nval_pred = np.expm1(val_pred_log)\ny_val_real = np.expm1(y_val_log)\n\nprint(\"\\nRMSLE (Validation):\", rmsle(y_val_real, val_pred))\n\n# Train full\nbest_model.fit(X, y_log)\n\n# Predict test\ntest_pred_log = best_model.predict(X_test_final)\ntest_pred = np.expm1(test_pred_log)\ntest_pred = np.maximum(test_pred, 0)\n\nsubmission = pd.DataFrame({\n    \"id\": test[\"id\"],            # من dataframe الأصلي test\n    \"Premium Amount\": test_pred\n})\n\nsubmission.to_csv(\"submission.csv\", index=False)\nsubmission.head()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-24T00:14:50.272659Z","iopub.execute_input":"2025-12-24T00:14:50.273157Z"}},"outputs":[],"execution_count":null}]}