{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"},"kaggle":{"accelerator":"none","dataSources":[{"sourceId":115000,"databundleVersionId":13897013,"sourceType":"competition"}],"isInternetEnabled":false,"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},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import pandas as pd\nimport numpy as np\nfrom sklearn.model_selection import StratifiedKFold\nfrom sklearn.metrics import mean_squared_error, accuracy_score\nfrom sklearn.preprocessing import LabelEncoder\nimport lightgbm as lgb\n","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_df = pd.read_csv('train.csv')\ntest_df = pd.read_csv('test.csv')\ncategorical_features = [\n    'Marital Status', 'Education Level', 'Occupation',\n    'Location', 'Policy Type', 'Customer Feedback',\n    'Smoking Status', 'Exercise Frequency', 'Property Type'\n]\n\nnumerical_features = [\n    'Age', 'Annual Income', 'Number of Children', 'Health Score',\n    'Previous Claims', 'Vehicle Age', 'Credit Score', 'Insurance Duration'\n]\n\ndate_feature = 'Policy Start Date'\n","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def handle_missing_values(df):\n    df = df.copy()\n    for col in numerical_features:\n        if col in df.columns and df[col].isnull().sum() > 0:\n            df[col].fillna(df[col].median(), inplace=True)\n    for col in categorical_features:\n        if col in df.columns and df[col].isnull().sum() > 0:\n            df[col].fillna(df[col].mode()[0], inplace=True)\n    if date_feature in df.columns and df[date_feature].isnull().sum() > 0:\n        df[date_feature].fillna(df[date_feature].mode()[0], inplace=True)\n    return df\n\ndef extract_date_features(df, date_col='Policy Start Date'):\n    df = df.copy()\n    if date_col in df.columns:\n        df[date_col] = pd.to_datetime(df[date_col])\n        df['Policy_Year'] = df[date_col].dt.year\n        df['Policy_Month'] = df[date_col].dt.month\n        df['Policy_Quarter'] = df[date_col].dt.quarter\n        df['Policy_DayOfYear'] = df[date_col].dt.dayofyear\n        df['Policy_DayOfWeek'] = df[date_col].dt.dayofweek\n        reference_date = pd.Timestamp('2025-10-05')\n        df['Policy_Age_Days'] = (reference_date - df[date_col]).dt.days\n        df.drop(columns=[date_col], inplace=True)\n    return df\n\ndef create_interaction_features(df):\n    df = df.copy()\n    if 'Age' in df.columns and 'Smoking Status' in df.columns:\n        df['Age_x_Smoking'] = df['Age'] * (df['Smoking Status'] == 'Yes').astype(int)\n    if 'Health Score' in df.columns and 'Exercise Frequency' in df.columns:\n        df['Health_x_Exercise'] = df['Health Score'] * df['Exercise Frequency'].map({\n            'Daily': 4, 'Weekly': 3, 'Monthly': 2, 'Rarely': 1, 'Never': 0\n        }).fillna(0)\n    if 'Annual Income' in df.columns and 'Number of Children' in df.columns:\n        df['Income_per_Child'] = df['Annual Income'] / (df['Number of Children'] + 1)\n    if 'Credit Score' in df.columns and 'Annual Income' in df.columns:\n        df['Credit_to_Income'] = df['Credit Score'] / (df['Annual Income'] + 1)\n    if 'Previous Claims' in df.columns and 'Insurance Duration' in df.columns:\n        df['Claims_per_Year'] = df['Previous Claims'] / (df['Insurance Duration'] + 0.1)\n    if 'Vehicle Age' in df.columns:\n        df['Vehicle_Age_Squared'] = df['Vehicle Age'] ** 2\n    if 'Age' in df.columns:\n        df['Age_Group'] = pd.cut(df['Age'], bins=[0, 25, 35, 45, 55, 65, 100],\n                                 labels=[1, 2, 3, 4, 5, 6], right=False)\n        df['Age_Group'] = df['Age_Group'].astype(float).fillna(0).astype(int)\n    return df\n","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_df = handle_missing_values(train_df)\ntest_df = handle_missing_values(test_df)\ntrain_df = extract_date_features(train_df)\ntest_df = extract_date_features(test_df)\ntrain_df = create_interaction_features(train_df)\ntest_df = create_interaction_features(test_df)\n","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"label_encoders = {}\nfor col in categorical_features:\n    if col in train_df.columns and col in test_df.columns:\n        le = LabelEncoder()\n        combined_values = pd.concat([train_df[col], test_df[col]], axis=0).astype(str)\n        le.fit(combined_values)\n        train_df[col] = le.transform(train_df[col].astype(str))\n        test_df[col] = le.transform(test_df[col].astype(str))\n        label_encoders[col] = le\n","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"label_encoders = {}\nfor col in categorical_features:\n    if col in train_df.columns and col in test_df.columns:\n        le = LabelEncoder()\n        combined_values = pd.concat([train_df[col], test_df[col]], axis=0).astype(str)\n        le.fit(combined_values)\n        train_df[col] = le.transform(train_df[col].astype(str))\n        test_df[col] = le.transform(test_df[col].astype(str))\n        label_encoders[col] = le\n","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"X = train_df.drop(columns=['id', 'Premium Amount'])\ny = train_df['Premium Amount']\nX_test = test_df.drop(columns=['id'])\ntest_ids = test_df['id'].values\n","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"THRESHOLD = 1.0\nlow_premium_mask = y <= THRESHOLD\nhigh_premium_mask = y > THRESHOLD\ny_class = (y > THRESHOLD).astype(int)\n\ndef create_target_bins(y, n_bins=10):\n    return pd.qcut(y, q=n_bins, labels=False, duplicates='drop')\n\ny_bins = create_target_bins(y, n_bins=10)\nn_folds = 5\nskf = StratifiedKFold(n_splits=n_folds, shuffle=True, random_state=42)\n","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"classifier_params = {\n    'objective': 'binary',\n    'metric': 'binary_logloss',\n    'boosting_type': 'gbdt',\n    'num_leaves': 63,\n    'max_depth': 8,\n    'learning_rate': 0.05,\n    'min_data_in_leaf': 100,\n    'feature_fraction': 0.8,\n    'bagging_fraction': 0.8,\n    'bagging_freq': 3,\n    'lambda_l1': 0.5,\n    'lambda_l2': 2.0,\n    'verbose': -1,\n    'random_state': 42,\n    'force_col_wise': True\n}\n\noof_class_probs = np.zeros(len(X))\ntest_class_probs = np.zeros(len(X_test))\n\nfor fold, (train_idx, val_idx) in enumerate(skf.split(X, y_bins), 1):\n    X_train_fold = X.iloc[train_idx]\n    y_class_fold = y_class.iloc[train_idx]\n    X_val_fold = X.iloc[val_idx]\n    y_class_val = y_class.iloc[val_idx]\n\n    train_data = lgb.Dataset(X_train_fold, label=y_class_fold, categorical_feature=categorical_features)\n    val_data = lgb.Dataset(X_val_fold, label=y_class_val, categorical_feature=categorical_features, reference=train_data)\n\n    clf = lgb.train(\n        classifier_params,\n        train_data,\n        num_boost_round=1000,\n        valid_sets=[val_data],\n        callbacks=[lgb.early_stopping(50, verbose=False)]\n    )\n\n    oof_class_probs[val_idx] = clf.predict(X_val_fold, num_iteration=clf.best_iteration)\n    test_class_probs += clf.predict(X_test, num_iteration=clf.best_iteration) / n_folds\n\noof_class_pred = (oof_class_probs > 0.5).astype(int)\ntest_class_pred = (test_class_probs > 0.5).astype(int)\naccuracy = accuracy_score(y_class, oof_class_pred)\n","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"X_low = X[low_premium_mask].reset_index(drop=True)\ny_low = y[low_premium_mask].reset_index(drop=True)\ny_low_bins = create_target_bins(y_low, n_bins=5)\nskf_low = StratifiedKFold(n_splits=5, shuffle=True, random_state=42)\n\nparams_low = {\n    'objective': 'regression',\n    'metric': 'rmse',\n    'boosting_type': 'gbdt',\n    'num_leaves': 100,\n    'max_depth': 10,\n    'learning_rate': 0.03,\n    'min_data_in_leaf': 50,\n    'feature_fraction': 0.9,\n    'bagging_fraction': 0.85,\n    'bagging_freq': 5,\n    'lambda_l1': 0.3,\n    'lambda_l2': 1.5,\n    'min_gain_to_split': 0.01,\n    'verbose': -1,\n    'random_state': 42,\n    'force_col_wise': True\n}\n\noof_low_pred = np.zeros(len(y_low))\ntest_low_pred = np.zeros(len(X_test))\n\nfor fold, (train_idx, val_idx) in enumerate(skf_low.split(X_low, y_low_bins), 1):\n    X_train_fold = X_low.iloc[train_idx]\n    y_train_fold = y_low.iloc[train_idx]\n    X_val_fold = X_low.iloc[val_idx]\n    y_val_fold = y_low.iloc[val_idx]\n\n    train_data = lgb.Dataset(X_train_fold, label=y_train_fold, categorical_feature=categorical_features)\n    val_data = lgb.Dataset(X_val_fold, label=y_val_fold, categorical_feature=categorical_features, reference=train_data)\n\n    model = lgb.train(\n        params_low,\n        train_data,\n        num_boost_round=3000,\n        valid_sets=[val_data],\n        callbacks=[lgb.early_stopping(100, verbose=False)]\n    )\n\n    oof_low_pred[val_idx] = model.predict(X_val_fold, num_iteration=model.best_iteration)\n    test_low_pred += model.predict(X_test, num_iteration=model.best_iteration) / 5\n\nlow_rmse = np.sqrt(mean_squared_error(y_low, oof_low_pred))\n","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"X_high = X[high_premium_mask].reset_index(drop=True)\ny_high = y[high_premium_mask].reset_index(drop=True)\ny_high_bins = create_target_bins(y_high, n_bins=5)\nskf_high = StratifiedKFold(n_splits=5, shuffle=True, random_state=42)\n\nparams_high = {\n    'objective': 'regression',\n    'metric': 'rmse',\n    'boosting_type': 'gbdt',\n    'num_leaves': 100,\n    'max_depth': 10,\n    'learning_rate': 0.03,\n    'min_data_in_leaf': 50,\n    'feature_fraction': 0.9,\n    'bagging_fraction': 0.85,\n    'bagging_freq': 5,\n    'lambda_l1': 0.3,\n    'lambda_l2': 1.5,\n    'min_gain_to_split': 0.01,\n    'verbose': -1,\n    'random_state': 123,\n    'force_col_wise': True\n}\n\noof_high_pred = np.zeros(len(y_high))\ntest_high_pred = np.zeros(len(X_test))\n\nfor fold, (train_idx, val_idx) in enumerate(skf_high.split(X_high, y_high_bins), 1):\n    X_train_fold = X_high.iloc[train_idx]\n    y_train_fold = y_high.iloc[train_idx]\n    X_val_fold = X_high.iloc[val_idx]\n    y_val_fold = y_high.iloc[val_idx]\n\n    train_data = lgb.Dataset(X_train_fold, label=y_train_fold, categorical_feature=categorical_features)\n    val_data = lgb.Dataset(X_val_fold, label=y_val_fold, categorical_feature=categorical_features, reference=train_data)\n\n    model = lgb.train(\n        params_high,\n        train_data,\n        num_boost_round=3000,\n        valid_sets=[val_data],\n        callbacks=[lgb.early_stopping(100, verbose=False)]\n    )\n\n    oof_high_pred[val_idx] = model.predict(X_val_fold, num_iteration=model.best_iteration)\n    test_high_pred += model.predict(X_test, num_iteration=model.best_iteration) / 5\n\nhigh_rmse = np.sqrt(mean_squared_error(y_high, oof_high_pred))\n","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}