{"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":"gpu","dataSources":[{"sourceId":115000,"databundleVersionId":13896359,"sourceType":"competition"}],"dockerImageVersionId":31090,"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-10-06T08:45:26.807872Z","iopub.execute_input":"2025-10-06T08:45:26.808058Z","iopub.status.idle":"2025-10-06T08:45:27.121480Z","shell.execute_reply.started":"2025-10-06T08:45:26.808038Z","shell.execute_reply":"2025-10-06T08:45:27.120570Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import pandas as pd\n\ntrain_df = pd.read_csv('/kaggle/input/carnival-risk-analytics-challenge/train.csv')\ntest_df = pd.read_csv('/kaggle/input/carnival-risk-analytics-challenge/train.csv')\n\nprint(\"Train DataFrame:\")\ndisplay(train_df.head())\n\nprint(\"\\nTest DataFrame:\")\ndisplay(test_df.head())","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-06T08:45:27.123087Z","iopub.execute_input":"2025-10-06T08:45:27.123405Z","iopub.status.idle":"2025-10-06T08:45:34.361729Z","shell.execute_reply.started":"2025-10-06T08:45:27.123386Z","shell.execute_reply":"2025-10-06T08:45:34.361058Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print(\"Number of duplicate rows in train_df before removal:\", train_df.duplicated().sum())\ntrain_df.drop_duplicates(inplace=True)\nprint(\"Number of duplicate rows in train_df after removal:\", train_df.duplicated().sum())","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-06T08:45:34.362503Z","iopub.execute_input":"2025-10-06T08:45:34.362818Z","iopub.status.idle":"2025-10-06T08:45:36.775602Z","shell.execute_reply.started":"2025-10-06T08:45:34.362800Z","shell.execute_reply":"2025-10-06T08:45:36.774968Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print(\"Missing values in train_df:\")\ndisplay(train_df.isnull().sum())\n\nprint(\"\\nMissing values in test_df:\")\ndisplay(test_df.isnull().sum())","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-06T08:45:36.776221Z","iopub.execute_input":"2025-10-06T08:45:36.776416Z","iopub.status.idle":"2025-10-06T08:45:37.424577Z","shell.execute_reply.started":"2025-10-06T08:45:36.776400Z","shell.execute_reply":"2025-10-06T08:45:37.424047Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# def impute_missing_values(df):\n#     \"\"\"\n#     Imputes missing values in the DataFrame based on specified strategies.\n\n#     Args:\n#         df: pandas DataFrame.\n\n#     Returns:\n#         pandas DataFrame with imputed missing values.\n#     \"\"\"\n#     # Impute 'Age' with the mean\n#     df['Age'] = df['Age'].fillna(df['Age'].mean())\n\n#     # Impute 'Annual Income' with the mean\n#     df['Annual Income'] = df['Annual Income'].fillna(df['Annual Income'].mean())\n\n#     # Impute 'Marital Status' with the mode\n#     df['Marital Status'] = df['Marital Status'].fillna(df['Marital Status'].mode()[0])\n\n#     # Impute 'Number of Children' based on age\n#     df['Number of Children'] = df.apply(\n#         lambda row: df['Number of Children'].mode()[0] if pd.isnull(row['Number of Children']) and row['Age'] > 25 else (0 if pd.isnull(row['Number of Children']) else row['Number of Children']), axis=1\n#     )\n\n#     # Impute 'Occupation' with the mode\n#     df['Occupation'] = df['Occupation'].fillna(df['Occupation'].mode()[0])\n\n#     # Impute 'Health Score' with the mean\n#     df['Health Score'] = df['Health Score'].fillna(df['Health Score'].mean())\n\n#     # Impute 'Previous Claims' with the mode\n#     df['Previous Claims'] = df['Previous Claims'].fillna(df['Previous Claims'].mode()[0])\n\n#     # Impute 'Vehicle Age' with the mean\n#     df['Vehicle Age'] = df['Vehicle Age'].fillna(df['Vehicle Age'].mean())\n\n#     # Impute 'Credit Score' with the mean\n#     df['Credit Score'] = df['Credit Score'].fillna(df['Credit Score'].mean())\n\n#     # Impute 'Insurance Duration' with the mean (only in train_df as test_df has no missing values)\n#     if 'Insurance Duration' in df.columns:\n#         df['Insurance Duration'] = df['Insurance Duration'].fillna(df['Insurance Duration'].mean())\n\n\n#     # Impute 'Customer Feedback' with the mode\n#     df['Customer Feedback'] = df['Customer Feedback'].fillna(df['Customer Feedback'].mode()[0])\n\n#     return df\n\n# # Apply imputation to both dataframes\n# train_df = impute_missing_values(train_df)\n# test_df = impute_missing_values(test_df)\n\nimport pandas as pd\nimport numpy as np\n\ndef impute_missing_values(df: pd.DataFrame) -> pd.DataFrame:\n    \"\"\"\n    Efficiently imputes missing values using vectorized operations.\n    Optimized for large DataFrames (~500k+ rows).\n    \"\"\"\n    df = df.copy()\n\n    # Precompute means and modes once\n    means = df[['Age', 'Annual Income', 'Health Score', 'Vehicle Age', 'Credit Score',\n                'Insurance Duration' if 'Insurance Duration' in df.columns else None]].mean(numeric_only=True)\n    modes = df[['Marital Status', 'Number of Children', 'Occupation',\n                'Previous Claims', 'Customer Feedback']].mode().iloc[0]\n\n    # Numeric columns - use vectorized fillna\n    df['Age'].fillna(means['Age'], inplace=True)\n    df['Annual Income'].fillna(means['Annual Income'], inplace=True)\n    df['Health Score'].fillna(means['Health Score'], inplace=True)\n    df['Vehicle Age'].fillna(means['Vehicle Age'], inplace=True)\n    df['Credit Score'].fillna(means['Credit Score'], inplace=True)\n    if 'Insurance Duration' in df.columns:\n        df['Insurance Duration'].fillna(means['Insurance Duration'], inplace=True)\n\n    # Categorical columns - use mode\n    df['Marital Status'].fillna(modes['Marital Status'], inplace=True)\n    df['Occupation'].fillna(modes['Occupation'], inplace=True)\n    df['Previous Claims'].fillna(modes['Previous Claims'], inplace=True)\n    df['Customer Feedback'].fillna(modes['Customer Feedback'], inplace=True)\n\n    # Number of Children logic (avoid .apply)\n    num_children_mode = modes['Number of Children']\n    mask_null_children = df['Number of Children'].isna()\n    df.loc[mask_null_children & (df['Age'] > 25), 'Number of Children'] = num_children_mode\n    df.loc[mask_null_children & (df['Age'] <= 25), 'Number of Children'] = 0\n\n    return df\n\n\n# Apply to both datasets\ntrain_df = impute_missing_values(train_df)\ntest_df = impute_missing_values(test_df)\n\nprint(\"Missing values in train_df after imputation:\")\ndisplay(train_df.isnull().sum())\n\nprint(\"\\nMissing values in test_df after imputation:\")\ndisplay(test_df.isnull().sum())\n\n# print(\"Missing values in train_df after imputation:\")\n# display(train_df.isnull().sum())\n\n# print(\"\\nMissing values in test_df after imputation:\")\n# display(test_df.isnull().sum())","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-06T08:45:37.425246Z","iopub.execute_input":"2025-10-06T08:45:37.425447Z","iopub.status.idle":"2025-10-06T08:45:38.959505Z","shell.execute_reply.started":"2025-10-06T08:45:37.425431Z","shell.execute_reply":"2025-10-06T08:45:38.958899Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"!pip install category_encoders","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-06T08:45:38.960206Z","iopub.execute_input":"2025-10-06T08:45:38.960415Z","iopub.status.idle":"2025-10-06T08:45:42.897651Z","shell.execute_reply.started":"2025-10-06T08:45:38.960399Z","shell.execute_reply":"2025-10-06T08:45:42.896962Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Identify categorical columns\ncategorical_cols_train = train_df.select_dtypes(include=['object', 'category']).columns.tolist()\ncategorical_cols_test = test_df.select_dtypes(include=['object', 'category']).columns.tolist()\n\nprint(\"Categorical columns in train_df:\", categorical_cols_train)\nprint(\"Categorical columns in test_df:\", categorical_cols_test)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-06T08:45:42.899909Z","iopub.execute_input":"2025-10-06T08:45:42.900541Z","iopub.status.idle":"2025-10-06T08:45:43.094009Z","shell.execute_reply.started":"2025-10-06T08:45:42.900517Z","shell.execute_reply":"2025-10-06T08:45:43.093291Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from sklearn.preprocessing import LabelEncoder, OrdinalEncoder\nimport category_encoders as ce\n\n# Drop 'id' column\ntrain_df.drop('id', axis=1, inplace=True)\ntest_df.drop('id', axis=1, inplace=True)\n\n# Binary encoding for 'Marital Status' (assuming 'Single' is one category and others are the other)\ntrain_df['Marital Status'] = train_df['Marital Status'].apply(lambda x: 1 if x == 'Married' else 0)\ntest_df['Marital Status'] = test_df['Marital Status'].apply(lambda x: 1 if x == 'Married' else 0)\n\n# Label Encoding for 'Education Level', 'Occupation', 'Location', 'Customer Feedback', 'Smoking Status', 'Property Type'\nlabel_encode_cols = ['Education Level', 'Occupation', 'Location', 'Customer Feedback', 'Smoking Status', 'Property Type']\nfor col in label_encode_cols:\n    le = LabelEncoder()\n    train_df[col] = le.fit_transform(train_df[col])\n    test_df[col] = le.transform(test_df[col]) # Use transform on test to avoid new categories\n\n# Ordinal Encoding for 'Policy Type'\n# Check for other tiers\nprint(\"Unique values in Policy Type:\", train_df['Policy Type'].unique())\npolicy_order = ['Basic', 'Premium', 'Comprehensive']\noe = OrdinalEncoder(categories=[policy_order])\ntrain_df['Policy Type'] = oe.fit_transform(train_df[['Policy Type']])\ntest_df['Policy Type'] = oe.transform(test_df[['Policy Type']])\n\n# Feature Engineering 'Policy Start Date'\ntrain_df['Policy Start Date'] = pd.to_datetime(train_df['Policy Start Date'])\ntest_df['Policy Start Date'] = pd.to_datetime(test_df['Policy Start Date'])\n\n# Calculate 'time since policy bought'. Assuming 'today' is a fixed date for consistency.\n# In a real scenario, you might use the current date or a reference date from the dataset.\n# Let's use the latest date in the training data as a reference.\nlatest_date = train_df['Policy Start Date'].max()\n\ntrain_df['time_since_policy_bought'] = (latest_date - train_df['Policy Start Date']).dt.days\ntest_df['time_since_policy_bought'] = (latest_date - test_df['Policy Start Date']).dt.days\n\n# Drop the original 'Policy Start Date' column\ntrain_df.drop('Policy Start Date', axis=1, inplace=True)\ntest_df.drop('Policy Start Date', axis=1, inplace=True)\n\n# Target Encoding for 'Exercise Frequency' using 'Premium Amount' as the target\ntarget_encode_col = 'Exercise Frequency'\ntarget = 'Premium Amount'\n\n# Ensure the target variable exists in the training data\nif target in train_df.columns:\n    # Initialize TargetEncoder\n    encoder = ce.TargetEncoder(cols=[target_encode_col])\n\n    # Fit and transform on the training data\n    train_df[target_encode_col] = encoder.fit_transform(train_df[target_encode_col], train_df[target])\n\n    # Transform on the testing data (use the mappings learned from the training data)\n    test_df[target_encode_col] = encoder.transform(test_df[target_encode_col])\nelse:\n    print(f\"Warning: Target variable '{target}' not found in the training data. Skipping target encoding for '{target_encode_col}'.\")\n\nprint(\"\\nTrain DataFrame after encoding and feature engineering:\")\ndisplay(train_df.head())\n\nprint(\"\\nTest DataFrame after encoding and feature engineering:\")\ndisplay(test_df.head())","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-06T08:45:43.095130Z","iopub.execute_input":"2025-10-06T08:45:43.095443Z","iopub.status.idle":"2025-10-06T08:45:47.479175Z","shell.execute_reply.started":"2025-10-06T08:45:43.095422Z","shell.execute_reply":"2025-10-06T08:45:47.478618Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import matplotlib.pyplot as plt\nimport seaborn as sns\n\n# Calculate the correlation matrix\ncorrelation_matrix = train_df.corr()\n\n# Display the correlation matrix\nprint(\"Correlation Matrix:\")\ndisplay(correlation_matrix)\n\n# Optionally, visualize the correlation matrix using a heatmap\nplt.figure(figsize=(12, 10))\nsns.heatmap(correlation_matrix, annot=False, cmap='coolwarm')\nplt.title('Correlation Matrix of Training Data')\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-06T08:45:47.479877Z","iopub.execute_input":"2025-10-06T08:45:47.480286Z","iopub.status.idle":"2025-10-06T08:45:49.000385Z","shell.execute_reply.started":"2025-10-06T08:45:47.480267Z","shell.execute_reply":"2025-10-06T08:45:48.999572Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"X = train_df.drop('Premium Amount', axis=1)\ny = train_df['Premium Amount']\n\nprint(\"Features (X) shape:\", X.shape)\nprint(\"Target (y) shape:\", y.shape)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-06T08:45:49.001242Z","iopub.execute_input":"2025-10-06T08:45:49.001590Z","iopub.status.idle":"2025-10-06T08:45:49.040787Z","shell.execute_reply.started":"2025-10-06T08:45:49.001573Z","shell.execute_reply":"2025-10-06T08:45:49.040158Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from sklearn.model_selection import train_test_split\n\nX_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)\n\nprint(\"X_train shape:\", X_train.shape)\nprint(\"X_test shape:\", X_test.shape)\nprint(\"y_train shape:\", y_train.shape)\nprint(\"y_test shape:\", y_test.shape)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-06T08:45:49.041459Z","iopub.execute_input":"2025-10-06T08:45:49.041669Z","iopub.status.idle":"2025-10-06T08:45:49.305961Z","shell.execute_reply.started":"2025-10-06T08:45:49.041653Z","shell.execute_reply":"2025-10-06T08:45:49.305342Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import xgboost as xgb\nfrom sklearn.ensemble import AdaBoostRegressor, RandomForestRegressor\nfrom lightgbm import LGBMRegressor\n\n# Initialize models with default parameters\nxgb_model = xgb.XGBRegressor(random_state=42)\nada_model = AdaBoostRegressor(random_state=42)\nlgbm_model = LGBMRegressor(random_state=42)\nrf_model = RandomForestRegressor(random_state=42)\n\nprint(\"Initialized XGBoost Regressor:\", xgb_model)\nprint(\"Initialized AdaBoost Regressor:\", ada_model)\nprint(\"Initialized LightGBM Regressor:\", lgbm_model)\nprint(\"Initialized Random Forest Regressor:\", rf_model)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-06T08:45:49.306673Z","iopub.execute_input":"2025-10-06T08:45:49.306932Z","iopub.status.idle":"2025-10-06T08:45:53.472877Z","shell.execute_reply.started":"2025-10-06T08:45:49.306911Z","shell.execute_reply":"2025-10-06T08:45:53.472073Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Define hyperparameter grids for each model\n\nxgb_param_grid = {\n    'n_estimators': [100, 200, 300],\n    'learning_rate': [0.01, 0.1, 0.2],\n    'max_depth': [3, 5, 7],\n    'subsample': [0.8, 1.0],\n    'colsample_bytree': [0.8, 1.0]\n}\n\nada_param_grid = {\n    'n_estimators': [50, 100, 200],\n    'learning_rate': [0.01, 0.1, 1.0],\n    'loss': ['linear', 'square', 'exponential']\n}\n\nlgbm_param_grid = {\n    'n_estimators': [100, 200, 300],\n    'learning_rate': [0.01, 0.1, 0.2],\n    'num_leaves': [31, 62, 124],\n    'max_depth': [-1, 10, 20],\n    'subsample': [0.8, 1.0],\n    'colsample_bytree': [0.8, 1.0]\n}\n\nrf_param_grid = {\n    'n_estimators': [100, 200, 300],\n    'max_depth': [10, 20, None],\n    'min_samples_split': [2, 5, 10],\n    'min_samples_leaf': [1, 2, 4]\n}\n\nprint(\"XGBoost Parameter Grid:\", xgb_param_grid)\nprint(\"AdaBoost Parameter Grid:\", ada_param_grid)\nprint(\"LightGBM Parameter Grid:\", lgbm_param_grid)\nprint(\"Random Forest Parameter Grid:\", rf_param_grid)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-06T08:45:53.473681Z","iopub.execute_input":"2025-10-06T08:45:53.474229Z","iopub.status.idle":"2025-10-06T08:45:53.479954Z","shell.execute_reply.started":"2025-10-06T08:45:53.474210Z","shell.execute_reply":"2025-10-06T08:45:53.479182Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from sklearn.model_selection import KFold\n\n# Define 5-fold cross-validation\nkf = KFold(n_splits=5, shuffle=True, random_state=42)\n\nprint(\"5-fold cross-validation object:\", kf)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-06T08:45:53.480848Z","iopub.execute_input":"2025-10-06T08:45:53.481121Z","iopub.status.idle":"2025-10-06T08:45:53.518123Z","shell.execute_reply.started":"2025-10-06T08:45:53.481101Z","shell.execute_reply":"2025-10-06T08:45:53.517529Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from sklearn.model_selection import GridSearchCV\n\n# List of models and their parameter grids\nmodels = [\n    ('XGBoost', xgb_model, xgb_param_grid),\n    ('AdaBoost', ada_model, ada_param_grid),\n    ('LightGBM', lgbm_model, lgbm_param_grid),\n    ('RandomForest', rf_model, rf_param_grid)\n]\n\nbest_estimators = {}\n\nfor name, model, param_grid in models:\n    print(f\"Running GridSearchCV for {name}...\")\n    grid_search = GridSearchCV(estimator=model, param_grid=param_grid, cv=kf, scoring='neg_mean_squared_error', n_jobs=-1, verbose=1)\n    grid_search.fit(X_train, y_train)\n\n    print(f\"Best parameters for {name}: {grid_search.best_params_}\")\n    print(f\"Best cross-validation score for {name}: {-grid_search.best_score_}\") # Convert negative MSE to positive\n    best_estimators[name] = grid_search.best_estimator_\n    print(\"-\" * 30)\n\nprint(\"\\nBest estimators found:\")\nfor name, estimator in best_estimators.items():\n    print(f\"{name}: {estimator}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-06T08:45:53.518909Z","iopub.execute_input":"2025-10-06T08:45:53.519144Z","execution_failed":"2025-10-06T15:48:16.176Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"\ntest_predictions = final_xgb_model.predict(test_df)\n\ntry:\n    submission_df = pd.DataFrame({'id': test_df_original['id'], 'Premium Amount': test_predictions})\nexcept NameError:\n    print(\"Warning: 'test_df_original' not found. Assuming the original test data needs to be reloaded to get the 'id' column.\")\n    test_df_original = pd.read_csv('test.csv')\n    submission_df = pd.DataFrame({'id': test_df_original['id'], 'Premium Amount': test_predictions})\n\n\nprint(\"Submission DataFrame:\")\ndisplay(submission_df.head())\n\nsubmission_df.to_csv('submission.csv', index=False)\n\nprint(\"Submission file created successfully.\")","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}