{"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","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":84896,"databundleVersionId":10305135,"isSourceIdPinned":false}],"dockerImageVersionId":31328,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# Insurance Premium Prediction ","metadata":{}},{"cell_type":"code","source":"import numpy as np\nimport pandas as pd\nimport seaborn as sns\nimport matplotlib.pyplot as plt\nimport warnings\n\nwarnings.filterwarnings('ignore')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-24T18:33:02.146936Z","iopub.execute_input":"2026-04-24T18:33:02.147756Z","iopub.status.idle":"2026-04-24T18:33:03.198166Z","shell.execute_reply.started":"2026-04-24T18:33:02.147712Z","shell.execute_reply":"2026-04-24T18:33:03.197279Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## 1. Load Data","metadata":{}},{"cell_type":"code","source":"test_df = pd.read_csv('/kaggle/input/competitions/playground-series-s4e12/test.csv')\ndf = pd.read_csv('/kaggle/input/competitions/playground-series-s4e12/train.csv')\ndf.head(10)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-24T18:33:03.199284Z","iopub.execute_input":"2026-04-24T18:33:03.199722Z","iopub.status.idle":"2026-04-24T18:33:08.813693Z","shell.execute_reply.started":"2026-04-24T18:33:03.199686Z","shell.execute_reply":"2026-04-24T18:33:08.812818Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## 2. Split Features & Target","metadata":{}},{"cell_type":"code","source":"submission_ids = test_df['id'].copy()\n\ncolumns_to_drop = ['Premium Amount', 'id']\nX = df.drop(columns=columns_to_drop, axis=1)\ny = df['Premium Amount']\n\n# Kaggle test — drop id for processing\nX_kaggle_test = test_df.drop(columns=['id'], axis=1)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-24T18:33:08.814571Z","iopub.execute_input":"2026-04-24T18:33:08.814827Z","iopub.status.idle":"2026-04-24T18:33:09.138097Z","shell.execute_reply.started":"2026-04-24T18:33:08.814805Z","shell.execute_reply":"2026-04-24T18:33:09.137523Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## 3. Null Handling","metadata":{}},{"cell_type":"code","source":"X.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-24T18:33:09.140148Z","iopub.execute_input":"2026-04-24T18:33:09.1406Z","iopub.status.idle":"2026-04-24T18:33:09.156033Z","shell.execute_reply.started":"2026-04-24T18:33:09.140577Z","shell.execute_reply":"2026-04-24T18:33:09.155479Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"null_pct = (X.isnull().sum() / len(X)) * 100\nprint(f\"Drop These Columns:\\n {null_pct[null_pct > 40]}\\n\")\nprint(f\"Fill These Columns:\\n{null_pct[(null_pct < 40) & (null_pct > 0)]}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-24T18:33:09.156935Z","iopub.execute_input":"2026-04-24T18:33:09.157317Z","iopub.status.idle":"2026-04-24T18:33:09.741736Z","shell.execute_reply.started":"2026-04-24T18:33:09.157289Z","shell.execute_reply":"2026-04-24T18:33:09.741045Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Numeric columns with missing values\nnumeric_col = []\nfor col in X.columns:\n    if pd.api.types.is_numeric_dtype(X[col]):\n        missing_count = X[col].isnull().sum()\n        if missing_count > 0.001:\n            missing_pct = X[col].isnull().mean() * 100\n            numeric_col.append(col)\n            print(f\"Column: {col} | Missing: {missing_pct:.4f}%\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-24T18:33:09.742734Z","iopub.execute_input":"2026-04-24T18:33:09.743102Z","iopub.status.idle":"2026-04-24T18:33:09.777978Z","shell.execute_reply.started":"2026-04-24T18:33:09.743079Z","shell.execute_reply":"2026-04-24T18:33:09.777295Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Median impute\nfor col in ['Age', 'Annual Income']:\n    X[col].fillna(X[col].median(), inplace=True)\n    X_kaggle_test[col].fillna(X_kaggle_test[col].median(), inplace=True)\n    ","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-24T18:33:09.778866Z","iopub.execute_input":"2026-04-24T18:33:09.779136Z","iopub.status.idle":"2026-04-24T18:33:09.855599Z","shell.execute_reply.started":"2026-04-24T18:33:09.779115Z","shell.execute_reply":"2026-04-24T18:33:09.854916Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Median \nfor col in ['Health Score', 'Number of Dependents', 'Credit Score']:\n    X[col].fillna(X[col].median(), inplace=True)\n    X_kaggle_test[col].fillna(X_kaggle_test[col].median(), inplace=True)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-24T18:33:09.85659Z","iopub.execute_input":"2026-04-24T18:33:09.856884Z","iopub.status.idle":"2026-04-24T18:33:09.963309Z","shell.execute_reply.started":"2026-04-24T18:33:09.856856Z","shell.execute_reply":"2026-04-24T18:33:09.962674Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"X['Previous Claims'].fillna(X['Previous Claims'].median(), inplace=True)\nX['Previous Claims'] = X['Previous Claims'].round().astype(int)\nX_kaggle_test['Previous Claims'].fillna(X_kaggle_test['Previous Claims'].median(), inplace=True)\nX_kaggle_test['Previous Claims'] = X_kaggle_test['Previous Claims'].round().astype(int)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-24T18:33:09.964284Z","iopub.execute_input":"2026-04-24T18:33:09.964575Z","iopub.status.idle":"2026-04-24T18:33:10.011396Z","shell.execute_reply.started":"2026-04-24T18:33:09.964537Z","shell.execute_reply":"2026-04-24T18:33:10.010742Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Object columns with missing values\nobject_missing_cols = []\nfor col in X.columns:\n    if pd.api.types.is_object_dtype(X[col]):\n        missing_pct = X[col].isnull().mean() * 100\n        if missing_pct > 0:\n            print(f\"Column: {col} | Missing: {missing_pct:.2f} | Dtype: {X[col].dtype}\")\n            object_missing_cols.append(col)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-24T18:33:10.012343Z","iopub.execute_input":"2026-04-24T18:33:10.012659Z","iopub.status.idle":"2026-04-24T18:33:10.611658Z","shell.execute_reply.started":"2026-04-24T18:33:10.012626Z","shell.execute_reply":"2026-04-24T18:33:10.610994Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Mode impute\nX['Marital Status'].fillna(X['Marital Status'].mode()[0], inplace=True)\nX_kaggle_test['Marital Status'].fillna(X_kaggle_test['Marital Status'].mode()[0], inplace=True)\n\n# Mode\nX['Customer Feedback'].fillna(X['Customer Feedback'].mode()[0], inplace=True)\nX_kaggle_test['Customer Feedback'].fillna(X_kaggle_test['Customer Feedback'].mode()[0], inplace=True)\n\n# Unknown\nX['Occupation'].fillna('Unknown', inplace=True)\nX_kaggle_test['Occupation'].fillna('Unknown', inplace=True)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-24T18:33:10.612679Z","iopub.execute_input":"2026-04-24T18:33:10.613397Z","iopub.status.idle":"2026-04-24T18:33:11.294702Z","shell.execute_reply.started":"2026-04-24T18:33:10.613361Z","shell.execute_reply":"2026-04-24T18:33:11.2939Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## 4. Train / Val / Test Split","metadata":{}},{"cell_type":"code","source":"from sklearn.model_selection import train_test_split\n# Stratified split\ny_binned = pd.cut(y, bins=10, labels=False)\n\nX_train, X_temp, y_train, y_temp = train_test_split(\n    X, y, test_size=0.20,\n    stratify=y_binned, random_state=42\n)\n\ny_temp_binned = pd.cut(y_temp, bins=10, labels=False)\n\nX_val, X_test, y_val, y_test = train_test_split(\n    X_temp, y_temp, test_size=0.50,\n    stratify=y_temp_binned, random_state=42\n)\n\n# Verify\nprint(\"Train mean:\", y_train.mean(), \"std:\", y_train.std())\nprint(\"Val mean:  \", y_val.mean(),   \"std:\", y_val.std())\nprint(\"Test mean: \", y_test.mean(),  \"std:\", y_test.std())","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-24T18:33:11.295642Z","iopub.execute_input":"2026-04-24T18:33:11.295959Z","iopub.status.idle":"2026-04-24T18:33:12.818733Z","shell.execute_reply.started":"2026-04-24T18:33:11.295936Z","shell.execute_reply":"2026-04-24T18:33:12.81777Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## 5. Policy Date Features","metadata":{}},{"cell_type":"code","source":"for frame in [X_train, X_val, X_test, X_kaggle_test]:\n    frame['Policy_Year']  = pd.to_datetime(frame['Policy Start Date']).dt.year\n    frame['Policy_Month'] = pd.to_datetime(frame['Policy Start Date']).dt.month\n    frame.drop(columns=['Policy Start Date'], inplace=True)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-24T18:33:12.819756Z","iopub.execute_input":"2026-04-24T18:33:12.820163Z","iopub.status.idle":"2026-04-24T18:33:14.631298Z","shell.execute_reply.started":"2026-04-24T18:33:12.820137Z","shell.execute_reply":"2026-04-24T18:33:14.630362Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## 6. Feature Engineering","metadata":{}},{"cell_type":"code","source":"def feature_create(name):\n    # Financial\n    name['Income_per_Dependent'] = name['Annual Income'] / (name['Number of Dependents'] + 1)\n    name['Credit_Score_Category'] = pd.cut(name['Credit Score'],\n                                            bins=[0, 580, 670, 740, 1000],\n                                            labels=['Poor', 'Fair', 'Good', 'Excellent'])\n    # Health & Lifestyle\n    name['Is_High_Risk_Health'] = ((name['Smoking Status'] == 'Yes') &\n                                    (name['Exercise Frequency'] == 'Rarely')).astype(int)\n    name['Age_Health_Ratio']    = name['Age'] / (name['Health Score'] + 1)\n    name['Age_Health_Interact'] = name['Age'] * name['Health Score']\n    name['Health_Income_Ratio'] = name['Health Score'] / (name['Annual Income'] + 1)\n\n    # Insurance & Risk\n    name['Claims_Frequency'] = name['Previous Claims'] / (name['Insurance Duration'] + 0.01)\n    # FIX 2: Removed redundant Claims_Per_Year (same as Claims_Frequency with tiny diff)\n    name['Dependents_Claims_Interact'] = name['Number of Dependents'] * name['Previous Claims']\n    name['Vehicle_Age_Group']  = pd.cut(name['Vehicle Age'], bins=[-1, 3, 10, 50],\n                                         labels=['New', 'Moderate', 'Old'])\n    name['Vehicle_Risk_Score'] = name['Vehicle Age'] ** 2\n\n    # Demographics\n    name['Age_Group'] = pd.cut(name['Age'], bins=[0, 25, 45, 60, 100],\n                                labels=['Young', 'Adult', 'Middle_Aged', 'Senior'])\n    name['Age_Bin']   = pd.cut(name['Age'], bins=[0, 25, 40, 55, 70, 100],\n                                labels=['Young', 'Adult', 'Middle', 'Senior', 'Elderly'])\n    name['Family_Resp'] = ((name['Marital Status'] == 'Married') &\n                            (name['Number of Dependents'] > 0)).astype(int)\n\n    # Binning\n    name['Income_Bin'] = pd.cut(name['Annual Income'],\n                                 bins=[0, 30000, 60000, 100000, 200000, np.inf],\n                                 labels=['Low', 'Medium', 'High', 'VeryHigh', 'UltraHigh'])\n    name['Credit_Bin'] = pd.cut(name['Credit Score'],\n                                 bins=[0, 400, 600, 750, 850, 1000],\n                                 labels=['Poor', 'Fair', 'Good', 'VeryGood', 'Excellent'])\n    name['Health_Bin'] = pd.cut(name['Health Score'],\n                                 bins=[0, 30, 50, 70, 85, 100],\n                                 labels=['VeryPoor', 'Poor', 'Average', 'Good', 'Excellent'])\n\n    # Interaction\n    name['Age_Income_Interact']    = name['Age'] * name['Annual Income']\n    name['Health_Credit_Interact'] = name['Health Score'] * name['Credit Score']\n    name['Income_Credit_Interact'] = name['Annual Income'] * name['Credit Score']\n    name['Claims_Health_Interact'] = name['Previous Claims'] * name['Health Score']\n\n    # Categorical Combos\n    name['Edu_Occ']                  = name['Education Level'] + '_' + name['Occupation']\n    name['Location_Property_Combo']  = name['Location'] + '_' + name['Property Type']\n    name['Lifestyle_Combo']          = name['Smoking Status'] + '_' + name['Exercise Frequency']\n    name['Marital_Education_Combo']  = name['Marital Status'] + '_' + name['Education Level']\n    name['Policy_Feedback_Combo']    = name['Policy Type'] + '_' + name['Customer Feedback']\n    name['Occupation_Location_Combo']= name['Occupation'] + '_' + name['Location']\n\n    # Policy Time\n    name['Policy_Age_Years']  = (2026 - name['Policy_Year']) + (name['Policy_Month'] / 12.0)\n    name['Policy_Season']     = name['Policy_Month'].apply(lambda m:\n        'Winter' if m in [12,1,2] else\n        'Spring' if m in [3,4,5] else\n        'Summer' if m in [6,7,8] else 'Fall')\n    name['Is_Recent_Policy'] = (name['Policy_Year'] >= 2023).astype(int)\n    name['Policy_Quarter']   = ((name['Policy_Month'] - 1) // 3) + 1","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-24T18:33:14.63241Z","iopub.execute_input":"2026-04-24T18:33:14.632729Z","iopub.status.idle":"2026-04-24T18:33:14.646491Z","shell.execute_reply.started":"2026-04-24T18:33:14.632698Z","shell.execute_reply":"2026-04-24T18:33:14.645719Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"feature_create(X_train)\nfeature_create(X_val)\nfeature_create(X_test)\nfeature_create(X_kaggle_test)\nprint(\"Feature engineering done. Shape:\", X_train.shape)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-24T18:33:14.647386Z","iopub.execute_input":"2026-04-24T18:33:14.648001Z","iopub.status.idle":"2026-04-24T18:33:18.297699Z","shell.execute_reply.started":"2026-04-24T18:33:14.647979Z","shell.execute_reply":"2026-04-24T18:33:18.296753Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"plt.figure(figsize=(16,10))\nsns.heatmap(data=X_train.corr(numeric_only=True), annot=True, fmt=\".2f\", cmap='coolwarm', cbar=True, linewidths=0.5)\nplt.title(\"Correlation Heatmap of Numerical Variables\")\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-24T18:33:18.298865Z","iopub.execute_input":"2026-04-24T18:33:18.299213Z","iopub.status.idle":"2026-04-24T18:33:21.093701Z","shell.execute_reply.started":"2026-04-24T18:33:18.299189Z","shell.execute_reply":"2026-04-24T18:33:21.092898Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"corr_matrix = X_train.corr(numeric_only=True)\n\nto_drop = [col for col in corr_matrix.columns \n           if corr_matrix[col].drop(col).abs().max() < 0.05]\n\nX_train = X_train.drop(columns=to_drop)\nX_val = X_val.drop(columns=to_drop)\nX_test = X_test.drop(columns=to_drop)\nX_kaggle_test = X_kaggle_test.drop(columns=to_drop)\n\nprint(\"Dropped:\", to_drop)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-24T18:33:21.099627Z","iopub.execute_input":"2026-04-24T18:33:21.100378Z","iopub.status.idle":"2026-04-24T18:33:23.40521Z","shell.execute_reply.started":"2026-04-24T18:33:21.100341Z","shell.execute_reply":"2026-04-24T18:33:23.404393Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"df_combined = X_train.copy()\ndf_combined['Premium Amount'] = y_train.values\n\n# ── Correlation of each feature with target ────────────────────────────\ntarget_corr = (df_combined.corr(numeric_only=True)['Premium Amount']\n               .drop('Premium Amount')\n               .abs()\n               .sort_values(ascending=False))\n\nprint(target_corr)\n\n# ── Bar plot of feature correlations with target ───────────────────────\ntarget_corr.plot(kind='bar', figsize=(12,5))\nplt.title(\"Correlation with Premium Amount\")\nplt.ylabel(\"Absolute Correlation\")\nplt.tight_layout()\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-24T18:33:23.406131Z","iopub.execute_input":"2026-04-24T18:33:23.406537Z","iopub.status.idle":"2026-04-24T18:33:26.18217Z","shell.execute_reply.started":"2026-04-24T18:33:23.406513Z","shell.execute_reply":"2026-04-24T18:33:26.18157Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"to_drop_target = target_corr[target_corr < 0.01].index.tolist()\nX_train = X_train.drop(columns=to_drop_target)\nX_val = X_val.drop(columns=to_drop_target)\nX_test = X_test.drop(columns=to_drop_target)\nX_kaggle_test = X_kaggle_test.drop(columns=to_drop_target)\nprint(\"Dropped:\", to_drop_target)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-24T18:33:26.183031Z","iopub.execute_input":"2026-04-24T18:33:26.183464Z","iopub.status.idle":"2026-04-24T18:33:26.737138Z","shell.execute_reply.started":"2026-04-24T18:33:26.183413Z","shell.execute_reply":"2026-04-24T18:33:26.736472Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"cat_cols = X_train.select_dtypes(include=['object']).columns\nfor col in cat_cols:\n    print(col, X_train[col].nunique())","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-24T18:33:26.738153Z","iopub.execute_input":"2026-04-24T18:33:26.738542Z","iopub.status.idle":"2026-04-24T18:33:28.117578Z","shell.execute_reply.started":"2026-04-24T18:33:26.738519Z","shell.execute_reply":"2026-04-24T18:33:28.116941Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"int_cols_corr_target= X_train.select_dtypes(include = ['float64','int64']).columns\ntarget_corr = X_train[int_cols_corr_target].corrwith(y_train).abs()\nprint(target_corr.sort_values())","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-24T18:33:28.118595Z","iopub.execute_input":"2026-04-24T18:33:28.118919Z","iopub.status.idle":"2026-04-24T18:33:28.299928Z","shell.execute_reply.started":"2026-04-24T18:33:28.118895Z","shell.execute_reply":"2026-04-24T18:33:28.29918Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"X_train.info()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-24T18:33:28.300957Z","iopub.execute_input":"2026-04-24T18:33:28.301317Z","iopub.status.idle":"2026-04-24T18:33:29.047434Z","shell.execute_reply.started":"2026-04-24T18:33:28.301293Z","shell.execute_reply":"2026-04-24T18:33:29.046657Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## 7. Encoding","metadata":{}},{"cell_type":"code","source":"from sklearn.preprocessing import OrdinalEncoder\n\ncat_cols = X_train.select_dtypes(include=['object', 'category']).columns.tolist()\n\nenc = OrdinalEncoder(handle_unknown='use_encoded_value', unknown_value=-1)\nX_train[cat_cols]      = enc.fit_transform(X_train[cat_cols])      # fit only on train\nX_val[cat_cols]        = enc.transform(X_val[cat_cols])\nX_test[cat_cols]       = enc.transform(X_test[cat_cols])\nX_kaggle_test[cat_cols]       = enc.transform(X_kaggle_test[cat_cols])\n\nprint(\"Encoding done. Shape:\", X_train.shape)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-24T18:33:29.048311Z","iopub.execute_input":"2026-04-24T18:33:29.048603Z","iopub.status.idle":"2026-04-24T18:33:39.235527Z","shell.execute_reply.started":"2026-04-24T18:33:29.048579Z","shell.execute_reply":"2026-04-24T18:33:39.234759Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## 8. Feature Selection via Importance","metadata":{}},{"cell_type":"code","source":"from xgboost import XGBRegressor\nfrom lightgbm import LGBMRegressor\nfrom catboost import CatBoostRegressor\n\nX_sample = X_train.sample(n=min(200000, len(X_train)), random_state=42)\ny_sample = y_train[X_sample.index]\n\nmodels_imp = {\n    'LightGBM': LGBMRegressor(verbose=-1, random_state=42),\n    'XGBoost' : XGBRegressor(verbosity=0, random_state=42),\n    'CatBoost': CatBoostRegressor(verbose=0, random_state=42),\n}\n\nfig, axes = plt.subplots(3, 1, figsize=(7, 10))\nmdl_imp_feature = set()\n\nfor ax, (name, model) in zip(axes, models_imp.items()):\n    model.fit(X_sample, y_sample)\n    imp = pd.Series(model.feature_importances_, index=X_sample.columns)\n    imp = imp.sort_values(ascending=False)\n    top = imp[imp.cumsum() / imp.sum() < 0.95]\n    mdl_imp_feature.update(top.index)\n    ax.barh(top.index, top.values)\n    ax.set_title(name)\n    ax.set_xlabel('Importance')\n\nplt.tight_layout()\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-24T18:33:39.236628Z","iopub.execute_input":"2026-04-24T18:33:39.236961Z","iopub.status.idle":"2026-04-24T18:34:02.527387Z","shell.execute_reply.started":"2026-04-24T18:33:39.236939Z","shell.execute_reply":"2026-04-24T18:34:02.526528Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"selected = list(set(mdl_imp_feature))\nprint(f\"Total selected features: {len(selected)}\")\n\nX_train_final      = X_train[selected].copy()\nX_val_final        = X_val[selected].copy()\nX_test_final       = X_test[selected].copy() \nX_kaggle_test       = X_kaggle_test[selected].copy() \n\nprint(f\"X_train_final : {X_train_final.shape}\")\nprint(f\"X_val_final   : {X_val_final.shape}\")\nprint(f\"X_test_final   : {X_test_final.shape}\") \nprint(f\"X_kaggle_test   : {X_kaggle_test.shape}\") ","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-24T18:34:02.528595Z","iopub.execute_input":"2026-04-24T18:34:02.528944Z","iopub.status.idle":"2026-04-24T18:34:03.186769Z","shell.execute_reply.started":"2026-04-24T18:34:02.52892Z","shell.execute_reply":"2026-04-24T18:34:03.186066Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"cols = X_train_final.select_dtypes(include=['float64','int32']).columns\nX_train_final[cols] = X_train_final[cols]\n\n# ── Correlation of each feature with target ────────────────────────────\ntarget_corr = (X_train_final.corrwith(y_train)\n               .abs()\n               .sort_values(ascending=False))\n\nprint(target_corr)\n\n# ── Bar plot of feature correlations with target ───────────────────────\ntarget_corr.plot(kind='bar', figsize=(12,5))\nplt.title(\"Correlation with Premium Amount\")\nplt.ylabel(\"Absolute Correlation\")\nplt.tight_layout()\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-24T18:34:03.187863Z","iopub.execute_input":"2026-04-24T18:34:03.18813Z","iopub.status.idle":"2026-04-24T18:34:04.092186Z","shell.execute_reply.started":"2026-04-24T18:34:03.188108Z","shell.execute_reply":"2026-04-24T18:34:04.09134Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"to_drop_target = target_corr[target_corr < 0.01].index.tolist()\nX_train_final = X_train_final.drop(columns=to_drop_target)\nX_val_final = X_val_final.drop(columns=to_drop_target)\nX_test_final = X_test_final.drop(columns=to_drop_target)\nX_kaggle_test = X_kaggle_test.drop(columns=to_drop_target)\nprint(\"Dropped:\", to_drop_target)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-24T18:34:04.093925Z","iopub.execute_input":"2026-04-24T18:34:04.094152Z","iopub.status.idle":"2026-04-24T18:34:04.160109Z","shell.execute_reply.started":"2026-04-24T18:34:04.094132Z","shell.execute_reply":"2026-04-24T18:34:04.159477Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## 12. Final Model Training & Evaluation","metadata":{}},{"cell_type":"code","source":"import numpy as np\n\ny_train_log = np.log1p(y_train)\ny_val_log = np.log1p(y_val)\ny_test_log = np.log1p(y_test)\n\n# Histogram dobara dekho\ny_train_log.hist(bins=50)\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-24T18:34:04.16132Z","iopub.execute_input":"2026-04-24T18:34:04.161656Z","iopub.status.idle":"2026-04-24T18:34:04.313739Z","shell.execute_reply.started":"2026-04-24T18:34:04.161631Z","shell.execute_reply":"2026-04-24T18:34:04.313039Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Risk score — claims + health combo\nX_train_final['Risk_Score'] = X_train_final['Previous Claims'] * X_train_final['Health Score']\n\n# Income per credit score — affordability proxy\nX_train_final['Income_per_Credit'] = X_train_final['Annual Income'] / (X_train_final['Credit Score'] + 1)\n\n# Claims per policy year — claim rate\nX_train_final['Claims_per_Year'] = X_train_final['Previous Claims'] / (X_train_final['Policy_Age_Years'] + 1)\n\n# High risk flag — claims zyada + health kharab\nX_train_final['HighRisk_Flag'] = (\n    (X_train_final['Previous Claims'] > 2) & \n    (X_train_final['Health Score'] < X_train_final['Health Score'].median())\n).astype(int)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-24T18:34:04.314799Z","iopub.execute_input":"2026-04-24T18:34:04.315548Z","iopub.status.idle":"2026-04-24T18:34:04.355727Z","shell.execute_reply.started":"2026-04-24T18:34:04.315506Z","shell.execute_reply":"2026-04-24T18:34:04.355042Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"for df in [X_val_final, X_test_final, X_kaggle_test]:\n    df['Risk_Score']       = df['Previous Claims'] * df['Health Score']\n    df['Income_per_Credit']= df['Annual Income'] / (df['Credit Score'] + 1)\n    df['Claims_per_Year']  = df['Previous Claims'] / (df['Policy_Age_Years'] + 1)\n    df['HighRisk_Flag']    = ((df['Previous Claims'] > 2) & (df['Health Score'] < X_train_final['Health Score'].median())).astype(int)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-24T18:34:04.357172Z","iopub.execute_input":"2026-04-24T18:34:04.357685Z","iopub.status.idle":"2026-04-24T18:34:04.428938Z","shell.execute_reply.started":"2026-04-24T18:34:04.357659Z","shell.execute_reply":"2026-04-24T18:34:04.428303Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"X_train_final.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-24T18:34:04.430003Z","iopub.execute_input":"2026-04-24T18:34:04.430333Z","iopub.status.idle":"2026-04-24T18:34:04.446086Z","shell.execute_reply.started":"2026-04-24T18:34:04.430303Z","shell.execute_reply":"2026-04-24T18:34:04.445189Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"X_train_final.info()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-24T18:34:04.447309Z","iopub.execute_input":"2026-04-24T18:34:04.447812Z","iopub.status.idle":"2026-04-24T18:34:04.484389Z","shell.execute_reply.started":"2026-04-24T18:34:04.447789Z","shell.execute_reply":"2026-04-24T18:34:04.48366Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"cols = X_train_final.select_dtypes(include=['float64','int32']).columns\nX_train_final[cols] = X_train_final[cols]\n\n# ── Correlation of each feature with target ────────────────────────────\ntarget_corr = (X_train_final.corrwith(y_train)\n               .abs()\n               .sort_values(ascending=False))\n\nprint(target_corr)\n\n# ── Bar plot of feature correlations with target ───────────────────────\ntarget_corr.plot(kind='bar', figsize=(12,5))\nplt.title(\"Correlation with Premium Amount\")\nplt.ylabel(\"Absolute Correlation\")\nplt.tight_layout()\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-24T18:34:04.485269Z","iopub.execute_input":"2026-04-24T18:34:04.485533Z","iopub.status.idle":"2026-04-24T18:34:05.155Z","shell.execute_reply.started":"2026-04-24T18:34:04.485513Z","shell.execute_reply":"2026-04-24T18:34:05.154306Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from sklearn.metrics import r2_score, mean_squared_error\nfrom xgboost import XGBRegressor\nfrom lightgbm import LGBMRegressor\nfrom catboost import CatBoostRegressor\n\nX_sample_final = X_train_final.sample(n=min(200000, len(X_train_final)), random_state=42)\ny_sample_final = y_train_log[X_sample_final.index] \n\nmodels_final = {\n    'XGBoost' : XGBRegressor(verbosity=0, random_state=42),\n    'LightGBM': LGBMRegressor(verbose=-1, random_state=42),\n    'CatBoost': CatBoostRegressor(verbose=0, random_state=42),\n}\n\nbest_model = None\nbest_r2 = -np.inf\n\nfor name, model in models_final.items():\n    model.fit(X_sample_final, y_sample_final)\n    preds_log = model.predict(X_val_final)\n\n    r2   = r2_score(y_val_log, preds_log)\n    rmse = np.sqrt(mean_squared_error(y_val_log, preds_log))\n\n    preds_orig = np.expm1(np.clip(preds_log, -10, 15))\n    y_val_orig = np.expm1(np.clip(y_val_log, -10, 15))\n    rmse_orig  = np.sqrt(mean_squared_error(y_val_orig, preds_orig))\n\n    print(f\"{name:<12}: R2(log) = {r2:.4f} | RMSE(log) = {rmse:.4f} | RMSE(orig) = {rmse_orig:.2f}\")\n\n    if r2 > best_r2:\n        best_r2    = r2\n        best_model = model\n        best_name  = name\n\nprint(f\"\\nBest model: {best_name} (R2 = {best_r2:.4f})\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-24T18:34:05.1559Z","iopub.execute_input":"2026-04-24T18:34:05.156104Z","iopub.status.idle":"2026-04-24T18:34:21.75395Z","shell.execute_reply.started":"2026-04-24T18:34:05.156085Z","shell.execute_reply":"2026-04-24T18:34:21.753274Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"pip install optuna-integration[lightgbm]","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-24T18:37:42.93456Z","iopub.execute_input":"2026-04-24T18:37:42.935356Z","iopub.status.idle":"2026-04-24T18:37:47.57275Z","shell.execute_reply.started":"2026-04-24T18:37:42.935324Z","shell.execute_reply":"2026-04-24T18:37:47.57185Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import optuna\nfrom optuna.integration import LightGBMPruningCallback\nimport numpy as np\nimport lightgbm as lgb\nfrom sklearn.metrics import r2_score, mean_squared_error\nfrom sklearn.model_selection import KFold\n\noptuna.logging.set_verbosity(optuna.logging.WARNING)\n\n# ====================== SAMPLE DATA ======================\nX_sample_final = X_train_final.sample(n=min(200000, len(X_train_final)), random_state=42)\ny_sample_final = y_train_log[X_sample_final.index]\n\n# ====================== OPTUNA OBJECTIVE (CV based) ======================\ndef objective(trial):\n    params = {\n        # Synthetic: shallow trees, heavy regularization\n        'n_estimators'      : trial.suggest_int('n_estimators', 300, 2000),\n        'learning_rate'     : trial.suggest_float('learning_rate', 0.005, 0.05, log=True),\n        'max_depth'         : trial.suggest_int('max_depth', 3, 6),        # shallow — synthetic noise avoid\n        'num_leaves'        : trial.suggest_int('num_leaves', 15, 100),    # low — overfit avoid\n        'min_child_samples' : trial.suggest_int('min_child_samples', 50, 300),  # high — noise ignore\n        'subsample'         : trial.suggest_float('subsample', 0.5, 0.85),\n        'colsample_bytree'  : trial.suggest_float('colsample_bytree', 0.5, 0.85),\n        'reg_alpha'         : trial.suggest_float('reg_alpha', 0.1, 20.0, log=True),   # strong L1\n        'reg_lambda'        : trial.suggest_float('reg_lambda', 0.1, 20.0, log=True),  # strong L2\n        'min_gain_to_split' : trial.suggest_float('min_gain_to_split', 0.01, 1.0),     # extra noise filter\n        'verbose'           : -1,\n        'random_state'      : 42\n    }\n\n    # 3-Fold CV — synthetic pe single split reliable nahi\n    kf = KFold(n_splits=3, shuffle=True, random_state=42)\n    r2_scores = []\n\n    for train_idx, val_idx in kf.split(X_sample_final):\n        X_tr = X_sample_final.iloc[train_idx]\n        y_tr = y_sample_final.iloc[train_idx]\n        X_vl = X_sample_final.iloc[val_idx]\n        y_vl = y_sample_final.iloc[val_idx]\n\n        model = lgb.LGBMRegressor(**params)\n        model.fit(\n            X_tr, y_tr,\n            eval_set=[(X_vl, y_vl)],\n            callbacks=[\n                lgb.early_stopping(50, verbose=False),\n                lgb.log_evaluation(-1)\n            ]\n        )\n\n        preds = model.predict(X_vl)\n        r2_scores.append(r2_score(y_vl, preds))\n\n    return np.mean(r2_scores)\n\n# ====================== RUN OPTUNA ======================\nstudy = optuna.create_study(\n    direction='maximize',\n    sampler=optuna.samplers.TPESampler(seed=42)\n)\nstudy.optimize(objective, n_trials=60, show_progress_bar=True)\n\nprint(\"\\n✅ Best CV R²:\", study.best_value)\nprint(\"✅ Best Params:\", study.best_params)\n\n# ====================== FINAL MODEL ======================\nbest_params = study.best_params\nbest_params['verbose'] = -1\nbest_params['random_state'] = 42\n\nfinal_model = lgb.LGBMRegressor(**best_params)\nfinal_model.fit(\n    X_sample_final, y_sample_final,\n    eval_set=[(X_val_final, y_val_log)],\n    callbacks=[\n        lgb.early_stopping(50, verbose=False),\n        lgb.log_evaluation(-1)\n    ]\n)\n\n# ====================== VALIDATION RESULTS ======================\npreds_log  = final_model.predict(X_val_final)\nr2         = r2_score(y_val_log, preds_log)\nrmse       = np.sqrt(mean_squared_error(y_val_log, preds_log))\n\npreds_orig = np.expm1(np.clip(preds_log, -10, 15))\ny_val_orig = np.expm1(np.clip(y_val_log, -10, 15))\nrmse_orig  = np.sqrt(mean_squared_error(y_val_orig, preds_orig))\n\nprint(\"\\n📊 OPTIMIZED LIGHTGBM RESULTS (Synthetic)\")\nprint(\"-\" * 50)\nprint(f\"R2(log)   : {r2:.4f}\")\nprint(f\"RMSE(log) : {rmse:.4f}\")\nprint(f\"RMSE(orig): {rmse_orig:.2f}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-24T18:38:37.148929Z","iopub.execute_input":"2026-04-24T18:38:37.149794Z","iopub.status.idle":"2026-04-24T19:01:54.783201Z","shell.execute_reply.started":"2026-04-24T18:38:37.149757Z","shell.execute_reply":"2026-04-24T19:01:54.782368Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## 13. Test Set Final Evaluation","metadata":{}},{"cell_type":"code","source":"test_preds_log = final_model.predict(X_test_final)\n\ny_test_log = np.log1p(y_test)  \n\ntest_r2   = r2_score(y_test_log, test_preds_log)\ntest_rmse = np.sqrt(mean_squared_error(\n    np.expm1(np.clip(y_test_log, -10, 15)),\n    np.expm1(np.clip(test_preds_log, -10, 15))\n))\n\nprint(f\"Test R2   : {test_r2:.4f}\")\nprint(f\"Test RMSE : {test_rmse:.2f}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-24T19:08:59.908824Z","iopub.execute_input":"2026-04-24T19:08:59.909519Z","iopub.status.idle":"2026-04-24T19:09:06.012711Z","shell.execute_reply.started":"2026-04-24T19:08:59.909482Z","shell.execute_reply":"2026-04-24T19:09:06.011818Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## 14. Kaggle Submission","metadata":{}},{"cell_type":"code","source":"# FIX 3 Final: Predict on Kaggle test, inverse log-transform\nkaggle_preds_log  = final_model.predict(X_kaggle_test)\nkaggle_preds_orig = np.expm1(kaggle_preds_log)  # back to original scale\n\nsubmission = pd.DataFrame({\n    'id': submission_ids,\n    'Premium Amount': kaggle_preds_orig\n})\n\nsubmission.to_csv('submission.csv', index=False)\nprint(\"submission.csv saved!\")\nsubmission.head(10)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-24T19:12:01.90018Z","iopub.execute_input":"2026-04-24T19:12:01.900608Z","iopub.status.idle":"2026-04-24T19:12:41.770581Z","shell.execute_reply.started":"2026-04-24T19:12:01.900579Z","shell.execute_reply":"2026-04-24T19:12:41.769885Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\nprint(os.listdir('/kaggle/working/'))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-24T19:14:02.267217Z","iopub.execute_input":"2026-04-24T19:14:02.267701Z","iopub.status.idle":"2026-04-24T19:14:02.272117Z","shell.execute_reply.started":"2026-04-24T19:14:02.267671Z","shell.execute_reply":"2026-04-24T19:14:02.271305Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}