{"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"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import numpy as np #矩阵预算相关的 \nimport pandas as pd  # csv文件处理相关的\nimport matplotlib.pyplot as plt # 画图的相关的一个包\nfrom matplotlib.ticker import MaxNLocator\nfrom matplotlib.colors import ListedColormap\nfrom cycler import cycler\nfrom IPython.display import display\nimport datetime\nimport scipy.stats\nimport warnings\nfrom colorama import Fore, Back, Style \nimport gc\n\nfrom sklearn.model_selection import StratifiedKFold # 交叉验证\nfrom sklearn.calibration import CalibrationDisplay # 显示相关的包\nfrom lightgbm import LGBMClassifier, log_evaluation # 本次所使用的模型\n\nplt.rcParams['axes.facecolor'] = '#0057b8' # blue\nplt.rcParams['axes.prop_cycle'] = cycler(color=['#ffd700'] +\n                                         plt.rcParams['axes.prop_cycle'].by_key()['color'][1:])\nplt.rcParams['text.color'] = 'w'\n\nINFERENCE = True # set to False if you only want to cross-validate\n","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2022-06-19T16:19:52.219452Z","iopub.execute_input":"2022-06-19T16:19:52.219898Z","iopub.status.idle":"2022-06-19T16:19:54.3844Z","shell.execute_reply.started":"2022-06-19T16:19:52.219806Z","shell.execute_reply":"2022-06-19T16:19:54.383498Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# @yunchonggan's fast metric implementation\n# From https://www.kaggle.com/competitions/amex-default-prediction/discussion/328020\ndef amex_metric(y_true: np.array, y_pred: np.array) -> float:\n\n    # 计算正负样本的个数\n    n_pos = y_true.sum()\n    n_neg = y_true.shape[0] - n_pos\n\n    # 根据违约率来排序，这样的话，违约率高的排前面，你会得到一个索引\n    indices = np.argsort(y_pred)[::-1]\n    # 根据这个索引，对preds和target进行一个排序\n    preds, target = y_pred[indices], y_true[indices]\n\n    # filter the top 4% by cumulative row weights\n    # 计算权重，违约为1（正样本） ， 不违约（负样本）为 20\n    weight = 20.0 - target * 19.0\n    # 进行一个累加的操作，cumsum是累加\n    # 假如权重和为1000，40.\n    # 如果你的预测比较准，那么里面正确的违约的正样本会比较多，正样本指的是为1的样本\n    # 如果预测不准，比如说带了一个负样本，那么就只能最多有20个正样本\n    # \n    cum_norm_weight = (weight / weight.sum()).cumsum()\n    # 下面是一个过滤\n    four_pct_filter = cum_norm_weight <= 0.04\n\n    # default rate captured at 4%\n    d = target[four_pct_filter].sum() / n_pos\n\n    # weighted gini coefficient\n    # 10个样本，比如说4个违约，6不违约,真正的数据\n    # 10个样本，比如说我们有预测的数据\n    # 真正的样本: y_true: 0,1,0,0,1,1,0,0,0,1\n    # 预测的结果：y_pred: 0，0.8，0.1，0.1，0，0，0，0，0，0.9\n    # preds: 0.9,0.8,0,0,0,0,0,0,0\n    # target: 1,1,0,0,1,1,0,0,0,0\n    # n_pos = 4\n    # lorentz:0.25,0.5,0.5,0.5,0.75,1.0,1,1,1,1\n    # cum_norm_weight: 1/124,2/124,22/124,42/124,43/124,44/124,64/124,84/124,104/124,/124/124\n    # weight: 1, 1, 20, 20, 1, 1, 20, 20, 1, 1, 1, 1\n    \n    lorentz = (target / n_pos).cumsum()\n    gini = ((lorentz - cum_norm_weight) * weight).sum()\n\n    # max weighted gini coefficient\n    gini_max = 10 * n_neg * (1 - 19 / (n_pos + 20 * n_neg))\n\n    # normalized weighted gini coefficient\n    g = gini / gini_max\n\n    return 0.5 * (g + d)\n\ndef lgb_amex_metric(y_true, y_pred):\n    \"\"\"The competition metric with lightgbm's calling convention\"\"\"\n    return ('amex',\n            amex_metric(y_true, y_pred),\n            True)","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2022-06-19T16:19:54.38586Z","iopub.execute_input":"2022-06-19T16:19:54.386178Z","iopub.status.idle":"2022-06-19T16:19:54.395263Z","shell.execute_reply.started":"2022-06-19T16:19:54.38615Z","shell.execute_reply":"2022-06-19T16:19:54.394545Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%%time\nfeatures_avg = ['B_1', 'B_2', 'B_3', 'B_4', 'B_5', 'B_6', 'B_8', 'B_9', 'B_10', 'B_11', 'B_12', 'B_13', 'B_14', 'B_15', 'B_16', 'B_17', 'B_18', 'B_19', 'B_20', 'B_21', 'B_22', 'B_23', 'B_24', 'B_25', 'B_28', 'B_29', 'B_30', 'B_32', 'B_33', 'B_37', 'B_38', 'B_39', 'B_40', 'B_41', 'B_42', 'D_39', 'D_41', 'D_42', 'D_43', 'D_44', 'D_45', 'D_46', 'D_47', 'D_48', 'D_50', 'D_51', 'D_53', 'D_54', 'D_55', 'D_58', 'D_59', 'D_60', 'D_61', 'D_62', 'D_65', 'D_66', 'D_69', 'D_70', 'D_71', 'D_72', 'D_73', 'D_74', 'D_75', 'D_76', 'D_77', 'D_78', 'D_80', 'D_82', 'D_84', 'D_86', 'D_91', 'D_92', 'D_94', 'D_96', 'D_103', 'D_104', 'D_108', 'D_112', 'D_113', 'D_114', 'D_115', 'D_117', 'D_118', 'D_119', 'D_120', 'D_121', 'D_122', 'D_123', 'D_124', 'D_125', 'D_126', 'D_128', 'D_129', 'D_131', 'D_132', 'D_133', 'D_134', 'D_135', 'D_136', 'D_140', 'D_141', 'D_142', 'D_144', 'D_145', 'P_2', 'P_3', 'P_4', 'R_1', 'R_2', 'R_3', 'R_7', 'R_8', 'R_9', 'R_10', 'R_11', 'R_14', 'R_15', 'R_16', 'R_17', 'R_20', 'R_21', 'R_22', 'R_24', 'R_26', 'R_27', 'S_3', 'S_5', 'S_6', 'S_7', 'S_9', 'S_11', 'S_12', 'S_13', 'S_15', 'S_16', 'S_18', 'S_22', 'S_23', 'S_25', 'S_26']\nfeatures_min = ['B_2', 'B_4', 'B_5', 'B_9', 'B_13', 'B_14', 'B_15', 'B_16', 'B_17', 'B_19', 'B_20', 'B_28', 'B_29', 'B_33', 'B_36', 'B_42', 'D_39', 'D_41', 'D_42', 'D_45', 'D_46', 'D_48', 'D_50', 'D_51', 'D_53', 'D_55', 'D_56', 'D_58', 'D_59', 'D_60', 'D_62', 'D_70', 'D_71', 'D_74', 'D_75', 'D_78', 'D_83', 'D_102', 'D_112', 'D_113', 'D_115', 'D_118', 'D_119', 'D_121', 'D_122', 'D_128', 'D_132', 'D_140', 'D_141', 'D_144', 'D_145', 'P_2', 'P_3', 'R_1', 'R_27', 'S_3', 'S_5', 'S_7', 'S_9', 'S_11', 'S_12', 'S_23', 'S_25']\nfeatures_max = ['B_1', 'B_2', 'B_3', 'B_4', 'B_5', 'B_6', 'B_7', 'B_8', 'B_9', 'B_10', 'B_12', 'B_13', 'B_14', 'B_15', 'B_16', 'B_17', 'B_18', 'B_19', 'B_21', 'B_23', 'B_24', 'B_25', 'B_29', 'B_30', 'B_33', 'B_37', 'B_38', 'B_39', 'B_40', 'B_42', 'D_39', 'D_41', 'D_42', 'D_43', 'D_44', 'D_45', 'D_46', 'D_47', 'D_48', 'D_49', 'D_50', 'D_52', 'D_55', 'D_56', 'D_58', 'D_59', 'D_60', 'D_61', 'D_63', 'D_64', 'D_65', 'D_70', 'D_71', 'D_72', 'D_73', 'D_74', 'D_76', 'D_77', 'D_78', 'D_80', 'D_82', 'D_84', 'D_91', 'D_102', 'D_105', 'D_107', 'D_110', 'D_111', 'D_112', 'D_115', 'D_116', 'D_117', 'D_118', 'D_119', 'D_121', 'D_122', 'D_123', 'D_124', 'D_125', 'D_126', 'D_128', 'D_131', 'D_132', 'D_133', 'D_134', 'D_135', 'D_136', 'D_138', 'D_140', 'D_141', 'D_142', 'D_144', 'D_145', 'P_2', 'P_3', 'P_4', 'R_1', 'R_3', 'R_5', 'R_6', 'R_7', 'R_8', 'R_10', 'R_11', 'R_14', 'R_17', 'R_20', 'R_26', 'R_27', 'S_3', 'S_5', 'S_7', 'S_8', 'S_11', 'S_12', 'S_13', 'S_15', 'S_16', 'S_22', 'S_23', 'S_24', 'S_25', 'S_26', 'S_27']\nfeatures_last = ['B_1', 'B_2', 'B_3', 'B_4', 'B_5', 'B_6', 'B_7', 'B_8', 'B_9', 'B_10', 'B_11', 'B_12', 'B_13', 'B_14', 'B_15', 'B_16', 'B_17', 'B_18', 'B_19', 'B_20', 'B_21', 'B_22', 'B_23', 'B_24', 'B_25', 'B_26', 'B_28', 'B_29', 'B_30', 'B_32', 'B_33', 'B_36', 'B_37', 'B_38', 'B_39', 'B_40', 'B_41', 'B_42', 'D_39', 'D_41', 'D_42', 'D_43', 'D_44', 'D_45', 'D_46', 'D_47', 'D_48', 'D_49', 'D_50', 'D_51', 'D_52', 'D_53', 'D_54', 'D_55', 'D_56', 'D_58', 'D_59', 'D_60', 'D_61', 'D_62', 'D_63', 'D_64', 'D_65', 'D_69', 'D_70', 'D_71', 'D_72', 'D_73', 'D_75', 'D_76', 'D_77', 'D_78', 'D_79', 'D_80', 'D_81', 'D_82', 'D_83', 'D_86', 'D_91', 'D_96', 'D_105', 'D_106', 'D_112', 'D_114', 'D_119', 'D_120', 'D_121', 'D_122', 'D_124', 'D_125', 'D_126', 'D_127', 'D_130', 'D_131', 'D_132', 'D_133', 'D_134', 'D_138', 'D_140', 'D_141', 'D_142', 'D_145', 'P_2', 'P_3', 'P_4', 'R_1', 'R_2', 'R_3', 'R_4', 'R_5', 'R_6', 'R_7', 'R_8', 'R_9', 'R_10', 'R_11', 'R_12', 'R_13', 'R_14', 'R_15', 'R_19', 'R_20', 'R_26', 'R_27', 'S_3', 'S_5', 'S_6', 'S_7', 'S_8', 'S_9', 'S_11', 'S_12', 'S_13', 'S_16', 'S_19', 'S_20', 'S_22', 'S_23', 'S_24', 'S_25', 'S_26', 'S_27']\nfor i in ['test', 'train'] if INFERENCE else ['train']:\n    df = pd.read_parquet(f'../input/amex-data-integer-dtypes-parquet-format/{i}.parquet')\n    cid = pd.Categorical(df.pop('customer_ID'), ordered=True)\n    last = (cid != np.roll(cid, -1)) # mask for last statement of every customer\n    if 'target' in df.columns:\n        df.drop(columns=['target'], inplace=True)\n    gc.collect()\n    print('Read', i)\n    df_avg = (df\n              .groupby(cid)\n              .mean()[features_avg]\n              .rename(columns={f: f\"{f}_avg\" for f in features_avg})\n             )\n    gc.collect()\n    print('Computed avg', i)\n    df_min = (df\n              .groupby(cid)\n              .min()[features_min]\n              .rename(columns={f: f\"{f}_min\" for f in features_min})\n             )\n    gc.collect()\n    print('Computed min', i)\n    df_max = (df\n              .groupby(cid)\n              .max()[features_max]\n              .rename(columns={f: f\"{f}_max\" for f in features_max})\n             )\n    gc.collect()\n    print('Computed max', i)\n    df = (df.loc[last, features_last]\n          .rename(columns={f: f\"{f}_last\" for f in features_last})\n          .set_index(np.asarray(cid[last]))\n         )\n    gc.collect()\n    print('Computed last', i)\n    df = pd.concat([df, df_min, df_max, df_avg], axis=1)\n    if i == 'train': train = df\n    else: test = df\n    print(f\"{i} shape: {df.shape}\")\n    del df, df_avg, df_min, df_max, cid, last\n\ntarget = pd.read_csv('../input/amex-default-prediction/train_labels.csv').target.values\nprint(f\"target shape: {target.shape}\")","metadata":{"execution":{"iopub.status.busy":"2022-06-19T16:19:54.396883Z","iopub.execute_input":"2022-06-19T16:19:54.397456Z","iopub.status.idle":"2022-06-19T16:26:09.846347Z","shell.execute_reply.started":"2022-06-19T16:19:54.397423Z","shell.execute_reply":"2022-06-19T16:26:09.845171Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%%time\n# Cross-validation of the classifier\n\nONLY_FIRST_FOLD = False\n\nfeatures = [f for f in train.columns if f != 'customer_ID' and f != 'target']\n\ndef my_booster(random_state=1, n_estimators=1200):\n    return LGBMClassifier(n_estimators=n_estimators,# 1200次\n                          learning_rate=0.03, reg_lambda=50, # 2次方的正则化\n                          min_child_samples=2400,\n                          num_leaves=95,\n                          colsample_bytree=0.19, # 189个，除了id\n                          max_bins=511, random_state=random_state)\n      \nprint(f\"{len(features)} features\")\nscore_list = []\ny_pred_list = []\nkf = StratifiedKFold(n_splits=6)\nfor fold, (idx_tr, idx_va) in enumerate(kf.split(train, target)):\n    X_tr, X_va, y_tr, y_va, model = None, None, None, None, None\n    start_time = datetime.datetime.now()\n    X_tr = train.iloc[idx_tr][features]\n    X_va = train.iloc[idx_va][features]\n    y_tr = target[idx_tr]\n    y_va = target[idx_va]\n    \n    model = my_booster()\n    with warnings.catch_warnings():\n        warnings.filterwarnings('ignore', category=UserWarning)\n        model.fit(X_tr, y_tr,\n                  eval_set = [(X_va, y_va)], \n                  eval_metric=[lgb_amex_metric],\n                  callbacks=[log_evaluation(100)])\n    X_tr, y_tr = None, None\n    y_va_pred = model.predict_proba(X_va, raw_score=True)\n    score = amex_metric(y_va, y_va_pred)\n    n_trees = model.best_iteration_\n    if n_trees is None: n_trees = model.n_estimators\n    print(f\"{Fore.GREEN}{Style.BRIGHT}Fold {fold} | {str(datetime.datetime.now() - start_time)[-12:-7]} |\"\n          f\" {n_trees:5} trees |\"\n          f\"                Score = {score:.5f}{Style.RESET_ALL}\")\n    score_list.append(score)\n    \n    if INFERENCE:\n        y_pred_list.append(model.predict_proba(test[features], raw_score=True))\n        \n    if ONLY_FIRST_FOLD: break # we only want the first fold\n    \nprint(f\"{Fore.GREEN}{Style.BRIGHT}OOF Score:                       {np.mean(score_list):.5f}{Style.RESET_ALL}\")","metadata":{"execution":{"iopub.status.busy":"2022-06-19T16:26:09.84855Z","iopub.execute_input":"2022-06-19T16:26:09.848905Z","iopub.status.idle":"2022-06-19T17:06:02.353949Z","shell.execute_reply.started":"2022-06-19T16:26:09.848867Z","shell.execute_reply":"2022-06-19T17:06:02.352313Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def sigmoid(log_odds):\n    return 1 / (1 + np.exp(-log_odds))\n\nplt.figure(figsize=(10, 4))\nplt.hist(sigmoid(y_va_pred[y_va == 0]), bins=np.linspace(0, 1, 101),\n         alpha=0.5, density=True, label='0')\nplt.hist(sigmoid(y_va_pred[y_va == 1]), bins=np.linspace(0, 1, 101),\n         alpha=0.5, density=True, label='1')\nplt.xlabel('y_pred')\nplt.ylabel('density')\nplt.title('OOF Prediction histogram', color='k')\nplt.legend()\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-06-19T17:13:54.486559Z","iopub.execute_input":"2022-06-19T17:13:54.486986Z","iopub.status.idle":"2022-06-19T17:13:55.047448Z","shell.execute_reply.started":"2022-06-19T17:13:54.486951Z","shell.execute_reply":"2022-06-19T17:13:55.046512Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.figure(figsize=(12, 4))\nCalibrationDisplay.from_predictions(y_va, sigmoid(y_va_pred), n_bins=50,\n                                    strategy='quantile', ax=plt.gca())\nplt.title('Probability calibration')\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-06-19T17:06:02.716511Z","iopub.execute_input":"2022-06-19T17:06:02.717687Z","iopub.status.idle":"2022-06-19T17:06:02.94387Z","shell.execute_reply.started":"2022-06-19T17:06:02.717639Z","shell.execute_reply":"2022-06-19T17:06:02.942918Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"if INFERENCE:\n    sub = pd.DataFrame({'customer_ID': test.index,\n                        'prediction': np.mean(y_pred_list, axis=0)})\n    sub.to_csv('submission.csv', index=False)\n    display(sub)","metadata":{"execution":{"iopub.status.busy":"2022-06-19T17:06:02.945588Z","iopub.execute_input":"2022-06-19T17:06:02.946311Z","iopub.status.idle":"2022-06-19T17:06:08.717493Z","shell.execute_reply.started":"2022-06-19T17:06:02.946269Z","shell.execute_reply":"2022-06-19T17:06:08.716212Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.figure(figsize=(12, 4))\nplt.hist(sigmoid(sub.prediction), bins=np.linspace(0, 1, 101), density=True)\nplt.hist(sigmoid(y_va_pred), bins=np.linspace(0, 1, 101), rwidth=0.5, color='orange', density=True)\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-06-19T17:14:12.39398Z","iopub.execute_input":"2022-06-19T17:14:12.394399Z","iopub.status.idle":"2022-06-19T17:14:12.987777Z","shell.execute_reply.started":"2022-06-19T17:14:12.394345Z","shell.execute_reply":"2022-06-19T17:14:12.987046Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}