{"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":115000,"databundleVersionId":13897013,"sourceType":"competition"}],"dockerImageVersionId":31153,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"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-10-10T20:55:36.879415Z","iopub.execute_input":"2025-10-10T20:55:36.8798Z","iopub.status.idle":"2025-10-10T20:55:36.896071Z","shell.execute_reply.started":"2025-10-10T20:55:36.879775Z","shell.execute_reply":"2025-10-10T20:55:36.894724Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import pandas as pd\nimport numpy as np\nimport lightgbm as lgb\nfrom sklearn.preprocessing import LabelEncoder\nfrom sklearn.cluster import KMeans\nimport warnings\n\n# Suppress warnings for cleaner output\nwarnings.filterwarnings('ignore', category=FutureWarning)\nwarnings.filterwarnings('ignore', category=UserWarning)\n\n# --- 1. Load Data ---\ntry:\n    train = pd.read_csv('/kaggle/input/carnival-risk-analytics-challenge/train.csv')\n    test = pd.read_csv('/kaggle/input/carnival-risk-analytics-challenge/test.csv')\nexcept FileNotFoundError:\n    print(\"Dataset files not found. Using placeholder data.\")\n    exit()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-10T20:55:40.038934Z","iopub.execute_input":"2025-10-10T20:55:40.039227Z","iopub.status.idle":"2025-10-10T20:55:45.619003Z","shell.execute_reply.started":"2025-10-10T20:55:40.039208Z","shell.execute_reply":"2025-10-10T20:55:45.618168Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def preprocess(df):\n    if 'Policy Start Date' in df.columns:\n        df['Policy Start Date'] = pd.to_datetime(df['Policy Start Date'], errors='coerce')\n        df['Policy_Start_Year'] = df['Policy Start Date'].dt.year\n        df['Policy_Start_Month'] = df['Policy Start Date'].dt.month\n        df['Policy_Start_Day'] = df['Policy Start Date'].dt.day\n        df['Policy_Start_DayOfWeek'] = df['Policy Start Date'].dt.dayofweek\n        df['Policy_Age_Days'] = (pd.to_datetime('2025-10-09') - df['Policy Start Date']).dt.days\n        df = df.drop('Policy Start Date', axis=1)\n\n    for col in df.select_dtypes(include=np.number).columns:\n        df[col] = df[col].fillna(df[col].median())\n    for col in df.select_dtypes(include=['object', 'category']).columns:\n        df[col] = df[col].fillna(df[col].mode()[0])\n\n    for col in df.select_dtypes(include=['object']).columns:\n        le = LabelEncoder()\n        df[col] = le.fit_transform(df[col])\n        \n    return df","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-10T20:55:50.849101Z","iopub.execute_input":"2025-10-10T20:55:50.849624Z","iopub.status.idle":"2025-10-10T20:55:50.857703Z","shell.execute_reply.started":"2025-10-10T20:55:50.849588Z","shell.execute_reply":"2025-10-10T20:55:50.856393Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print(\"Preprocessing data...\")\ntrain_processed = preprocess(train.copy())\ntest_processed = preprocess(test.copy())","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-10T20:55:56.729651Z","iopub.execute_input":"2025-10-10T20:55:56.729989Z","iopub.status.idle":"2025-10-10T20:56:02.498969Z","shell.execute_reply.started":"2025-10-10T20:55:56.72996Z","shell.execute_reply":"2025-10-10T20:56:02.498002Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import pandas as pd\nimport numpy as np\nimport matplotlib.pyplot as plt\nimport seaborn as sns\nfrom itertools import combinations\n\ntrain_df = train.copy()\ntest_df = test.copy()\n# --- 1. Basic Data Info ---\nprint(\"📋 Dataset Summary:\\n\")\nprint(train_df.describe())\nprint(\"\\n🔍 Info:\\n\")\nprint(train_df.info())\nprint(\"\\n🔢 Value Counts (for categorical features):\\n\")\n\nfor col in train_df.select_dtypes(include=['object', 'category']).columns:\n    print(f\"\\n--- {col} ---\")\n    print(train_df[col].value_counts().head(10))\n\n# --- 2. Identify Numerical & Categorical Columns ---\nnumerical_cols = train_df.select_dtypes(include=[np.number]).columns.tolist()\ncategorical_cols = train_df.select_dtypes(exclude=[np.number]).columns.tolist()\n\nprint(\"\\n✅ Numerical Columns:\", numerical_cols)\nprint(\"\\n✅ Categorical Columns:\", categorical_cols)\n\n# --- 3. Missing Value Count ---\nprint(\"\\n🚨 Missing Value Count (Descending):\")\nmissing_values = train_df.isna().sum().sort_values(ascending=False)\nprint(missing_values[missing_values > 0])\n\n# --- 4. Plot Distribution of Each Numerical Feature ---\nprint(\"\\n📊 Plotting Distributions for Numerical Features...\")\nplt.figure(figsize=(15, len(numerical_cols) * 3))\nfor i, col in enumerate(numerical_cols, 1):\n    plt.subplot(len(numerical_cols), 1, i)\n    sns.histplot(train_df[col], kde=True, color='royalblue', bins=30)\n    plt.title(f\"Distribution of {col}\", fontsize=12)\n    plt.xlabel(\"\")\n    plt.grid(True, linestyle=\"--\", alpha=0.4)\nplt.tight_layout()\nplt.show()\n\n# --- 5. Correlation Matrix ---\nif 'Premium Amount' in train_df.columns:\n    corr = train_df[numerical_cols].corr()['Premium Amount'].sort_values(ascending=False)\n    print(\"\\n📈 Correlation with Target (Premium Amount):\\n\", corr)\n\nif 'Premium Amount' in train_df.columns:\n    print(\"\\n📈 Correlation Matrix (Original Numerical Features):\")\n    corr_matrix_orig = train_df[numerical_cols].corr()\n\n    plt.figure(figsize=(10, 8))\n    sns.heatmap(corr_matrix_orig, cmap='coolwarm', center=0, annot=False)\n    plt.title(\"Correlation Matrix - Original Numerical Features\", fontsize=14)\n    plt.show()\n\n    corr_target_orig = corr_matrix_orig['Premium Amount'].sort_values(ascending=False)\n    print(\"\\n📊 Correlation with Premium Amount (Original Features):\\n\", corr_target_orig)\n# --- 6. Feature Interaction Engineering ---\nprint(\"\\n🧩 Creating New Interaction Features and Calculating Correlations...\")\n\nnum_feats = [col for col in numerical_cols if col != 'Premium Amount']\ninteractions = {}\nfor (f1, f2) in combinations(num_feats, 2):\n    # Safe numeric ops (avoid division by zero)\n    train_df[f'{f1}_plus_{f2}'] = train_df[f1] + train_df[f2]\n    train_df[f'{f1}_minus_{f2}'] = train_df[f1] - train_df[f2]\n    train_df[f'{f1}_times_{f2}'] = train_df[f1] * train_df[f2]\n    train_df[f'{f1}_div_{f2}'] = np.where(train_df[f2] != 0, train_df[f1] / train_df[f2], np.nan)\n\n# Compute correlations for new features only\ninteraction_cols = [c for c in train_df.columns if any(op in c for op in ['plus', 'minus', 'times', 'div'])]\ncorr_new = train_df[interaction_cols + ['Premium Amount']].corr()['Premium Amount'].sort_values(ascending=False)\n\n# Show top correlated new features\nprint(\"\\n🔥 Top 15 New Features by Correlation with Premium Amount:\\n\")\nprint(corr_new.head(15))\n\n# Optional: Plot top correlated new features\ntop_features = corr_new.head(10).index\nplt.figure(figsize=(8, 5))\nsns.barplot(x=corr_new.loc[top_features], y=top_features, palette='Blues_r')\nplt.title(\"Top 10 Engineered Features Correlated with Premium Amount\", fontsize=13)\nplt.xlabel(\"Correlation Coefficient\")\nplt.ylabel(\"Feature\")\nplt.grid(True, linestyle=\"--\", alpha=0.5)\nplt.show()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-10T20:56:19.80054Z","iopub.execute_input":"2025-10-10T20:56:19.800887Z","iopub.status.idle":"2025-10-10T20:57:40.730531Z","shell.execute_reply.started":"2025-10-10T20:56:19.800863Z","shell.execute_reply":"2025-10-10T20:57:40.729627Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"'''\nPrevious Claims_div_Credit Score            0.012634\nPrevious Claims_minus_Vehicle Age           0.011937\nHealth Score_times_Previous Claims          0.011889\nNumber of Children_plus_Previous Claims     0.011174\nPrevious Claims_plus_Vehicle Age            0.010633\nPrevious Claims_times_Insurance Duration    0.010592\n'''","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_processed['Previous Claims_div_Credit Score'] = train_processed['Previous Claims']/train_processed['Credit Score']\ntrain_processed['Previous Claims_minus_Vehicle Age'] = train_processed['Previous Claims']-train_processed['Vehicle Age']      \ntrain_processed['Health Score_times_Previous Claims'] = train_processed['Previous Claims']*train_processed['Health Score']     \ntrain_processed['Number of Children_plus_Previous Claims'] = train_processed['Previous Claims']+train_processed['Number of Children']  \ntrain_processed['Previous Claims_plus_Vehicle Age'] = train_processed['Previous Claims']+train_processed['Vehicle Age']\ntrain_processed['Previous Claims_times_Insurance Duration'] = train_processed['Previous Claims']*train_processed['Insurance Duration']","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-10T21:06:05.439372Z","iopub.execute_input":"2025-10-10T21:06:05.439925Z","iopub.status.idle":"2025-10-10T21:06:05.484426Z","shell.execute_reply.started":"2025-10-10T21:06:05.439873Z","shell.execute_reply":"2025-10-10T21:06:05.482471Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_Final_processed=train_processed.drop(columns=['Previous Claims','Education Level','Number of Children','Exercise Frequency','Customer Feedback','Number of Children_plus_Previous Claims'])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-10T22:18:10.441999Z","iopub.execute_input":"2025-10-10T22:18:10.442303Z","iopub.status.idle":"2025-10-10T22:18:10.51686Z","shell.execute_reply.started":"2025-10-10T22:18:10.442255Z","shell.execute_reply":"2025-10-10T22:18:10.515631Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"test_processed['Previous Claims_div_Credit Score'] = test_processed['Previous Claims']/test_processed['Credit Score']\ntest_processed['Previous Claims_minus_Vehicle Age'] = test_processed['Previous Claims']-test_processed['Vehicle Age']      \ntest_processed['Health Score_times_Previous Claims'] = test_processed['Previous Claims']*test_processed['Health Score']     \ntest_processed['Number of Children_plus_Previous Claims'] = test_processed['Previous Claims']+test_processed['Number of Children']  \ntest_processed['Previous Claims_plus_Vehicle Age'] = test_processed['Previous Claims']+test_processed['Vehicle Age']\ntest_processed['Previous Claims_times_Insurance Duration'] = test_processed['Previous Claims']*test_processed['Insurance Duration']","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-10T21:07:39.969917Z","iopub.execute_input":"2025-10-10T21:07:39.970261Z","iopub.status.idle":"2025-10-10T21:07:39.992613Z","shell.execute_reply.started":"2025-10-10T21:07:39.970235Z","shell.execute_reply":"2025-10-10T21:07:39.991446Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"test_Final_processed=test_processed.drop(columns=['Previous Claims','Education Level','Number of Children','Exercise Frequency','Customer Feedback','Number of Children_plus_Previous Claims'])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-10T22:18:08.041874Z","iopub.execute_input":"2025-10-10T22:18:08.042194Z","iopub.status.idle":"2025-10-10T22:18:08.085977Z","shell.execute_reply.started":"2025-10-10T22:18:08.04217Z","shell.execute_reply":"2025-10-10T22:18:08.084953Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from sklearn.decomposition import PCA\nfrom sklearn.cluster import MiniBatchKMeans\n\n# --- 3. Clustering (with PCA + MiniBatchKMeans) ---\nfeatures_for_clustering = [\n    col for col in train_Final_processed.columns if col not in ['id', 'Premium Amount']\n]\ntrain_cluster_data = train_Final_processed[features_for_clustering]\ntest_cluster_data = test_Final_processed[features_for_clustering]\n\n# Ensure columns align between train/test\nmissing_cols = set(train_cluster_data.columns) - set(test_cluster_data.columns)\n'''\nfor c in missing_cols:\n    if c in train_cluster_data.select_dtypes(include=[np.number]).columns:\n        test_cluster_data[c] = train_cluster_data[c].median()\n    else:\n        test_cluster_data[c] = train_cluster_data[c].mode()[0]\n\ntest_cluster_data = test_cluster_data[train_cluster_data.columns]\n'''\nfor c in missing_cols:\n    test_cluster_data[c] = 0\ntest_cluster_data = test_cluster_data[train_cluster_data.columns]\n\n\n\n# Combine for joint clustering\ncombined_data = pd.concat([train_cluster_data, test_cluster_data], ignore_index=True)\n\nprint(\"Reducing dimensionality with PCA before clustering...\")\npca = PCA(n_components=min(10, combined_data.shape[1]), random_state=42)\nreduced_data = pca.fit_transform(combined_data)\n\nprint(\"Clustering reduced data with MiniBatchKMeans...\")\nkmeans = MiniBatchKMeans(n_clusters=2, random_state=42, batch_size=512)\ncombined_data['cluster'] = kmeans.fit_predict(reduced_data)\n\n# Assign cluster labels back to train/test\ntrain_Final_processed['cluster'] = combined_data['cluster'][:len(train_Final_processed)].values\ntest_Final_processed['cluster'] = combined_data['cluster'][len(train_Final_processed):].values\n\n# Optional: visualize explained variance\nimport matplotlib.pyplot as plt\nimport numpy as np\n\nplt.figure(figsize=(8,5))\nplt.plot(np.cumsum(pca.explained_variance_ratio_), marker='o')\nplt.xlabel('Number of PCA Components')\nplt.ylabel('Cumulative Explained Variance')\nplt.title('PCA Explained Variance Ratio')\nplt.grid(True, linestyle='--', alpha=0.6)\nplt.show()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-10T22:18:14.492068Z","iopub.execute_input":"2025-10-10T22:18:14.492498Z","iopub.status.idle":"2025-10-10T22:18:21.226698Z","shell.execute_reply.started":"2025-10-10T22:18:14.492463Z","shell.execute_reply":"2025-10-10T22:18:21.225552Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_Final_processed","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-10T22:18:27.916977Z","iopub.execute_input":"2025-10-10T22:18:27.917257Z","iopub.status.idle":"2025-10-10T22:18:28.15833Z","shell.execute_reply.started":"2025-10-10T22:18:27.917236Z","shell.execute_reply":"2025-10-10T22:18:28.157339Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"numerical_cols = train_Final_processed.select_dtypes(include=[np.number]).columns.tolist()\n\nif 'Premium Amount' in train_Final_processed.columns:\n    print(\"\\n📈 Correlation Matrix (Original Numerical Features):\")\n    corr_matrix_orig = train_Final_processed[numerical_cols].corr()\n\n    plt.figure(figsize=(10, 8))\n    sns.heatmap(corr_matrix_orig, cmap='coolwarm', center=0, annot=False)\n    plt.title(\"Correlation Matrix - Original Numerical Features\", fontsize=14)\n    plt.show()\n\n    corr_target_orig = corr_matrix_orig['Premium Amount'].sort_values(ascending=False)\n    print(\"\\n📊 Correlation with Premium Amount (Original Features):\\n\", corr_target_orig)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-10T22:18:32.926941Z","iopub.execute_input":"2025-10-10T22:18:32.927215Z","iopub.status.idle":"2025-10-10T22:18:34.939723Z","shell.execute_reply.started":"2025-10-10T22:18:32.927197Z","shell.execute_reply":"2025-10-10T22:18:34.938763Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# --- 4. Train Two Separate Models ---\nfeatures = [col for col in train_Final_processed.columns if col not in ['id', 'Premium Amount']]\ntarget = 'Premium Amount'\n\ntrain_c0 = train_Final_processed[train_Final_processed['cluster'] == 0]\ntrain_c1 = train_Final_processed[train_Final_processed['cluster'] == 1]\n\nX_c0, y_c0 = train_c0[features], train_c0[target]\nX_c1, y_c1 = train_c1[features], train_c1[target]","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-10T22:20:53.667765Z","iopub.execute_input":"2025-10-10T22:20:53.668473Z","iopub.status.idle":"2025-10-10T22:20:53.830823Z","shell.execute_reply.started":"2025-10-10T22:20:53.668444Z","shell.execute_reply":"2025-10-10T22:20:53.82947Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"\n\n\nlgb_params = {\n    'objective': 'regression_l1', 'metric': 'rmse', 'n_estimators': 2000,\n    'learning_rate': 0.01, 'feature_fraction': 0.8, 'bagging_fraction': 0.8,\n    'bagging_freq': 1, 'lambda_l1': 0.1, 'lambda_l2': 0.1,\n    'num_leaves': 31, 'verbose': -1, 'n_jobs': -1, 'seed': 42,\n    'boosting_type': 'gbdt',\n}\n\nprint(\"Training model for Cluster 0...\")\nmodel_c0 = lgb.LGBMRegressor(**lgb_params)\nmodel_c0.fit(X_c0, y_c0)\n\nprint(\"Training model for Cluster 1...\")\nmodel_c1 = lgb.LGBMRegressor(**lgb_params)\nmodel_c1.fit(X_c1, y_c1)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-10T22:03:05.82566Z","iopub.execute_input":"2025-10-10T22:03:05.825988Z","iopub.status.idle":"2025-10-10T22:04:42.883895Z","shell.execute_reply.started":"2025-10-10T22:03:05.825962Z","shell.execute_reply":"2025-10-10T22:04:42.882856Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from sklearn.metrics import mean_squared_error\n\npred_c0 = model_c0.predict(X_c0)\npred_c1 = model_c1.predict(X_c1)\n\n# Compute RMSE for each cluster\nrmse_c0 = np.sqrt(mean_squared_error(y_c0, pred_c0))\nrmse_c1 = np.sqrt(mean_squared_error(y_c1, pred_c1))\nprint(f\"Cluster 0 RMSE: {rmse_c0:.5f}\")\nprint(f\"Cluster 1 RMSE: {rmse_c1:.5f}\")\n\ndef plot_feature_importance(model, feature_names, top_n=20, cluster_name=\"Cluster\"):\n    importance = pd.DataFrame({\n        'feature': feature_names,\n        'importance': model.feature_importances_\n    }).sort_values(by='importance', ascending=False).head(top_n)\n    \n    plt.figure(figsize=(8, top_n*0.35))\n    plt.barh(importance['feature'][::-1], importance['importance'][::-1], color='royalblue')\n    plt.xlabel(\"Feature Importance\")\n    plt.title(f\"Top {top_n} Features - {cluster_name}\")\n    plt.grid(True, linestyle='--', alpha=0.5)\n    plt.show()\n\n# Plot for Cluster 0\nplot_feature_importance(model_c0, X_c0.columns, top_n=20, cluster_name=\"Cluster 0\")\n\n# Plot for Cluster 1\nplot_feature_importance(model_c1, X_c1.columns, top_n=20, cluster_name=\"Cluster 1\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-10T22:04:50.621802Z","iopub.execute_input":"2025-10-10T22:04:50.622116Z","iopub.status.idle":"2025-10-10T22:05:39.426635Z","shell.execute_reply.started":"2025-10-10T22:04:50.62209Z","shell.execute_reply":"2025-10-10T22:05:39.425359Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"plt.figure(figsize=(12,5))\n\n# Cluster 0\nplt.subplot(1,2,1)\nplt.scatter(y_c0, pred_c0, alpha=0.5, color='royalblue')\nplt.plot([y_c0.min(), y_c0.max()], [y_c0.min(), y_c0.max()], 'r--', lw=2)\nplt.xlabel(\"Actual Premium Amount\")\nplt.ylabel(\"Predicted Premium Amount\")\nplt.title(\"Cluster 0: Actual vs Predicted\")\nplt.grid(True, linestyle='--', alpha=0.5)\n\n# Cluster 1\nplt.subplot(1,2,2)\nplt.scatter(y_c1, pred_c1, alpha=0.5, color='orange')\nplt.plot([y_c1.min(), y_c1.max()], [y_c1.min(), y_c1.max()], 'r--', lw=2)\nplt.xlabel(\"Actual Premium Amount\")\nplt.ylabel(\"Predicted Premium Amount\")\nplt.title(\"Cluster 1: Actual vs Predicted\")\nplt.grid(True, linestyle='--', alpha=0.5)\n\nplt.tight_layout()\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-10T22:06:21.797492Z","iopub.execute_input":"2025-10-10T22:06:21.797868Z","iopub.status.idle":"2025-10-10T22:06:24.044786Z","shell.execute_reply.started":"2025-10-10T22:06:21.79784Z","shell.execute_reply":"2025-10-10T22:06:24.04387Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from sklearn.ensemble import RandomForestRegressor\n\nrf_params = {\n    'n_estimators': 600,\n    'max_depth': 15,\n    'min_samples_split': 5,\n    'min_samples_leaf': 3,\n    'max_features': 'sqrt',\n    'n_jobs': -1,\n    'random_state': 42,\n}\nprint(\"Training model for Cluster 0...\")\n\nrf_c0 = RandomForestRegressor(**rf_params)\nrf_c0.fit(X_c0, y_c0)\n\nprint(\"Training model for Cluster 1...\")\n\nrf_c1 = RandomForestRegressor(**rf_params)\nrf_c1.fit(X_c1, y_c1)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-10T22:06:34.492148Z","iopub.execute_input":"2025-10-10T22:06:34.49301Z","iopub.status.idle":"2025-10-10T22:14:12.709805Z","shell.execute_reply.started":"2025-10-10T22:06:34.492971Z","shell.execute_reply":"2025-10-10T22:14:12.708785Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from sklearn.metrics import mean_squared_error\n\npred_c0 = rf_c0.predict(X_c0)\npred_c1 = rf_c1.predict(X_c1)\n\n# Compute RMSE for each cluster\nrmse_c0 = np.sqrt(mean_squared_error(y_c0, pred_c0))\nrmse_c1 = np.sqrt(mean_squared_error(y_c1, pred_c1))\nprint(f\"Cluster 0 RMSE: {rmse_c0:.5f}\")\nprint(f\"Cluster 1 RMSE: {rmse_c1:.5f}\")\n\ndef plot_feature_importance(model, feature_names, top_n=20, cluster_name=\"Cluster\"):\n    importance = pd.DataFrame({\n        'feature': feature_names,\n        'importance': model.feature_importances_\n    }).sort_values(by='importance', ascending=False).head(top_n)\n    \n    plt.figure(figsize=(8, top_n*0.35))\n    plt.barh(importance['feature'][::-1], importance['importance'][::-1], color='royalblue')\n    plt.xlabel(\"Feature Importance\")\n    plt.title(f\"Top {top_n} Features - {cluster_name}\")\n    plt.grid(True, linestyle='--', alpha=0.5)\n    plt.show()\n\n# Plot for Cluster 0\nplot_feature_importance(rf_c0, X_c0.columns, top_n=20, cluster_name=\"Cluster 0\")\n\n# Plot for Cluster 1\nplot_feature_importance(rf_c1, X_c1.columns, top_n=20, cluster_name=\"Cluster 1\")\n\nplt.figure(figsize=(12,5))\n\n# Cluster 0\nplt.subplot(1,2,1)\nplt.scatter(y_c0, pred_c0, alpha=0.5, color='royalblue')\nplt.plot([y_c0.min(), y_c0.max()], [y_c0.min(), y_c0.max()], 'r--', lw=2)\nplt.xlabel(\"Actual Premium Amount\")\nplt.ylabel(\"Predicted Premium Amount\")\nplt.title(\"Cluster 0: Actual vs Predicted\")\nplt.grid(True, linestyle='--', alpha=0.5)\n\n# Cluster 1\nplt.subplot(1,2,2)\nplt.scatter(y_c1, pred_c1, alpha=0.5, color='orange')\nplt.plot([y_c1.min(), y_c1.max()], [y_c1.min(), y_c1.max()], 'r--', lw=2)\nplt.xlabel(\"Actual Premium Amount\")\nplt.ylabel(\"Predicted Premium Amount\")\nplt.title(\"Cluster 1: Actual vs Predicted\")\nplt.grid(True, linestyle='--', alpha=0.5)\n\nplt.tight_layout()\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-10T22:14:12.711334Z","iopub.execute_input":"2025-10-10T22:14:12.711697Z","iopub.status.idle":"2025-10-10T22:14:42.230438Z","shell.execute_reply.started":"2025-10-10T22:14:12.711664Z","shell.execute_reply":"2025-10-10T22:14:42.228725Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import numpy as np\nfrom sklearn.model_selection import GridSearchCV, KFold\nfrom sklearn.ensemble import RandomForestRegressor\nimport lightgbm as lgb\nfrom sklearn.metrics import make_scorer, mean_squared_error\n\n# --- Custom RMSE scorer ---\ndef rmse(y_true, y_pred):\n    return np.sqrt(mean_squared_error(y_true, y_pred))\n\nrmse_scorer = make_scorer(rmse, greater_is_better=False)  # for GridSearchCV\n\n# --- LightGBM Grid Search ---\nlgb_model = lgb.LGBMRegressor(objective='regression', n_jobs=-1, random_state=42)\n\nlgb_param_grid = {\n    'num_leaves': [31, 50, 70],\n    'learning_rate': [0.01, 0.05, 0.1],\n    'n_estimators': [1000, 1500, 2000],\n    'feature_fraction': [0.7, 0.8, 0.9],\n    'bagging_fraction': [0.7, 0.8, 0.9],\n    'lambda_l1': [0, 0.1, 0.5],\n    'lambda_l2': [0, 0.1, 0.5]\n}\n\nprint(\"Running GridSearchCV for LightGBM...\")\nlgb_gs = GridSearchCV(lgb_model, lgb_param_grid, cv=3, scoring=rmse_scorer, verbose=1, n_jobs=-1)\nlgb_gs.fit(X_c0, y_c0)  # Example for Cluster 0\nprint(\"Best LightGBM params (Cluster 0):\", lgb_gs.best_params_)\nprint(\"Best LightGBM RMSE (Cluster 0):\", -lgb_gs.best_score_)\n\n# --- Random Forest Grid Search ---\nrf_model = RandomForestRegressor(random_state=42, n_jobs=-1)\n\nrf_param_grid = {\n    'n_estimators': [300, 500, 700],\n    'max_depth': [None, 10, 20, 30],\n    'min_samples_split': [2, 5, 10],\n    'min_samples_leaf': [1, 2, 4],\n    'max_features': ['auto', 'sqrt', 'log2']\n}\n\nprint(\"Running GridSearchCV for Random Forest...\")\nrf_gs = GridSearchCV(rf_model, rf_param_grid, cv=3, scoring=rmse_scorer, verbose=1, n_jobs=-1)\nrf_gs.fit(X_c0, y_c0)  # Example for Cluster 0\nprint(\"Best RF params (Cluster 0):\", rf_gs.best_params_)\nprint(\"Best RF RMSE (Cluster 0):\", -rf_gs.best_score_)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-10T22:21:09.727789Z","iopub.execute_input":"2025-10-10T22:21:09.728093Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Predict on test sets\npred_lgb_c0 = model_c0.predict(test_c0[features])\npred_rf_c0  = rf_model_c0.predict(test_c0[features])\n\npred_lgb_c1 = model_c1.predict(test_c1[features])\npred_rf_c1  = rf_model_c1.predict(test_c1[features])\n\n# Weighted average (weight by inverse RMSE is common)\nw_lgb_c0 = 0.6\nw_rf_c0  = 0.4\nw_lgb_c1 = 0.6\nw_rf_c1  = 0.4\n\nfinal_pred_c0 = w_lgb_c0 * pred_lgb_c0 + w_rf_c0 * pred_rf_c0\nfinal_pred_c1 = w_lgb_c1 * pred_lgb_c1 + w_rf_c1 * pred_rf_c1\n","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from sklearn.linear_model import LinearRegression\n\n# Prepare training data for meta-model\nX_meta_c0 = np.column_stack((model_c0.predict(X_c0), rf_model_c0.predict(X_c0)))\nX_meta_c1 = np.column_stack((model_c1.predict(X_c1), rf_model_c1.predict(X_c1)))\n\nmeta_model_c0 = LinearRegression()\nmeta_model_c0.fit(X_meta_c0, y_c0)\n\nmeta_model_c1 = LinearRegression()\nmeta_model_c1.fit(X_meta_c1, y_c1)\n\n# Predict on test set\nX_test_meta_c0 = np.column_stack((pred_lgb_c0, pred_rf_c0))\nX_test_meta_c1 = np.column_stack((pred_lgb_c1, pred_rf_c1))\n\nfinal_pred_c0 = meta_model_c0.predict(X_test_meta_c0)\nfinal_pred_c1 = meta_model_c1.predict(X_test_meta_c1)\n","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"numerical_cols = train_Final_processed.select_dtypes(include=[np.number]).columns.tolist()\n\nif 'Premium Amount' in train_Final_processed.columns:\n    print(\"\\n📈 Correlation Matrix (Original Numerical Features):\")\n    corr_matrix_orig = train_processed[numerical_cols].corr()\n\n    plt.figure(figsize=(10, 8))\n    sns.heatmap(corr_matrix_orig, cmap='coolwarm', center=0, annot=False)\n    plt.title(\"Correlation Matrix - Original Numerical Features\", fontsize=14)\n    plt.show()\n\n    corr_target_orig = corr_matrix_orig['Premium Amount'].sort_values(ascending=False)\n    print(\"\\n📊 Correlation with Premium Amount (Original Features):\\n\", corr_target_orig)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-10T21:46:35.374758Z","iopub.execute_input":"2025-10-10T21:46:35.37578Z","iopub.status.idle":"2025-10-10T21:46:38.192427Z","shell.execute_reply.started":"2025-10-10T21:46:35.37574Z","shell.execute_reply":"2025-10-10T21:46:38.191348Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# --- 5. Predict on Test Set (with robust checks) ---\ntest_c0 = test_processed[test_processed['cluster'] == 0]\ntest_c1 = test_processed[test_processed['cluster'] == 1]\nprint(f\"Test samples assigned to Cluster 0: {len(test_c0)}\")\nprint(f\"Test samples assigned to Cluster 1: {len(test_c1)}\")\n\nprint(\"\\nPredicting on test data...\")\nprediction_dfs = []\n\nif not test_c0.empty:\n    preds_c0 = model_c0.predict(test_c0[features])\n    preds_df_c0 = pd.DataFrame({'id': test_c0['id'], 'Premium Amount': preds_c0})\n    prediction_dfs.append(preds_df_c0)\n\nif not test_c1.empty:\n    preds_c1 = model_c1.predict(test_c1[features])\n    preds_df_c1 = pd.DataFrame({'id': test_c1['id'], 'Premium Amount': preds_c1})\n    prediction_dfs.append(preds_df_c1)\n\n# --- 6. Generate Submission File ---\nfinal_preds_df = pd.concat(prediction_dfs).sort_values('id').reset_index(drop=True)\nfinal_preds_df.to_csv('submission.csv', index=False)\n\nprint(\"\\n'submission.csv' created successfully!\")\nprint(final_preds_df.head())","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}