{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.14","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"gpu","dataSources":[{"sourceId":84896,"databundleVersionId":10305135,"sourceType":"competition"}],"dockerImageVersionId":30805,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# Import Libraries","metadata":{}},{"cell_type":"markdown","source":"Try to do feature engineering in a scoring way to explain better in business✅, not may not effective for a kaggle competition❌","metadata":{}},{"cell_type":"code","source":"!pip install autogluon # install autogluon\nimport autogluon\nimport warnings\nwarnings.filterwarnings('ignore')\n\nimport pandas as pd\nimport numpy as np\nimport matplotlib.pyplot as plt\nimport seaborn as sns\nfrom sklearn.model_selection import cross_val_score, KFold\nfrom sklearn.metrics import make_scorer, mean_squared_log_error\nimport xgboost as xgb\nfrom sklearn.ensemble import RandomForestRegressor\nfrom xgboost import plot_importance\nfrom lightgbm import early_stopping, log_evaluation","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2024-12-06T14:27:30.563167Z","iopub.execute_input":"2024-12-06T14:27:30.56341Z","iopub.status.idle":"2024-12-06T14:27:36.58901Z","shell.execute_reply.started":"2024-12-06T14:27:30.563385Z","shell.execute_reply":"2024-12-06T14:27:36.588073Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Import Data","metadata":{}},{"cell_type":"code","source":"df_train = pd.read_csv(\"/kaggle/input/playground-series-s4e12/train.csv\")\ndf_test = pd.read_csv(\"/kaggle/input/playground-series-s4e12/test.csv\")\nsample_submission = pd.read_csv(\"/kaggle/input/playground-series-s4e12/sample_submission.csv\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-06T14:27:36.5905Z","iopub.execute_input":"2024-12-06T14:27:36.591058Z","iopub.status.idle":"2024-12-06T14:27:45.170406Z","shell.execute_reply.started":"2024-12-06T14:27:36.591029Z","shell.execute_reply":"2024-12-06T14:27:45.169701Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"df_train","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-06T14:27:45.171341Z","iopub.execute_input":"2024-12-06T14:27:45.171599Z","iopub.status.idle":"2024-12-06T14:27:45.880442Z","shell.execute_reply.started":"2024-12-06T14:27:45.171574Z","shell.execute_reply":"2024-12-06T14:27:45.879587Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"df_train.info()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-06T14:27:45.883241Z","iopub.execute_input":"2024-12-06T14:27:45.883961Z","iopub.status.idle":"2024-12-06T14:27:46.441063Z","shell.execute_reply.started":"2024-12-06T14:27:45.88392Z","shell.execute_reply":"2024-12-06T14:27:46.440161Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Data Preprocessing","metadata":{}},{"cell_type":"code","source":"train = df_train.copy()\ntest = df_test.copy()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-06T14:27:46.441916Z","iopub.execute_input":"2024-12-06T14:27:46.442159Z","iopub.status.idle":"2024-12-06T14:27:46.681606Z","shell.execute_reply.started":"2024-12-06T14:27:46.442136Z","shell.execute_reply":"2024-12-06T14:27:46.680667Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# NaN Fill","metadata":{}},{"cell_type":"code","source":"def fill_missing_values(train_df, test_df):\n    # 2.1 Fill 'Age' with median\n    # 'Age' is a continuous variable, and missing values are filled with the median.\n    age_median = train_df['Age'].median()\n    train_df['Age'].fillna(age_median, inplace=True)\n    test_df['Age'].fillna(age_median, inplace=True)\n\n    # 2.2 Fill 'Annual Income' based on skewness\n    # 'Annual Income' is filled with mean or median depending on skewness.\n    income_skew = train_df['Annual Income'].skew()\n    income_fill = train_df['Annual Income'].median() if abs(income_skew) > 1 else train_df['Annual Income'].mean()\n    train_df['Annual Income'].fillna(income_fill, inplace=True)\n    test_df['Annual Income'].fillna(income_fill, inplace=True)\n\n    # 2.3 Fill 'Marital Status' with 'Single'\n    # 'Marital Status' is a categorical variable, and missing values are filled with 'Single'.\n    train_df['Marital Status'].fillna('Single', inplace=True)\n    test_df['Marital Status'].fillna('Single', inplace=True)\n\n    # 2.4 Fill 'Number of Dependents' with median\n    # 'Number of Dependents' is a continuous variable, and missing values are filled with the median.\n    dependents_median = train_df['Number of Dependents'].median()\n    train_df['Number of Dependents'].fillna(dependents_median, inplace=True)\n    test_df['Number of Dependents'].fillna(dependents_median, inplace=True)\n\n    # 2.5 Fill 'Health Score' with median\n    # 'Health Score' is a continuous variable, and missing values are filled with the median.\n    health_median = train_df['Health Score'].median()\n    train_df['Health Score'].fillna(health_median, inplace=True)\n    test_df['Health Score'].fillna(health_median, inplace=True)\n\n    # 2.6 Fill 'Occupation' with 'Unemployed'\n    # 'Occupation' is a categorical variable, and missing values are filled with 'Unemployed'.\n    train_df['Occupation'].fillna('Unemployed', inplace=True)\n    test_df['Occupation'].fillna('Unemployed', inplace=True)\n\n    # 2.7 No specific operations for 'Gender'\n    # 'Gender' requires no specific imputation. It can be encoded if necessary.\n\n    # 2.8 No specific operations for 'Education Level'\n    # 'Education Level' is a categorical variable. No imputation is applied here but can be handled if needed.\n\n    # 2.9 Fill 'Previous Claims' with 0\n    # 'Previous Claims' is a numerical variable, and missing values are filled with 0.\n    train_df['Previous Claims'].fillna(0, inplace=True)\n    test_df['Previous Claims'].fillna(0, inplace=True)\n\n    # 2.10 Fill 'Vehicle Age' with median\n    # 'Vehicle Age' is a continuous variable, and missing values are filled with the median.\n    vehicle_median = train_df['Vehicle Age'].median()\n    train_df['Vehicle Age'].fillna(vehicle_median, inplace=True)\n    test_df['Vehicle Age'].fillna(vehicle_median, inplace=True)\n\n    # 2.11 Fill 'Credit Score' with median\n    # 'Credit Score' is a continuous variable, and missing values are filled with the median.\n    credit_score_median = train_df['Credit Score'].median()\n    train_df['Credit Score'].fillna(credit_score_median, inplace=True)\n    test_df['Credit Score'].fillna(credit_score_median, inplace=True)\n\n    # 2.12 Fill 'Insurance Duration' with mean or median based on skewness\n    # 'Insurance Duration' is filled with mean or median depending on skewness.\n    duration_skew = train_df['Insurance Duration'].skew()\n    duration_fill = train_df['Insurance Duration'].median() if abs(duration_skew) > 1 else train_df['Insurance Duration'].mean()\n    train_df['Insurance Duration'].fillna(duration_fill, inplace=True)\n    test_df['Insurance Duration'].fillna(duration_fill, inplace=True)\n\n    # 2.13 Fill 'Policy Start Date' with median date\n    # 'Policy Start Date' is a date variable. Missing values are filled with the median after converting to numeric ordinal format.\n    train_df['Policy Start Date'] = pd.to_datetime(train_df['Policy Start Date'], errors='coerce')\n    test_df['Policy Start Date'] = pd.to_datetime(test_df['Policy Start Date'], errors='coerce')\n    policy_start_median = train_df['Policy Start Date'].median()\n    train_df['Policy Start Date'].fillna(policy_start_median, inplace=True)\n    test_df['Policy Start Date'].fillna(policy_start_median, inplace=True)\n    train_df['Policy Start Date'] = train_df['Policy Start Date'].apply(lambda x: x.toordinal())\n    test_df['Policy Start Date'] = test_df['Policy Start Date'].apply(lambda x: x.toordinal())\n\n    # 2.14 Fill 'Customer Feedback' with median or mode\n    # 'Customer Feedback' can be numeric or categorical. If numeric, missing values are filled with the median. If categorical, the mode is used.\n    if pd.api.types.is_numeric_dtype(train_df['Customer Feedback']):\n        feedback_median = train_df['Customer Feedback'].median()\n        train_df['Customer Feedback'].fillna(feedback_median, inplace=True)\n        test_df['Customer Feedback'].fillna(feedback_median, inplace=True)\n    else:\n        feedback_mode = train_df['Customer Feedback'].mode()[0]\n        train_df['Customer Feedback'].fillna(feedback_mode, inplace=True)\n        test_df['Customer Feedback'].fillna(feedback_mode, inplace=True)\n\n    # 2.15 No specific operations for 'Smoking Status'\n    # 'Smoking Status' is a categorical variable. No imputation is applied here but can be handled if needed.\n\n    # 2.16 No specific operations for 'Exercise Frequency'\n    # 'Exercise Frequency' is a categorical variable. No imputation is applied here but can be handled if needed.\n\n    # 2.17 No specific operations for 'Property Type'\n    # 'Property Type' is a categorical variable. No imputation is applied here.\n\n    # 2.18 No specific operations for 'Premium Amount'\n    # 'Premium Amount' is the target variable and should not be modified.\n\n    return train_df, test_df","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-06T14:27:46.683013Z","iopub.execute_input":"2024-12-06T14:27:46.683306Z","iopub.status.idle":"2024-12-06T14:27:46.701404Z","shell.execute_reply.started":"2024-12-06T14:27:46.683279Z","shell.execute_reply":"2024-12-06T14:27:46.700074Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Apply the function to fill missing values\ntrain, test = fill_missing_values(train, test)\ntrain","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-06T14:27:46.702471Z","iopub.execute_input":"2024-12-06T14:27:46.702775Z","iopub.status.idle":"2024-12-06T14:27:53.413169Z","shell.execute_reply.started":"2024-12-06T14:27:46.702732Z","shell.execute_reply":"2024-12-06T14:27:53.41235Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Feature engineering with scoring","metadata":{}},{"cell_type":"code","source":"import pandas as pd\nfrom sklearn.preprocessing import MinMaxScaler\n\n# Feature Engineering Function\ndef feature_engineering(train, test):\n    # Standardize column names to lowercase\n    train.columns = train.columns.str.strip().str.lower()\n    test.columns = test.columns.str.strip().str.lower()\n\n    # Gender - Ordinary encoding\n    gender_mapping = {'Male': 1, 'Female': 0}\n    train['gender'] = train['gender'].map(gender_mapping)\n    test['gender'] = test['gender'].map(gender_mapping)\n\n    # Marital Status - Customized scoring\n    marital_status_mapping = {'Single': 0, 'Married': 1, 'Divorced': -1, 'Widowed': -0.5}\n    train['marital status'] = train['marital status'].map(marital_status_mapping)\n    test['marital status'] = test['marital status'].map(marital_status_mapping)\n\n    # Education Level - Customized scoring\n    education_mapping = {'High School': -1, \"Bachelor's\": 0, \"Master's\": 1, 'PhD': 2}\n    train['education level'] = train['education level'].map(education_mapping)\n    test['education level'] = test['education level'].map(education_mapping)\n    \n    # Occupation - Customized scoring\n    occupation_mapping = {'Employed': 2, 'Self-Employed': 1, 'Unemployed': 0}\n    train['occupation'] = train['occupation'].map(occupation_mapping)\n    test['occupation'] = test['occupation'].map(occupation_mapping)\n    \n    # Location - Customized scoring\n    location_mapping = {'Rural': -1, 'Suburban': 0, 'Urban': 1}\n    train['location'] = train['location'].map(location_mapping)\n    test['location'] = test['location'].map(location_mapping)\n\n    # Policy Type - Customized scoring\n    policy_type_mapping = {'Basic': 0, 'Comprehensive': 1, 'Premium': 2}\n    train['policy type'] = train['policy type'].map(policy_type_mapping)\n    test['policy type'] = test['policy type'].map(policy_type_mapping)\n\n    # Smoking Status - Customized scoring\n    smoking_status_mapping = {'Yes': -1, 'No': 1}\n    train['smoking status'] = train['smoking status'].map(smoking_status_mapping)\n    test['smoking status'] = test['smoking status'].map(smoking_status_mapping)\n\n    # Exercise Frequency - Customized scoring\n    exercise_mapping = {'Rarely': -1, 'Monthly': 0, 'Weekly': 1, 'Daily': 2}\n    train['exercise frequency'] = train['exercise frequency'].map(exercise_mapping)\n    test['exercise frequency'] = test['exercise frequency'].map(exercise_mapping)\n\n    # Property Type - Assign scores based on average property value\n    property_values = {'Apartment': 300000, 'Condo': 500000, 'House': 407200}\n    max_value = max(property_values.values())\n    property_scores = {k: v / max_value for k, v in property_values.items()}  # Normalize values\n    train['property type'] = train['property type'].map(property_scores)\n    test['property type'] = test['property type'].map(property_scores)\n\n    # Policy Start Date - Extract year, month, day features\n    train['policy start date'] = pd.to_datetime(train['policy start date'], errors='coerce')\n    test['policy start date'] = pd.to_datetime(test['policy start date'], errors='coerce')\n\n    for df in [train, test]:\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        \n    # Customer Feedback - Customized scoring\n    feedback_mapping = {'Good': 1, 'Poor': -1, 'Average': 0}\n    train['customer feedback'] = train['customer feedback'].map(feedback_mapping).fillna(0)\n    test['customer feedback'] = test['customer feedback'].map(feedback_mapping).fillna(0)\n\n    # Drop the original 'Policy Start Date' column\n    train.drop('policy start date', axis=1, inplace=True)\n    test.drop('policy start date', axis=1, inplace=True)\n\n    # Derive new features\n    # 1. Income Per Dependent\n    train['income_per_dependent'] = train['annual income'] / (train['number of dependents'] + 1)\n    test['income_per_dependent'] = test['annual income'] / (test['number of dependents'] + 1)\n    \n    # 3. Claims Per Year\n    train['claims_per_year'] = train['previous claims'] / train['insurance duration']\n    test['claims_per_year'] = test['previous claims'] / test['insurance duration']\n\n    # 4. Credit Score Normalization\n    scaler = MinMaxScaler()\n    train['credit score'] = scaler.fit_transform(train[['credit score']])\n    test['credit score'] = scaler.transform(test[['credit score']])\n\n    return train, test\n\n\n# Apply the feature engineering function\ntrain, test = feature_engineering(train, test)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-06T14:27:53.414684Z","iopub.execute_input":"2024-12-06T14:27:53.415059Z","iopub.status.idle":"2024-12-06T14:27:55.494498Z","shell.execute_reply.started":"2024-12-06T14:27:53.415021Z","shell.execute_reply":"2024-12-06T14:27:55.493831Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Train the model","metadata":{}},{"cell_type":"code","source":"import pandas as pd\nimport numpy as np\nfrom sklearn.metrics import mean_squared_log_error\nfrom autogluon.tabular import TabularPredictor\n\n# RMSLE calculation function\n# This function computes the Root Mean Squared Logarithmic Error (RMSLE).\ndef rmsle(y_true, y_pred):\n    return np.sqrt(mean_squared_log_error(y_true, np.maximum(0, y_pred)))\n\n# Data loading and preprocessing\n# Assume the train and test datasets are already loaded and preprocessed.\n# Drop the 'id' column and specify the target column for prediction.\ntarget = \"premium amount\"\nX_train = train.drop(columns=[\"id\"])  # Remove the 'id' column from training data\nX_test = test.drop(columns=[\"id\"])    # Remove the 'id' column from test data\ntest_ids = test[\"id\"]  # Save test IDs for submission\n\n# Initialize an AutoGluon TabularPredictor with the specified target label and evaluation metric.\npredictor = TabularPredictor(label=target, eval_metric=\"root_mean_squared_error\")\n\n# Train the AutoGluon model\npredictor.fit(\n    train_data=X_train,                # Provide the training dataset\n    presets=\"best_quality\",            # Use the \"best quality\" preset for optimal results\n    time_limit=7200,                   # Set a time limit of 3600 seconds (2 hour) for training\n    verbosity=0,                       # Suppress detailed logs during training\n    ag_args_fit={\"num_gpus\": 1}        # Explicitly specify the use of 1 GPU for training\n)\n\n# Validate model performance\n# Generate a leaderboard to show model rankings based on their performance.\nleaderboard = predictor.leaderboard(silent=False)\n\n# Predict on the test dataset\ntest_preds = predictor.predict(X_test)  # Generate predictions for the test data\n\n# Save predictions to a CSV file for submission\nsubmission = pd.DataFrame({\n    \"id\": test_ids,                  # Include test IDs\n    \"Premium Amount\": test_preds     # Include predicted premium amounts\n})\nsubmission.to_csv(\"submission.csv\", index=False)  # Save to a file named 'submission.csv'","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-06T14:27:55.849602Z","iopub.execute_input":"2024-12-06T14:27:55.849897Z","iopub.status.idle":"2024-12-06T14:27:56.181458Z","shell.execute_reply.started":"2024-12-06T14:27:55.84986Z","shell.execute_reply":"2024-12-06T14:27:56.180409Z"}},"outputs":[],"execution_count":null}]}