{"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":"# 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","execution":{"iopub.status.busy":"2022-12-24T09:43:09.077449Z","iopub.execute_input":"2022-12-24T09:43:09.078095Z","iopub.status.idle":"2022-12-24T09:43:09.116593Z","shell.execute_reply.started":"2022-12-24T09:43:09.078008Z","shell.execute_reply":"2022-12-24T09:43:09.115460Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 1. Read libaries","metadata":{}},{"cell_type":"code","source":"import gc\nimport warnings\nimport pandas as pd\nimport xgboost as xgb\nimport numpy as np\nimport lightgbm as lgb\nfrom sklearn import metrics\nfrom lightgbm import LGBMClassifier\nfrom sklearn.preprocessing import LabelEncoder\nfrom sklearn.model_selection import train_test_split","metadata":{"execution":{"iopub.status.busy":"2022-12-24T09:43:09.118716Z","iopub.execute_input":"2022-12-24T09:43:09.119042Z","iopub.status.idle":"2022-12-24T09:43:11.281624Z","shell.execute_reply.started":"2022-12-24T09:43:09.119006Z","shell.execute_reply":"2022-12-24T09:43:11.280525Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# **2. Read data**\nWe read data from /kaggle/input/amex-data-integer-dtypes-parquet-format because this dataset in parquet format is read faster than csv format and this dataset changes data to interger when you need help saving memory","metadata":{}},{"cell_type":"code","source":"TRAIN_DATA_PATH = \"/kaggle/input/amex-parquet/train_data.parquet\"","metadata":{"execution":{"iopub.status.busy":"2022-12-24T09:43:11.282985Z","iopub.execute_input":"2022-12-24T09:43:11.283459Z","iopub.status.idle":"2022-12-24T09:43:11.289523Z","shell.execute_reply.started":"2022-12-24T09:43:11.283413Z","shell.execute_reply":"2022-12-24T09:43:11.288396Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"labels = pd.read_csv('../input/amex-default-prediction/train_labels.csv')","metadata":{"execution":{"iopub.status.busy":"2022-12-24T09:43:11.291903Z","iopub.execute_input":"2022-12-24T09:43:11.292382Z","iopub.status.idle":"2022-12-24T09:43:12.360589Z","shell.execute_reply.started":"2022-12-24T09:43:11.292347Z","shell.execute_reply":"2022-12-24T09:43:12.359444Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"labels.head()","metadata":{"execution":{"iopub.status.busy":"2022-12-24T09:43:12.361965Z","iopub.execute_input":"2022-12-24T09:43:12.362356Z","iopub.status.idle":"2022-12-24T09:43:12.380062Z","shell.execute_reply.started":"2022-12-24T09:43:12.362316Z","shell.execute_reply":"2022-12-24T09:43:12.379325Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train = pd.read_parquet('../input/amex-data-integer-dtypes-parquet-format/train.parquet')\ntest = pd.read_parquet('../input/amex-data-integer-dtypes-parquet-format/test.parquet')","metadata":{"execution":{"iopub.status.busy":"2022-12-24T09:43:12.381432Z","iopub.execute_input":"2022-12-24T09:43:12.381977Z","iopub.status.idle":"2022-12-24T09:44:13.109674Z","shell.execute_reply.started":"2022-12-24T09:43:12.381945Z","shell.execute_reply":"2022-12-24T09:44:13.108582Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 3. EDA\nThe dataset contains aggregated profile features for each customer at each statement date. Features are anonymized and normalized, and fall into the following general categories:\n* D_* = Delinquency variables\n* S_* = Spend variables\n* P_* = Payment variables\n* B_* = Balance variables\n* R_* = Risk variables \\\nwith the following features being categorical:\n\n['B_30', 'B_38', 'D_114', 'D_116', 'D_117', 'D_120', 'D_126', 'D_63', 'D_64', 'D_66', 'D_68']","metadata":{}},{"cell_type":"code","source":"print('Number of row: ' + str(len(train)))\nprint('Number of column: ' + str(len(train.columns)))\nprint(f'Train dates range is from {train[\"S_2\"].min()} to {train[\"S_2\"].max()}.')","metadata":{"execution":{"iopub.status.busy":"2022-12-24T09:44:13.111493Z","iopub.execute_input":"2022-12-24T09:44:13.112148Z","iopub.status.idle":"2022-12-24T09:44:14.079544Z","shell.execute_reply.started":"2022-12-24T09:44:13.112102Z","shell.execute_reply":"2022-12-24T09:44:14.078274Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 3.1 Missing data","metadata":{}},{"cell_type":"code","source":"print(\" \\nCount total NaN at each column in a DataFrame : \\n\\n\", train.isnull().sum())","metadata":{"execution":{"iopub.status.busy":"2022-12-24T09:44:14.081109Z","iopub.execute_input":"2022-12-24T09:44:14.082488Z","iopub.status.idle":"2022-12-24T09:44:16.694813Z","shell.execute_reply.started":"2022-12-24T09:44:14.082446Z","shell.execute_reply":"2022-12-24T09:44:16.693354Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import matplotlib.pyplot as plt\nplot_width, plot_height = (50,55)\nplt.rcParams['figure.figsize'] = (plot_width,plot_height)\ndef plot_nas(df: pd.DataFrame):\n    if df.isnull().sum().sum() != 0:\n        na_df = (df.isnull().sum() / len(df)) * 100      \n        na_df = na_df.drop(na_df[na_df == 0].index).sort_values(ascending=False)\n        missing_data = pd.DataFrame({'Missing Ratio %' :na_df})\n        missing_data.plot(kind = \"barh\")\n        plot_width, plot_height = (50,55)\n        plt.rcParams['figure.figsize'] = (plot_width,plot_height)\n        plt.show()\n    else:\n        print('No NAs found')\nplot_nas(train)","metadata":{"execution":{"iopub.status.busy":"2022-12-24T09:44:16.696899Z","iopub.execute_input":"2022-12-24T09:44:16.697483Z","iopub.status.idle":"2022-12-24T09:44:24.876983Z","shell.execute_reply.started":"2022-12-24T09:44:16.697447Z","shell.execute_reply":"2022-12-24T09:44:24.875408Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 3.2 Distribution of target variables","metadata":{}},{"cell_type":"code","source":"import matplotlib.ticker as mtick\ntmp = labels['target'].value_counts().div(len(labels)).mul(100)\nax = tmp.plot.bar(x=tmp.index, y=tmp.values, rot=0)\nfor container in ax.containers:\n    ax.bar_label(ax.containers[0], fmt='%.f%%')\n    ax.yaxis.set_major_formatter(mtick.PercentFormatter())","metadata":{"execution":{"iopub.status.busy":"2022-12-24T09:44:24.882125Z","iopub.execute_input":"2022-12-24T09:44:24.882699Z","iopub.status.idle":"2022-12-24T09:44:25.693939Z","shell.execute_reply.started":"2022-12-24T09:44:24.882634Z","shell.execute_reply":"2022-12-24T09:44:25.692719Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 4. Preprocessing\nWe group data by customer id and create feature first, mean, std, min, max, last for numerical features and feature first, mean, std, min, max, last for categorical feature","metadata":{}},{"cell_type":"code","source":"cat_features = [\n        \"B_30\",\n        \"B_38\",\n        \"D_114\",\n        \"D_116\",\n        \"D_117\",\n        \"D_120\",\n        \"D_126\",\n        \"D_63\",\n        \"D_64\",\n        \"D_66\",\n        \"D_68\",\n    ]\nfeatures = train.drop(['customer_ID', 'S_2'], axis = 1).columns.to_list()\nnum_features = [col for col in features if col not in cat_features]\ntrain_num_agg = train.groupby(\"customer_ID\")[num_features].agg(['first', 'mean', 'min', 'max', 'last'])\ntrain_num_agg.columns = ['_'.join(x) for x in train_num_agg.columns]\ntrain_num_agg.reset_index(inplace = True)\n\ntrain_cat_agg = train.groupby(\"customer_ID\")[cat_features].agg(['count', 'first', 'last'])\ntrain_cat_agg.columns = ['_'.join(x) for x in train_cat_agg.columns]\ntrain_cat_agg.reset_index(inplace = True)\n\ntrain = train_num_agg.merge(train_cat_agg, how = 'inner', on = 'customer_ID').merge(labels, how = 'inner', on = 'customer_ID')\ndel train_num_agg, train_cat_agg        \ngc.collect()\nprint(train.shape) \n","metadata":{"execution":{"iopub.status.busy":"2022-12-24T09:44:25.695828Z","iopub.execute_input":"2022-12-24T09:44:25.696219Z","iopub.status.idle":"2022-12-24T09:47:23.811129Z","shell.execute_reply.started":"2022-12-24T09:44:25.696186Z","shell.execute_reply":"2022-12-24T09:47:23.810066Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"cat_features = [\n        \"B_30\",\n        \"B_38\",\n        \"D_114\",\n        \"D_116\",\n        \"D_117\",\n        \"D_120\",\n        \"D_126\",\n        \"D_63\",\n        \"D_64\",\n        \"D_66\",\n        \"D_68\"\n    ]\ngc.collect()\ntest_num_agg = test.groupby(\"customer_ID\")[num_features].agg(['first', 'mean', 'min', 'max', 'last'])\ntest_num_agg.columns = ['_'.join(x) for x in test_num_agg.columns]\ntest_num_agg.reset_index(inplace = True)\ntest_cat_agg = test.groupby(\"customer_ID\")[cat_features].agg(['count', 'first', 'last'])\ntest_cat_agg.columns = ['_'.join(x) for x in test_cat_agg.columns]\ntest_cat_agg.reset_index(inplace = True)\ntest = test_num_agg.merge(test_cat_agg, how = 'inner', on = 'customer_ID')\ndel test_num_agg, test_cat_agg\ngc.collect()\n","metadata":{"execution":{"iopub.status.busy":"2022-12-24T09:47:23.812332Z","iopub.execute_input":"2022-12-24T09:47:23.812638Z","iopub.status.idle":"2022-12-24T09:53:33.629544Z","shell.execute_reply.started":"2022-12-24T09:47:23.812611Z","shell.execute_reply":"2022-12-24T09:53:33.628337Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"cat_features = [f\"{cf}_last\" for cf in cat_features]\nfor cat_col in cat_features:\n    encoder = LabelEncoder()\n    train[cat_col] = encoder.fit_transform(train[cat_col])\n    test[cat_col] = encoder.transform(test[cat_col])\nprint(train[cat_col])\ntrain[train.select_dtypes('float64').columns] = train.select_dtypes('float64').astype('float32')\ntrain[train.select_dtypes('int64').columns] = train.select_dtypes('int64').astype('int32')","metadata":{"execution":{"iopub.status.busy":"2022-12-24T09:53:33.631212Z","iopub.execute_input":"2022-12-24T09:53:33.632636Z","iopub.status.idle":"2022-12-24T09:53:39.501998Z","shell.execute_reply.started":"2022-12-24T09:53:33.632588Z","shell.execute_reply":"2022-12-24T09:53:39.500777Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def amex_metric(y_true, y_pred):\n    labels = np.transpose(np.array([y_true, y_pred]))\n    labels = labels[labels[:, 1].argsort()[::-1]]\n    weights = np.where(labels[:,0]==0, 20, 1)\n    cut_vals = labels[np.cumsum(weights) <= int(0.04 * np.sum(weights))]\n    top_four = np.sum(cut_vals[:,0]) / np.sum(labels[:,0])\n    gini = [0,0]\n    for i in [1,0]:\n        labels = np.transpose(np.array([y_true, y_pred]))\n        labels = labels[labels[:, i].argsort()[::-1]]\n        weight = np.where(labels[:,0]==0, 20, 1)\n        weight_random = np.cumsum(weight / np.sum(weight))\n        total_pos = np.sum(labels[:, 0] *  weight)\n        cum_pos_found = np.cumsum(labels[:, 0] * weight)\n        lorentz = cum_pos_found / total_pos\n        gini[i] = np.sum((lorentz - weight_random) * weight)\n    return 0.5 * (gini[1]/gini[0] + top_four)\n\ndef amex_metric_np(preds, target):\n    indices = np.argsort(preds)[::-1]\n    preds, target = preds[indices], target[indices]\n    weight = 20.0 - target * 19.0\n    cum_norm_weight = (weight / weight.sum()).cumsum()\n    four_pct_mask = cum_norm_weight <= 0.04\n    d = np.sum(target[four_pct_mask]) / np.sum(target)\n    weighted_target = target * weight\n    lorentz = (weighted_target / weighted_target.sum()).cumsum()\n    gini = ((lorentz - cum_norm_weight) * weight).sum()\n    n_pos = np.sum(target)\n    n_neg = target.shape[0] - n_pos\n    gini_max = 10 * n_neg * (n_pos + 20 * n_neg - 19) / (n_pos + 20 * n_neg)\n    g = gini / gini_max\n    return 0.5 * (g + d)\ndef lgb_amex_metric(y_pred, y_true):\n    y_true = y_true.get_label()\n    return 'amex_metric', amex_metric(y_true, y_pred), True","metadata":{"execution":{"iopub.status.busy":"2022-12-24T09:53:39.503725Z","iopub.execute_input":"2022-12-24T09:53:39.504168Z","iopub.status.idle":"2022-12-24T09:53:39.519622Z","shell.execute_reply.started":"2022-12-24T09:53:39.504127Z","shell.execute_reply":"2022-12-24T09:53:39.518807Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 5. Model\nWe use lgb model to predict","metadata":{}},{"cell_type":"code","source":"features = [col for col in train.columns if col not in ['customer_ID', 'target']]\n\nX = train[features] # Features\ny = train.target # Target variable\n# Split dataset into training set and test set\nX_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=1)\nlgb_train = lgb.Dataset(X_train, y_train)\nlgb_valid = lgb.Dataset(X_test, y_test)\nparams = {\n        'objective': 'binary',\n        'metric': 'binary_logloss',\n        'boosting': 'dart',\n        'seed': 42,\n        'num_leaves': 100,\n        'learning_rate': 0.01,\n        'feature_fraction': 0.20,\n        'bagging_freq': 10,\n        'bagging_fraction': 0.50,\n        'n_jobs': -1,\n        'lambda_l2': 2,\n        'min_data_in_leaf': 40,\n        }\nmodel = lgb.train(\n            params = params,\n            train_set = lgb_train,\n            num_boost_round = 500,\n            valid_sets = [lgb_train, lgb_valid],\n            early_stopping_rounds = 1500,\n            verbose_eval = 500,\n            feval = lgb_amex_metric\n            )\n","metadata":{"execution":{"iopub.status.busy":"2022-12-24T09:53:39.520745Z","iopub.execute_input":"2022-12-24T09:53:39.521532Z","iopub.status.idle":"2022-12-24T10:04:05.944592Z","shell.execute_reply.started":"2022-12-24T09:53:39.521497Z","shell.execute_reply":"2022-12-24T10:04:05.943224Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 6. Inference","metadata":{}},{"cell_type":"code","source":"len(features)","metadata":{"execution":{"iopub.status.busy":"2022-12-24T10:04:05.946333Z","iopub.execute_input":"2022-12-24T10:04:05.947457Z","iopub.status.idle":"2022-12-24T10:04:05.955627Z","shell.execute_reply.started":"2022-12-24T10:04:05.947414Z","shell.execute_reply":"2022-12-24T10:04:05.954485Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_pred = model.predict(test[features])\ntest_df = pd.DataFrame({'customer_ID': test['customer_ID'], 'prediction': test_pred})\ntest_df.to_csv(f'submissin.csv', index = False)\n","metadata":{"execution":{"iopub.status.busy":"2022-12-24T10:04:05.957943Z","iopub.execute_input":"2022-12-24T10:04:05.958485Z","iopub.status.idle":"2022-12-24T10:04:52.665686Z","shell.execute_reply.started":"2022-12-24T10:04:05.958441Z","shell.execute_reply":"2022-12-24T10:04:52.664214Z"},"trusted":true},"execution_count":null,"outputs":[]}]}