{"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":74571,"databundleVersionId":8671431,"sourceType":"competition"}],"dockerImageVersionId":30673,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import pandas as pd\nimport numpy as np\nimport matplotlib.pyplot as plt\nimport seaborn as sns","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2024-06-28T01:48:51.806151Z","iopub.execute_input":"2024-06-28T01:48:51.806599Z","iopub.status.idle":"2024-06-28T01:48:55.153169Z","shell.execute_reply.started":"2024-06-28T01:48:51.806552Z","shell.execute_reply":"2024-06-28T01:48:55.151818Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#데이터 불러오기\ntrain = pd.read_csv(\"/kaggle/input/affel-ds2-credit-card/train.csv\")\ntest = pd.read_csv(\"/kaggle/input/affel-ds2-credit-card/test.csv\")","metadata":{"execution":{"iopub.status.busy":"2024-06-28T01:48:55.158497Z","iopub.execute_input":"2024-06-28T01:48:55.158862Z","iopub.status.idle":"2024-06-28T01:48:59.649521Z","shell.execute_reply.started":"2024-06-28T01:48:55.158831Z","shell.execute_reply":"2024-06-28T01:48:59.648165Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 데이터 전처리","metadata":{}},{"cell_type":"code","source":"train.info()\n#결측치 없는것 확인됨","metadata":{"execution":{"iopub.status.busy":"2024-06-28T01:48:59.652897Z","iopub.execute_input":"2024-06-28T01:48:59.653305Z","iopub.status.idle":"2024-06-28T01:48:59.699234Z","shell.execute_reply.started":"2024-06-28T01:48:59.653271Z","shell.execute_reply":"2024-06-28T01:48:59.697541Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train.head()","metadata":{"execution":{"iopub.status.busy":"2024-06-28T01:48:59.700773Z","iopub.execute_input":"2024-06-28T01:48:59.701243Z","iopub.status.idle":"2024-06-28T01:48:59.741891Z","shell.execute_reply.started":"2024-06-28T01:48:59.701202Z","shell.execute_reply":"2024-06-28T01:48:59.740705Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train.describe()","metadata":{"execution":{"iopub.status.busy":"2024-06-28T01:48:59.743429Z","iopub.execute_input":"2024-06-28T01:48:59.743795Z","iopub.status.idle":"2024-06-28T01:49:00.093243Z","shell.execute_reply.started":"2024-06-28T01:48:59.743764Z","shell.execute_reply":"2024-06-28T01:49:00.092052Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#사기 건수가 360건 밖에 안된다.\ntrain.value_counts()","metadata":{"execution":{"iopub.status.busy":"2024-06-28T01:49:00.094972Z","iopub.execute_input":"2024-06-28T01:49:00.095457Z","iopub.status.idle":"2024-06-28T01:49:01.812737Z","shell.execute_reply.started":"2024-06-28T01:49:00.095416Z","shell.execute_reply":"2024-06-28T01:49:01.811357Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#중복값 찾기\ntrain[train.duplicated()]\n#중복값 없음","metadata":{"execution":{"iopub.status.busy":"2024-06-28T01:49:01.814468Z","iopub.execute_input":"2024-06-28T01:49:01.814865Z","iopub.status.idle":"2024-06-28T01:49:02.288764Z","shell.execute_reply.started":"2024-06-28T01:49:01.814834Z","shell.execute_reply":"2024-06-28T01:49:02.287419Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#id 날리기\ntrain.drop('id', axis=1, inplace=True)","metadata":{"execution":{"iopub.status.busy":"2024-06-28T01:49:02.290168Z","iopub.execute_input":"2024-06-28T01:49:02.290503Z","iopub.status.idle":"2024-06-28T01:49:02.313155Z","shell.execute_reply.started":"2024-06-28T01:49:02.290474Z","shell.execute_reply":"2024-06-28T01:49:02.311640Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#데이터 자세히 확인하기\npd.set_option('display.max_columns', None)\ntrain.describe()","metadata":{"execution":{"iopub.status.busy":"2024-06-28T01:49:02.314906Z","iopub.execute_input":"2024-06-28T01:49:02.315348Z","iopub.status.idle":"2024-06-28T01:49:02.658143Z","shell.execute_reply.started":"2024-06-28T01:49:02.315297Z","shell.execute_reply":"2024-06-28T01:49:02.656864Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#time과 amount만 스케일링이 되어있지 않아 스케일링한다\n#time은 아웃라이어가 없는 시계열 데이터라 스탠다드 스케일러로, amount는 아웃라이어 때문에 로버스트 스케일러로 한다.\nfrom sklearn.preprocessing import StandardScaler\nfrom sklearn.preprocessing import RobustScaler\n\ns_scaler = StandardScaler()\nr_scaler = RobustScaler()\n\ntrain['s_Time'] = s_scaler.fit_transform(train['Time'].values.reshape(-1,1))\ntrain['s_Amount'] = r_scaler.fit_transform(train['Amount'].values.reshape(-1,1))\n\n\n#원데이터 삭제\ntrain.drop(['Time', 'Amount'], axis=1, inplace=True)","metadata":{"execution":{"iopub.status.busy":"2024-06-28T01:49:02.659677Z","iopub.execute_input":"2024-06-28T01:49:02.660059Z","iopub.status.idle":"2024-06-28T01:49:02.992687Z","shell.execute_reply.started":"2024-06-28T01:49:02.660028Z","shell.execute_reply":"2024-06-28T01:49:02.991520Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#정리하기\nmove_col = train.pop('s_Time')\ntrain.insert(0, 's_Time', move_col)\n\nmove_col = train.pop('s_Amount')\ntrain.insert(1, 's_Amount', move_col)","metadata":{"execution":{"iopub.status.busy":"2024-06-28T01:49:02.994161Z","iopub.execute_input":"2024-06-28T01:49:02.994510Z","iopub.status.idle":"2024-06-28T01:49:03.003684Z","shell.execute_reply.started":"2024-06-28T01:49:02.994476Z","shell.execute_reply":"2024-06-28T01:49:03.002394Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train.describe()","metadata":{"execution":{"iopub.status.busy":"2024-06-28T01:49:03.009706Z","iopub.execute_input":"2024-06-28T01:49:03.010155Z","iopub.status.idle":"2024-06-28T01:49:03.407981Z","shell.execute_reply.started":"2024-06-28T01:49:03.010116Z","shell.execute_reply":"2024-06-28T01:49:03.406774Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#test.csv를 보니 time을 드랍해야 할 것 같다. 원 데이터에서 무작위 추출이 아니라 뒷부분을 잘랐다.\ntrain.drop('s_Time', axis=1, inplace=True)","metadata":{"execution":{"iopub.status.busy":"2024-06-28T01:49:03.409301Z","iopub.execute_input":"2024-06-28T01:49:03.409650Z","iopub.status.idle":"2024-06-28T01:49:03.431164Z","shell.execute_reply.started":"2024-06-28T01:49:03.409620Z","shell.execute_reply":"2024-06-28T01:49:03.429962Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 모델 만들기","metadata":{}},{"cell_type":"code","source":"#train과 test 나누기, 불균형한 클래스 때문에 stratified Kfold로 나누기\nfrom sklearn.model_selection import train_test_split\n\nX_train, X_test, y_train, y_test = train_test_split(train.drop(['Class'], axis=1), train['Class'], test_size=0.3, random_state=0, stratify=train['Class'])","metadata":{"execution":{"iopub.status.busy":"2024-06-28T01:49:03.432584Z","iopub.execute_input":"2024-06-28T01:49:03.433123Z","iopub.status.idle":"2024-06-28T01:49:03.730712Z","shell.execute_reply.started":"2024-06-28T01:49:03.433057Z","shell.execute_reply":"2024-06-28T01:49:03.729238Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 나누어진 것 확인하기\nX_train.shape, X_test.shape, y_train.shape, y_test.shape","metadata":{"execution":{"iopub.status.busy":"2024-06-28T01:49:03.732341Z","iopub.execute_input":"2024-06-28T01:49:03.732754Z","iopub.status.idle":"2024-06-28T01:49:03.741480Z","shell.execute_reply.started":"2024-06-28T01:49:03.732721Z","shell.execute_reply":"2024-06-28T01:49:03.740113Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score, confusion_matrix, roc_auc_score\n\n#평가하는 함수\ndef geteval(i):\n    acc = accuracy_score(y_test, i)\n    prec = precision_score(y_test, i)\n    recall = recall_score(y_test, i)\n    f1 = f1_score(y_test, i)\n    confu = confusion_matrix(y_test, i)\n    roc_auc = roc_auc_score(y_test, i)\n\n    print('accuracy:', round(acc,5))\n    print('precision:', round(prec,5))\n    print('recall:', round(recall, 5))\n    print('f1', round(f1, 5))\n    print('roc_auc', round(roc_auc, 5))\n    ","metadata":{"execution":{"iopub.status.busy":"2024-06-28T01:49:03.743023Z","iopub.execute_input":"2024-06-28T01:49:03.743471Z","iopub.status.idle":"2024-06-28T01:49:03.753127Z","shell.execute_reply.started":"2024-06-28T01:49:03.743427Z","shell.execute_reply":"2024-06-28T01:49:03.751594Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"랜덤포레스트 - 불균형 데이터일 때 랜덤포레스트를 사용하는 것이 좋다.","metadata":{}},{"cell_type":"code","source":"#랜덤포레스트 모델\nfrom sklearn.ensemble import RandomForestClassifier\n\n# 랜덤포레스트 모델 학습\nrf_model = RandomForestClassifier()\nrf_model.fit(X_train, y_train)","metadata":{"execution":{"iopub.status.busy":"2024-06-28T01:49:03.754752Z","iopub.execute_input":"2024-06-28T01:49:03.755221Z","iopub.status.idle":"2024-06-28T01:50:58.770209Z","shell.execute_reply.started":"2024-06-28T01:49:03.755179Z","shell.execute_reply":"2024-06-28T01:50:58.768668Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score, confusion_matrix, roc_auc_score\n\n# 랜덤포레스트 예측\nrf_pred = rf_model.predict(X_test)\nrf_pred_proba = rf_model.predict_proba(X_test)[:, 1]\n\n#평가항목 적용\nrf_acc = accuracy_score(y_test, rf_pred)\nrf_prec = precision_score(y_test, rf_pred)\nrf_recall = recall_score(y_test, rf_pred)\nrf_f1 = f1_score(y_test, rf_pred)\nrf_confu = confusion_matrix(y_test, rf_pred)\nrf_roc_auc = roc_auc_score(y_test, rf_pred)\n\nprint('accuracy:', round(rf_acc,5))\nprint('precision:', round(rf_prec,5))\nprint('recall:', round(rf_recall, 5))\nprint('f1', round(rf_f1, 5))\nprint('roc_auc', round(rf_roc_auc, 5))","metadata":{"execution":{"iopub.status.busy":"2024-06-28T01:50:58.772060Z","iopub.execute_input":"2024-06-28T01:50:58.772572Z","iopub.status.idle":"2024-06-28T01:50:59.843298Z","shell.execute_reply.started":"2024-06-28T01:50:58.772529Z","shell.execute_reply":"2024-06-28T01:50:59.841589Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"xgboost - 랜덤포레스트와 마찬가지로 불균형 데이터에서 사용하는 것이 좋다.","metadata":{}},{"cell_type":"code","source":"#xgboost 모델\nfrom xgboost import XGBClassifier\n\n# XGB 모델 학습\nxgb_model = XGBClassifier()\nxgb_model.fit(X_train, y_train)","metadata":{"execution":{"iopub.status.busy":"2024-06-28T01:50:59.845110Z","iopub.execute_input":"2024-06-28T01:50:59.845504Z","iopub.status.idle":"2024-06-28T01:51:01.743676Z","shell.execute_reply.started":"2024-06-28T01:50:59.845470Z","shell.execute_reply":"2024-06-28T01:51:01.742632Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# xgb 예측\nxgb_pred = xgb_model.predict(X_test)\n\n#평가항목 적용\ngeteval(xgb_pred)","metadata":{"execution":{"iopub.status.busy":"2024-06-28T01:51:01.745359Z","iopub.execute_input":"2024-06-28T01:51:01.746252Z","iopub.status.idle":"2024-06-28T01:51:01.895098Z","shell.execute_reply.started":"2024-06-28T01:51:01.746214Z","shell.execute_reply":"2024-06-28T01:51:01.893597Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"lightgbm","metadata":{}},{"cell_type":"code","source":"from lightgbm import LGBMClassifier\n\nlgbm_model = LGBMClassifier()\nlgbm_model.fit(X_train, y_train)","metadata":{"execution":{"iopub.status.busy":"2024-06-28T01:51:01.896548Z","iopub.execute_input":"2024-06-28T01:51:01.896931Z","iopub.status.idle":"2024-06-28T01:51:06.175393Z","shell.execute_reply.started":"2024-06-28T01:51:01.896898Z","shell.execute_reply":"2024-06-28T01:51:06.174334Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# lgbm 예측\nlgbm_pred = lgbm_model.predict(X_test)\n\n#평가항목 적용\ngeteval(lgbm_pred)","metadata":{"execution":{"iopub.status.busy":"2024-06-28T01:51:06.176798Z","iopub.execute_input":"2024-06-28T01:51:06.177491Z","iopub.status.idle":"2024-06-28T01:51:06.550773Z","shell.execute_reply.started":"2024-06-28T01:51:06.177458Z","shell.execute_reply":"2024-06-28T01:51:06.549420Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 모델 수정하기\n나는 사기 거래 감지에서는 재현률을 높이는 데에 집중해야 한다고 생각한다. False positive로 거래나 카드가 중단되는 것은 당사자가 잠깐 불편할 뿐 큰 문제가 되지 않는다. 하지만 False negative로 사기거래를 감지하지 못하면 사용자나 카드사에 큰 손해가 발생할 수 있다. 그래서 재현률 Recall이 가장 높은 모델이 가장 좋은 모델이다.","metadata":{}},{"cell_type":"code","source":"# 우선 가장 떨어지는 성능을 내는 lightgbm부터 하이퍼 파라미터 수정해보기\n\nh1_lgbm_model = LGBMClassifier(n_estimators=200, learning_rate=0.05)\nh1_lgbm_model.fit(X_train, y_train)\n\nh1_lgbm_pred = h1_lgbm_model.predict(X_test)\n","metadata":{"execution":{"iopub.status.busy":"2024-06-28T01:51:06.552196Z","iopub.execute_input":"2024-06-28T01:51:06.552545Z","iopub.status.idle":"2024-06-28T01:51:17.515322Z","shell.execute_reply.started":"2024-06-28T01:51:06.552517Z","shell.execute_reply":"2024-06-28T01:51:17.514130Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"geteval(h1_lgbm_pred)\n#학습률을 두 배 높이고 트리개수를 두 배 낮추었더니 성능이 훨씬 좋아졌다.\n#하지만 아직 xgboost보다 재현률이 높지 않다.","metadata":{"execution":{"iopub.status.busy":"2024-06-28T01:51:17.516646Z","iopub.execute_input":"2024-06-28T01:51:17.517429Z","iopub.status.idle":"2024-06-28T01:51:17.605794Z","shell.execute_reply.started":"2024-06-28T01:51:17.517390Z","shell.execute_reply":"2024-06-28T01:51:17.604433Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 깊이를 제한한다\nh1_lgbm_model = LGBMClassifier(n_estimators=200, learning_rate=0.05, max_depth=2)\nh1_lgbm_model.fit(X_train, y_train)\n\nh1_lgbm_pred = h1_lgbm_model.predict(X_test)\n","metadata":{"execution":{"iopub.status.busy":"2024-06-28T01:51:17.607410Z","iopub.execute_input":"2024-06-28T01:51:17.607877Z","iopub.status.idle":"2024-06-28T01:51:23.984494Z","shell.execute_reply.started":"2024-06-28T01:51:17.607831Z","shell.execute_reply":"2024-06-28T01:51:23.983178Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"geteval(h1_lgbm_pred)\n#성능이 조금 떨어졌다.","metadata":{"execution":{"iopub.status.busy":"2024-06-28T01:51:23.986377Z","iopub.execute_input":"2024-06-28T01:51:23.986969Z","iopub.status.idle":"2024-06-28T01:51:24.078323Z","shell.execute_reply.started":"2024-06-28T01:51:23.986922Z","shell.execute_reply":"2024-06-28T01:51:24.077091Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"h1_lgbm_model = LGBMClassifier(n_estimators=200, learning_rate=0.05, max_depth=5, num_leaves=23)\nh1_lgbm_model.fit(X_train, y_train)\n\nh1_lgbm_pred = h1_lgbm_model.predict(X_test)","metadata":{"execution":{"iopub.status.busy":"2024-06-28T01:51:24.080125Z","iopub.execute_input":"2024-06-28T01:51:24.080672Z","iopub.status.idle":"2024-06-28T01:51:33.593688Z","shell.execute_reply.started":"2024-06-28T01:51:24.080552Z","shell.execute_reply":"2024-06-28T01:51:33.592640Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"geteval(h1_lgbm_pred)\n#다시 원점으로 돌아왔다.","metadata":{"execution":{"iopub.status.busy":"2024-06-28T01:51:33.595173Z","iopub.execute_input":"2024-06-28T01:51:33.595610Z","iopub.status.idle":"2024-06-28T01:51:33.681303Z","shell.execute_reply.started":"2024-06-28T01:51:33.595570Z","shell.execute_reply":"2024-06-28T01:51:33.679933Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"xgb로 시도하기","metadata":{}},{"cell_type":"code","source":"#xgb가 하이퍼 파라미더 없이도 결과가 좋았기 때문에 xgb로 시도\n# XGB 모델 학습\nh1_xgb_model = XGBClassifier(n_estimators=400, learning_rate=0.2, max_depth=3)\nh1_xgb_model.fit(X_train, y_train)\n\nh1_xgb_pred = h1_xgb_model.predict(X_test)","metadata":{"execution":{"iopub.status.busy":"2024-06-28T01:51:33.683053Z","iopub.execute_input":"2024-06-28T01:51:33.683550Z","iopub.status.idle":"2024-06-28T01:51:46.004123Z","shell.execute_reply.started":"2024-06-28T01:51:33.683498Z","shell.execute_reply":"2024-06-28T01:51:46.002724Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"geteval(h1_xgb_pred)\n#변화가 없다","metadata":{"execution":{"iopub.status.busy":"2024-06-28T01:51:46.005543Z","iopub.execute_input":"2024-06-28T01:51:46.005994Z","iopub.status.idle":"2024-06-28T01:51:46.101101Z","shell.execute_reply.started":"2024-06-28T01:51:46.005955Z","shell.execute_reply":"2024-06-28T01:51:46.099438Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#xgb로 제출\n\ntest_submi = test.drop(['id'], axis=1)\ntest_submi = test_submi.drop(['Time'], axis=1)\ntest_submi['s_Amount'] = r_scaler.fit_transform(test_submi['Amount'].values.reshape(-1,1))\n\nmove_col = test_submi.pop('s_Amount')\ntest_submi.insert(0, 's_Amount', move_col)\n\ntest_submi = test_submi.drop(['Amount'], axis=1)\n\ny_pred = h1_xgb_model.predict(test_submi)","metadata":{"execution":{"iopub.status.busy":"2024-06-28T01:55:50.690594Z","iopub.execute_input":"2024-06-28T01:55:50.691083Z","iopub.status.idle":"2024-06-28T01:55:51.377083Z","shell.execute_reply.started":"2024-06-28T01:55:50.691035Z","shell.execute_reply":"2024-06-28T01:55:51.375781Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 제출하기","metadata":{}},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 제출 파일 생성\nsubmission = pd.DataFrame({'id': test['id'], 'Class': y_pred})\nsubmission.to_csv('submission.csv', index=False)","metadata":{"execution":{"iopub.status.busy":"2024-06-28T01:56:05.649848Z","iopub.execute_input":"2024-06-28T01:56:05.650289Z","iopub.status.idle":"2024-06-28T01:56:05.831868Z","shell.execute_reply.started":"2024-06-28T01:56:05.650257Z","shell.execute_reply":"2024-06-28T01:56:05.830390Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission","metadata":{"execution":{"iopub.status.busy":"2024-06-28T01:56:08.766594Z","iopub.execute_input":"2024-06-28T01:56:08.767079Z","iopub.status.idle":"2024-06-28T01:56:08.781309Z","shell.execute_reply.started":"2024-06-28T01:56:08.767029Z","shell.execute_reply":"2024-06-28T01:56:08.779752Z"},"trusted":true},"execution_count":null,"outputs":[]}]}