{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.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":50160,"databundleVersionId":7921029,"sourceType":"competition"}],"dockerImageVersionId":30673,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# Introduction\n- As you can see [in the Data tab](https://www.kaggle.com/competitions/home-credit-credit-risk-model-stability/data), the data of this competition is classified according to the depth indicator.\n\n|Classification|Description|\n|--|--|\n|base|Base file including \"case_id\" and \"target\"|\n|depth=0|Files that can be combined with \"case_id\" in the base|\n|depth=1|Files that can be combined using \"case_id\" and \"num_group1\" in base|\n|depth=2|Files that can be combined using \"case_id\" and \"num_group2\" in base|\n\n- This notebook is a simple baseline using only depth=0 data.","metadata":{}},{"cell_type":"markdown","source":"# Read data","metadata":{}},{"cell_type":"code","source":"import numpy as np\nimport pandas as pd\n\npd.set_option('display.max_columns', None)","metadata":{"execution":{"iopub.status.busy":"2024-03-26T22:27:28.442789Z","iopub.execute_input":"2024-03-26T22:27:28.443207Z","iopub.status.idle":"2024-03-26T22:27:29.576999Z","shell.execute_reply.started":"2024-03-26T22:27:28.443165Z","shell.execute_reply":"2024-03-26T22:27:29.575851Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Directory where files are stored\ndirectory = \"/kaggle/input/home-credit-credit-risk-model-stability/csv_files/\"","metadata":{"execution":{"iopub.status.busy":"2024-03-26T22:27:29.579420Z","iopub.execute_input":"2024-03-26T22:27:29.580174Z","iopub.status.idle":"2024-03-26T22:27:29.585193Z","shell.execute_reply.started":"2024-03-26T22:27:29.580133Z","shell.execute_reply":"2024-03-26T22:27:29.584124Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def set_column_datatypes(df):\n    \"\"\"\n    Function to set the data type based on each column name\n    :param df: Dataframe\n    :return: Dataframe with the data type set\n    \"\"\"\n    for column in df.columns:\n        if column.endswith('P') or column.endswith('A'):\n            df[column] = df[column].astype(float)\n        elif column.endswith('M'):\n            df[column] = df[column].astype(object)\n        elif column.endswith('D'):\n            df[column] = pd.to_datetime(df[column])\n    return df","metadata":{"execution":{"iopub.status.busy":"2024-03-26T22:27:29.590291Z","iopub.execute_input":"2024-03-26T22:27:29.590683Z","iopub.status.idle":"2024-03-26T22:27:29.598150Z","shell.execute_reply.started":"2024-03-26T22:27:29.590644Z","shell.execute_reply":"2024-03-26T22:27:29.596974Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# base.csv\ntrain_base_df = pd.read_csv(directory + \"train/train_base.csv\")\ntest_base_df = pd.read_csv(directory + \"test/test_base.csv\")\n\n# static(depth=0)\n## train_static is divided into two parts, 0 and 1. read and concat one by one\ntrain_static0 = pd.read_csv(directory + \"train/train_static_0_0.csv\")\ntrain_static1 = pd.read_csv(directory + \"train/train_static_0_1.csv\")\ntrain_static = pd.concat([train_static0, train_static1], ignore_index=True)\ntrain_static = set_column_datatypes(train_static)\ndel train_static0, train_static1\n## test_static is divided into three parts: 0, 1, and 2. Processing is the same as train.\ntest_static0 = pd.read_csv(directory + \"test/test_static_0_0.csv\")\ntest_static1 = pd.read_csv(directory + \"test/test_static_0_1.csv\")\ntest_static2 = pd.read_csv(directory + \"test/test_static_0_2.csv\")\ntest_static = pd.concat([test_static0, test_static1, test_static2], ignore_index=True) # csv同士をconcatする\ntest_static = set_column_datatypes(test_static)\ndel test_static0, test_static1, test_static2\n\n# static_cb\ntrain_static_cb = pd.read_csv(directory + \"train/train_static_cb_0.csv\")\ntrain_static_cb = set_column_datatypes(train_static_cb)\n\ntest_static_cb = pd.read_csv(directory + \"test/test_static_cb_0.csv\")\ntest_static_cb = set_column_datatypes(test_static_cb)","metadata":{"execution":{"iopub.status.busy":"2024-03-26T22:27:29.601091Z","iopub.execute_input":"2024-03-26T22:27:29.601439Z","iopub.status.idle":"2024-03-26T22:28:32.309904Z","shell.execute_reply.started":"2024-03-26T22:27:29.601410Z","shell.execute_reply":"2024-03-26T22:28:32.308747Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Check the SHAPE of the data loaded\n- train may have more data in train_base and no static_cb\n- test has more data in test_static than test_base","metadata":{}},{"cell_type":"code","source":"# base\nprint(train_base_df.shape)\nprint(test_base_df.shape)","metadata":{"execution":{"iopub.status.busy":"2024-03-26T22:28:32.311364Z","iopub.execute_input":"2024-03-26T22:28:32.311814Z","iopub.status.idle":"2024-03-26T22:28:32.318646Z","shell.execute_reply.started":"2024-03-26T22:28:32.311775Z","shell.execute_reply":"2024-03-26T22:28:32.317415Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# static\nprint(\"train:\", train_static.shape)\nprint(\"test:\", test_static.shape)","metadata":{"execution":{"iopub.status.busy":"2024-03-26T22:28:32.320191Z","iopub.execute_input":"2024-03-26T22:28:32.320951Z","iopub.status.idle":"2024-03-26T22:28:32.335374Z","shell.execute_reply.started":"2024-03-26T22:28:32.320908Z","shell.execute_reply":"2024-03-26T22:28:32.334119Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#static_cb\nprint(train_static_cb.shape)\nprint(test_static_cb.shape)","metadata":{"execution":{"iopub.status.busy":"2024-03-26T22:28:32.336881Z","iopub.execute_input":"2024-03-26T22:28:32.337322Z","iopub.status.idle":"2024-03-26T22:28:32.345738Z","shell.execute_reply.started":"2024-03-26T22:28:32.337284Z","shell.execute_reply":"2024-03-26T22:28:32.344529Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Join with case_id as a key\n- Do the same process for train and test","metadata":{}},{"cell_type":"code","source":"# For simplicity, select only columns ending in \"A\" or \"P\" (columns of float type)\nselected_static_cols = []\nfor col in train_static.columns:\n    if col[-1] in (\"A\", \"P\"):\n        selected_static_cols.append(col)\n# print(selected_static_cols)\n\nselected_static_cb_cols = []\nfor col in train_static_cb.columns:\n    if col[-1] in (\"A\", \"P\"):\n        selected_static_cb_cols.append(col)\n# print(selected_static_cb_cols)\n\n# merge\ntrain_data = pd.merge(train_base_df, train_static[[\"case_id\"]+selected_static_cols], how=\"left\", on=\"case_id\")\ntrain_data = pd.merge(train_data, train_static_cb[[\"case_id\"]+selected_static_cb_cols], how=\"left\", on=\"case_id\")","metadata":{"execution":{"iopub.status.busy":"2024-03-26T22:28:32.347258Z","iopub.execute_input":"2024-03-26T22:28:32.347675Z","iopub.status.idle":"2024-03-26T22:28:36.445458Z","shell.execute_reply.started":"2024-03-26T22:28:32.347545Z","shell.execute_reply":"2024-03-26T22:28:36.444310Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# For simplicity, select only columns ending in \"A\" or \"P\" (columns of float type)\nselected_static_cols = []\nfor col in test_static.columns:\n    if col[-1] in (\"A\", \"P\"):\n        selected_static_cols.append(col)\n# print(selected_static_cols)\n\nselected_static_cb_cols = []\nfor col in test_static_cb.columns:\n    if col[-1] in (\"A\", \"P\"):\n        selected_static_cb_cols.append(col)\n# print(selected_static_cb_cols)\n\n# merge\ntest_data = pd.merge(test_base_df, test_static[[\"case_id\"]+selected_static_cols], how=\"left\", on=\"case_id\")\ntest_data = pd.merge(test_data, test_static_cb[[\"case_id\"]+selected_static_cb_cols], how=\"left\", on=\"case_id\")","metadata":{"execution":{"iopub.status.busy":"2024-03-26T22:28:36.446860Z","iopub.execute_input":"2024-03-26T22:28:36.447249Z","iopub.status.idle":"2024-03-26T22:28:36.469179Z","shell.execute_reply.started":"2024-03-26T22:28:36.447214Z","shell.execute_reply":"2024-03-26T22:28:36.468065Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_data.info()","metadata":{"execution":{"iopub.status.busy":"2024-03-26T22:28:36.470771Z","iopub.execute_input":"2024-03-26T22:28:36.471129Z","iopub.status.idle":"2024-03-26T22:28:36.744781Z","shell.execute_reply.started":"2024-03-26T22:28:36.471101Z","shell.execute_reply":"2024-03-26T22:28:36.743517Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_data.columns","metadata":{"execution":{"iopub.status.busy":"2024-03-26T22:28:36.746387Z","iopub.execute_input":"2024-03-26T22:28:36.746841Z","iopub.status.idle":"2024-03-26T22:28:36.756871Z","shell.execute_reply.started":"2024-03-26T22:28:36.746799Z","shell.execute_reply":"2024-03-26T22:28:36.755743Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"base_train = train_data[[\"case_id\", \"WEEK_NUM\", \"target\"]]\nX_train = train_data.drop([\"case_id\", \"date_decision\", \"WEEK_NUM\",\"target\"], axis=1)\ny_train = train_data[\"target\"]\n\nX_test = test_data.drop([\"case_id\", \"date_decision\", \"WEEK_NUM\"], axis=1)","metadata":{"execution":{"iopub.status.busy":"2024-03-26T22:28:36.758367Z","iopub.execute_input":"2024-03-26T22:28:36.758818Z","iopub.status.idle":"2024-03-26T22:28:37.233922Z","shell.execute_reply.started":"2024-03-26T22:28:36.758784Z","shell.execute_reply":"2024-03-26T22:28:37.232809Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Cross-validation and LightGBM","metadata":{}},{"cell_type":"code","source":"from sklearn.metrics import accuracy_score\nfrom sklearn.model_selection import StratifiedKFold\nimport lightgbm as lgb\nfrom sklearn.metrics import roc_auc_score","metadata":{"execution":{"iopub.status.busy":"2024-03-26T22:28:37.237597Z","iopub.execute_input":"2024-03-26T22:28:37.237922Z","iopub.status.idle":"2024-03-26T22:28:39.673755Z","shell.execute_reply.started":"2024-03-26T22:28:37.237897Z","shell.execute_reply":"2024-03-26T22:28:39.672461Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"params = {\n    \"boosting_type\": \"gbdt\",\n    \"objective\": \"binary\",\n    \"metric\": \"binary_logloss\",\n    \"learning_rate\": 0.1,\n    \"num_leaves\": 16,\n    \"n_estimators\": 1000000,\n    \"random_state\": 123,\n    \"importance_type\": \"gain\",\n    \"verbose\": 1\n}","metadata":{"execution":{"iopub.status.busy":"2024-03-26T22:28:39.675289Z","iopub.execute_input":"2024-03-26T22:28:39.675865Z","iopub.status.idle":"2024-03-26T22:28:39.681710Z","shell.execute_reply.started":"2024-03-26T22:28:39.675833Z","shell.execute_reply":"2024-03-26T22:28:39.680861Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"metrics = []\nimp = pd.DataFrame()\n\nn_splits = 5\n\nkf = StratifiedKFold(n_splits=n_splits, shuffle=True, random_state=123)\n\nfor nfold, (train_idx, val_idx) in enumerate(kf.split(X_train, y_train)):\n    print('-'*10, nfold, '-'*10)\n    \n    x_tr, y_tr = X_train.iloc[train_idx], y_train.iloc[train_idx]\n    x_va, y_va = X_train.iloc[val_idx], y_train.iloc[val_idx]\n    \n    print(\"Train:\", x_tr.shape, y_tr.shape)\n    print(\"Valid:\", x_va.shape, y_va.shape)\n    \n    model = lgb.LGBMClassifier(**params)\n    model.fit(\n        x_tr, \n        y_tr, \n        eval_set=[(x_tr, y_tr), (x_va, y_va)], \n        callbacks=[\n            lgb.early_stopping(stopping_rounds=100),\n        ]\n    )\n    \n    y_tr_pred = model.predict(x_tr)\n    accuracy_tr = accuracy_score(y_tr, y_tr_pred)\n    \n    y_va_pred = model.predict(x_va)\n    accuracy_va = accuracy_score(y_va, y_va_pred)\n\n    print(f'Fold {nfold}, Accuracy_tr: {accuracy_tr}, Accuracy_va: {accuracy_va}')\n    \n    metrics.append([nfold, accuracy_tr, accuracy_va])\n    \n    _imp = pd.DataFrame({\n        \"col\": X_train.columns,\n        \"imp\": model.feature_importances_,\n        \"nfold\": nfold\n    })\n    \n    imp = pd.concat([imp, _imp], axis=0, ignore_index=True)\n\n    if nfold == 0:  # nfold starts at 0, so to stop learning at the first fold, use nfold == 0 as a condition\n        break","metadata":{"execution":{"iopub.status.busy":"2024-03-26T22:28:39.682784Z","iopub.execute_input":"2024-03-26T22:28:39.683410Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"metrics = np.array(metrics)\nmetrics","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(\"tr: {:3f}+-{:2f}\".format(metrics[:, 1].mean(), metrics[:, 1].std()))\nprint(\"va: {:3f}+-{:2f}\".format(metrics[:, 2].mean(), metrics[:, 2].std()))","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"imp = imp.groupby(\"col\")[\"imp\"].agg([\"mean\", \"std\"])\nimp.columns = [\"imp\", \"imp_std\"]\nimp = imp.reset_index(drop=False)\nimp.head(20)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def gini_stability(base, w_fallingrate=88.0, w_resstd=-0.5):\n    gini_in_time = base.loc[:, [\"WEEK_NUM\", \"target\", \"score\"]]\\\n        .sort_values(\"WEEK_NUM\")\\\n        .groupby(\"WEEK_NUM\")[[\"target\", \"score\"]]\\\n        .apply(lambda x: 2*roc_auc_score(x[\"target\"], x[\"score\"])-1).tolist()\n    \n    x = np.arange(len(gini_in_time))\n    y = gini_in_time\n    a, b = np.polyfit(x, y, 1)\n    y_hat = a*x + b\n    residuals = y - y_hat\n    res_std = np.std(residuals)\n    avg_gini = np.mean(gini_in_time)\n    return avg_gini + w_fallingrate * min(0, a) + w_resstd * res_std\n\nbase_train.loc[:, 'score'] = model.predict(X_train)\n\nstability_score_train = gini_stability(base_train)\nprint(f'The stability score on Train-data is: {stability_score_train}') ","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# submission","metadata":{}},{"cell_type":"code","source":"y_pred = model.predict_proba(X_test)[:, 1]","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission = pd.DataFrame({\n    \"case_id\": test_data[\"case_id\"],\n    \"score\": y_pred\n}).set_index('case_id')\n\nsubmission.to_csv(\"./submission.csv\")","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}