{"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":30732,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# 아직 뭐가 뭔지 잘 모르겠어서, 그냥 책을 보며 천천히 따라해보았습니다.","metadata":{}},{"cell_type":"code","source":"# 라이브러리 불러오기\nimport pandas as pd\nimport numpy as np\nimport matplotlib.pyplot as plt\nimport warnings\nwarnings.filterwarnings('ignore')\n%matplotlib inline","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2024-06-27T06:29:13.974625Z","iopub.execute_input":"2024-06-27T06:29:13.975182Z","iopub.status.idle":"2024-06-27T06:29:13.986765Z","shell.execute_reply.started":"2024-06-27T06:29:13.975137Z","shell.execute_reply":"2024-06-27T06:29:13.985474Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 데이터 불러오기 + 대략적인 내용 확인\ncard_df = pd.read_csv('/kaggle/input/affel-ds2-credit-card/train.csv')\ncard_df.head()","metadata":{"execution":{"iopub.status.busy":"2024-06-27T06:29:13.988886Z","iopub.execute_input":"2024-06-27T06:29:13.989329Z","iopub.status.idle":"2024-06-27T06:29:15.590400Z","shell.execute_reply.started":"2024-06-27T06:29:13.989288Z","shell.execute_reply":"2024-06-27T06:29:15.589376Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test = pd.read_csv('/kaggle/input/affel-ds2-credit-card/test.csv')","metadata":{"execution":{"iopub.status.busy":"2024-06-27T07:06:27.404466Z","iopub.execute_input":"2024-06-27T07:06:27.404918Z","iopub.status.idle":"2024-06-27T07:06:28.613664Z","shell.execute_reply.started":"2024-06-27T07:06:27.404884Z","shell.execute_reply":"2024-06-27T07:06:28.612606Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test.shape","metadata":{"execution":{"iopub.status.busy":"2024-06-27T07:06:38.111297Z","iopub.execute_input":"2024-06-27T07:06:38.111736Z","iopub.status.idle":"2024-06-27T07:06:38.119306Z","shell.execute_reply.started":"2024-06-27T07:06:38.111704Z","shell.execute_reply":"2024-06-27T07:06:38.118162Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 데이터 세부 내용 확인\ncard_df.info()\n\n# 결측치 없음 확인","metadata":{"execution":{"iopub.status.busy":"2024-06-27T06:29:15.591764Z","iopub.execute_input":"2024-06-27T06:29:15.592088Z","iopub.status.idle":"2024-06-27T06:29:15.614380Z","shell.execute_reply.started":"2024-06-27T06:29:15.592059Z","shell.execute_reply":"2024-06-27T06:29:15.613301Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"card_df.shape","metadata":{"execution":{"iopub.status.busy":"2024-06-27T06:29:15.617393Z","iopub.execute_input":"2024-06-27T06:29:15.618193Z","iopub.status.idle":"2024-06-27T06:29:15.625834Z","shell.execute_reply.started":"2024-06-27T06:29:15.618148Z","shell.execute_reply":"2024-06-27T06:29:15.624598Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"card_df.describe()","metadata":{"execution":{"iopub.status.busy":"2024-06-27T06:29:15.627245Z","iopub.execute_input":"2024-06-27T06:29:15.627590Z","iopub.status.idle":"2024-06-27T06:29:15.959259Z","shell.execute_reply.started":"2024-06-27T06:29:15.627543Z","shell.execute_reply":"2024-06-27T06:29:15.958105Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 클래스 값 분포 확인\ncard_df.iloc[:,-1].value_counts()","metadata":{"execution":{"iopub.status.busy":"2024-06-27T06:29:15.960991Z","iopub.execute_input":"2024-06-27T06:29:15.961381Z","iopub.status.idle":"2024-06-27T06:29:15.972920Z","shell.execute_reply.started":"2024-06-27T06:29:15.961350Z","shell.execute_reply":"2024-06-27T06:29:15.971607Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 불필요한 데이터(Time컬럼) 삭제\n# 인자로 입력 받은 Dataframe 복사 후 Time 컬럼만 삭제하고 복사된 데이터프레임 반환\nfrom sklearn.model_selection import train_test_split\n\ndef get_preprocessed_df (df=None):\n    df_copy = df.copy()\n    df_copy.drop('Time', axis=1, inplace=True)\n    return df_copy","metadata":{"execution":{"iopub.status.busy":"2024-06-27T06:29:15.974511Z","iopub.execute_input":"2024-06-27T06:29:15.975293Z","iopub.status.idle":"2024-06-27T06:29:15.982715Z","shell.execute_reply.started":"2024-06-27T06:29:15.975251Z","shell.execute_reply":"2024-06-27T06:29:15.981391Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 사전 데이터 가공 후 학습과 테스트 데이터 세트를 반환하는 함수\ndef get_train_test_dataset(df=None):\n    # 인자로 입력된 데이터프레임의 사전 데이터 가공이 완료된 복사 데이터 프레임 반환\n    df_copy = get_preprocessed_df(df)\n    # 데이터프레임 맨 마지막 컬럼이 레이블, 나머지는 피처들\n    X_features = df_copy.iloc[:, :-1]\n    y_target = df_copy.iloc[:, -1]\n    # 학습과 테스트 데이터 분할, 동일한 타겟값 분포를 위한 stratified 조건 추가 \n    X_train, X_test, y_train, y_test = \\\n    train_test_split(X_features, y_target, test_size=0.3, random_state=0, stratify=y_target)\n    # 학습&테스트 데이터 세트 반환\n    return X_train, X_test, y_train, y_test\n\nX_train, X_test, y_train, y_test = get_train_test_dataset(card_df)","metadata":{"execution":{"iopub.status.busy":"2024-06-27T06:29:15.984252Z","iopub.execute_input":"2024-06-27T06:29:15.984708Z","iopub.status.idle":"2024-06-27T06:29:16.185784Z","shell.execute_reply.started":"2024-06-27T06:29:15.984669Z","shell.execute_reply":"2024-06-27T06:29:16.184602Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 레이블 분포 확인\ny_train.value_counts()/y_train.shape[0]*100","metadata":{"execution":{"iopub.status.busy":"2024-06-27T06:29:16.187065Z","iopub.execute_input":"2024-06-27T06:29:16.187409Z","iopub.status.idle":"2024-06-27T06:29:16.198500Z","shell.execute_reply.started":"2024-06-27T06:29:16.187380Z","shell.execute_reply":"2024-06-27T06:29:16.197354Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"y_test.value_counts()/y_test.shape[0]*100","metadata":{"execution":{"iopub.status.busy":"2024-06-27T06:29:16.203169Z","iopub.execute_input":"2024-06-27T06:29:16.203635Z","iopub.status.idle":"2024-06-27T06:29:16.215192Z","shell.execute_reply.started":"2024-06-27T06:29:16.203597Z","shell.execute_reply":"2024-06-27T06:29:16.213984Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 로지스틱 회귀로 신용 카드 사기 여부 예측","metadata":{}},{"cell_type":"code","source":"from sklearn.linear_model import LogisticRegression\n\n# 학습 & 예측\nlr_clf = LogisticRegression(max_iter=1000)\nlr_clf.fit(X_train, y_train)\nlr_pred = lr_clf.predict(X_test)\nlr_pred_proba = lr_clf.predict_proba(X_test)[:,1]","metadata":{"execution":{"iopub.status.busy":"2024-06-27T06:29:16.216664Z","iopub.execute_input":"2024-06-27T06:29:16.217107Z","iopub.status.idle":"2024-06-27T06:29:24.411505Z","shell.execute_reply.started":"2024-06-27T06:29:16.217054Z","shell.execute_reply":"2024-06-27T06:29:24.409698Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 평가\nfrom sklearn.metrics import accuracy_score, precision_score, recall_score, confusion_matrix, roc_auc_score\n\ndef get_clf_eval(y_test, pred, pred_proba):\n    confusion = confusion_matrix(y_test, pred)\n    accuracy = accuracy_score(y_test, pred)\n    precision = precision_score(y_test, pred)\n    recall = recall_score(y_test, pred)\n    roc_auc = roc_auc_score(y_test, pred_proba)\n    print('오차 행렬')\n    print(confusion)\n    print('정확도: {0:.4f}, 정밀도: {1:.4f}, 재현율: {2:.4f}, ROC AUC: {3:.4f}'.format(accuracy, precision, recall, roc_auc))\n    \n    \nget_clf_eval(y_test, lr_pred, lr_pred_proba)","metadata":{"execution":{"iopub.status.busy":"2024-06-27T06:29:24.413681Z","iopub.execute_input":"2024-06-27T06:29:24.414140Z","iopub.status.idle":"2024-06-27T06:29:24.549515Z","shell.execute_reply.started":"2024-06-27T06:29:24.414102Z","shell.execute_reply":"2024-06-27T06:29:24.548305Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# LightGBM","metadata":{}},{"cell_type":"code","source":"# 학습/예측/평가 반복을 위한 별도의 함수 생성\ndef get_model_train_eval(model, ftr_train=None, ftr_test=None, tgt_train=None, tgt_test=None):\n    model.fit(ftr_train, tgt_train)\n    pred = model.predict(ftr_test)\n    pred_proba = model.predict_proba(ftr_test)[:,1]\n    get_clf_eval(tgt_test, pred, pred_proba)","metadata":{"execution":{"iopub.status.busy":"2024-06-27T06:29:24.550988Z","iopub.execute_input":"2024-06-27T06:29:24.551401Z","iopub.status.idle":"2024-06-27T06:29:24.558978Z","shell.execute_reply.started":"2024-06-27T06:29:24.551362Z","shell.execute_reply":"2024-06-27T06:29:24.557861Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# lightgbm 모델 학습/예측/평가\nfrom lightgbm import LGBMClassifier\n\nlgbm_clf = LGBMClassifier(n_estimators=1000, num_leaves=64, n_jobs=-1, boost_from_average=False)\nget_model_train_eval(lgbm_clf, ftr_train=X_train, ftr_test=X_test, tgt_train=y_train, tgt_test=y_test)","metadata":{"execution":{"iopub.status.busy":"2024-06-27T06:29:24.560332Z","iopub.execute_input":"2024-06-27T06:29:24.560701Z","iopub.status.idle":"2024-06-27T06:30:04.810163Z","shell.execute_reply.started":"2024-06-27T06:29:24.560669Z","shell.execute_reply":"2024-06-27T06:30:04.809028Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 데이터 분포도 변환 후 모델 학습/예측/평가","metadata":{}},{"cell_type":"code","source":"# amount 피처의 분포도 확인\nimport seaborn as sns\n\n# 피겨 사이즈 설정\nplt.figure(figsize=(8,4))\n\n# x축 눈금 설정\nplt.xticks(range(0, 30000, 1000), rotation=60)\n\n# 히스토그램 그리기\nsns.histplot(card_df['Amount'], bins=100, kde=True)\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2024-06-27T06:30:04.811415Z","iopub.execute_input":"2024-06-27T06:30:04.811791Z","iopub.status.idle":"2024-06-27T06:30:06.162334Z","shell.execute_reply.started":"2024-06-27T06:30:04.811760Z","shell.execute_reply":"2024-06-27T06:30:06.161107Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# amount를 표준 정규 분포 형태로 변환 후 로지스틱 회귀의 예측 성능 측정\nfrom sklearn.preprocessing import StandardScaler\n\n# 사이킷런의 스탠다드 스케일러 이용하여 amount 피처값을 정규 분포 형태로 변환하는 로직으로 수정\ndef get_preprocessed_df(df=None):\n    df_copy = df.copy()\n    scaler = StandardScaler()\n    amount_n = scaler.fit_transform(df_copy['Amount'].values.reshape(-1,1))\n    # 변환된 amount를 amount_scaled로 피처명 변경 후 데이터프레임 맨 앞 컬럼으로 추가\n    df_copy.insert(0, 'Amount_Scaled', amount_n)\n    # 기존 Time, Amount 피처 삭제\n    df_copy.drop(['Time', 'Amount'], axis=1, inplace=True)\n    return df_copy","metadata":{"execution":{"iopub.status.busy":"2024-06-27T06:30:06.164086Z","iopub.execute_input":"2024-06-27T06:30:06.164871Z","iopub.status.idle":"2024-06-27T06:30:06.175613Z","shell.execute_reply.started":"2024-06-27T06:30:06.164827Z","shell.execute_reply":"2024-06-27T06:30:06.174293Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Amount를 정규 분포 형태로 변환 후 로지스틱 회귀 및 LightGBM 수행\nX_train, X_test, y_train, y_test = get_train_test_dataset(card_df)\n\nprint('### 로지스틱 회귀 예측 성능 w.정규분포화 ###')\nlr_clf = LogisticRegression(max_iter=1000)\nget_model_train_eval(lr_clf, ftr_train=X_train, ftr_test=X_test, tgt_train=y_train, tgt_test=y_test)\n\nprint('### LightGBM 예측 성능 w.정규분포화 ###')\nlgbm_clf = LGBMClassifier(n_estimators=1000, num_leaves=64, n_jobs=-1, boost_from_average=False)\nget_model_train_eval(lgbm_clf, ftr_train=X_train, ftr_test=X_test, tgt_train=y_train, tgt_test=y_test)","metadata":{"execution":{"iopub.status.busy":"2024-06-27T06:30:06.177148Z","iopub.execute_input":"2024-06-27T06:30:06.177610Z","iopub.status.idle":"2024-06-27T06:30:49.891047Z","shell.execute_reply.started":"2024-06-27T06:30:06.177540Z","shell.execute_reply":"2024-06-27T06:30:49.889965Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 로그 변환","metadata":{}},{"cell_type":"code","source":"def get_preprocessed_df(df=None):\n    df_copy = df.copy()\n    # 넘파이의 log1p()를 이용해 Amount를 로그 변환\n    # log1p: 주어진 값에 대해 자연로그 취한 후 1을 더함.\n    amount_n = np.log1p(df_copy['Amount'])\n    df_copy.insert(0, 'Amount_Scaled', amount_n)\n    df_copy.drop(['Time', 'Amount'], axis=1, inplace=True)\n    return df_copy","metadata":{"execution":{"iopub.status.busy":"2024-06-27T06:30:49.892505Z","iopub.execute_input":"2024-06-27T06:30:49.892967Z","iopub.status.idle":"2024-06-27T06:30:49.900036Z","shell.execute_reply.started":"2024-06-27T06:30:49.892927Z","shell.execute_reply":"2024-06-27T06:30:49.898913Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"X_train, X_test, y_train, y_test = get_train_test_dataset(card_df)\n\nprint('### 로지스틱 회귀 예측 성능 w.로그변환 ###')\nget_model_train_eval(lr_clf, ftr_train=X_train, ftr_test=X_test, tgt_train=y_train, tgt_test=y_test)\n\nprint('### LightGBM 예측 성능 w.로그변환 ###')\nget_model_train_eval(lgbm_clf, ftr_train=X_train, ftr_test=X_test, tgt_train=y_train, tgt_test=y_test)","metadata":{"execution":{"iopub.status.busy":"2024-06-27T06:30:49.901726Z","iopub.execute_input":"2024-06-27T06:30:49.902151Z","iopub.status.idle":"2024-06-27T06:31:35.926203Z","shell.execute_reply.started":"2024-06-27T06:30:49.902113Z","shell.execute_reply":"2024-06-27T06:31:35.924961Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 이상치 데이터 제거 후 모델 학습/예측/평가","metadata":{}},{"cell_type":"code","source":"# 피처별 상관도 확인 후 레이블과 가장 상관성이 높은 피처 대상 이상치 검출\n\nimport seaborn as sns\n\nplt.figure(figsize=(9,9))\ncorr = card_df.corr()\nsns.heatmap(corr, cmap='RdBu')","metadata":{"execution":{"iopub.status.busy":"2024-06-27T06:31:35.927843Z","iopub.execute_input":"2024-06-27T06:31:35.928222Z","iopub.status.idle":"2024-06-27T06:31:37.287329Z","shell.execute_reply.started":"2024-06-27T06:31:35.928190Z","shell.execute_reply":"2024-06-27T06:31:37.286183Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 위 히트맵에서 class 피처와 음의 상관 관계가 특히 높아보이는 V14 대상 이상치 검출 진행 결정\n# 먼저 이상치 검출하는 함수 정의\n\nimport numpy as np\n\ndef get_outlier(df=None, column=None, weight=1.5):\n    # fraud에 해당하는 column 데이터만 추출, 1/4분위와 3/4분위 지점을 np.percentile로 구함\n    fraud = df[df['Class']==1][column]\n    quantile_25 = np.percentile(fraud.values, 25)\n    quantile_75 = np.percentile(fraud.values, 75)\n    \n    # IQR을 구하고, IQR에 1.5 곱해서 최대/최소값 구하기\n    iqr = quantile_75 - quantile_25\n    iqr_weight = iqr*weight\n    lowest_val = quantile_25 - iqr_weight\n    highest_val = quantile_75 + iqr_weight\n    \n    # 최대값보다 크거나, 최소값보다 작으면 이상치로 설정하고 데이터프레임 인덱스 반환\n    outlier_index = fraud[(fraud<lowest_val) | (fraud>highest_val)].index\n    return outlier_index","metadata":{"execution":{"iopub.status.busy":"2024-06-27T06:31:37.288958Z","iopub.execute_input":"2024-06-27T06:31:37.289391Z","iopub.status.idle":"2024-06-27T06:31:37.298203Z","shell.execute_reply.started":"2024-06-27T06:31:37.289354Z","shell.execute_reply":"2024-06-27T06:31:37.296911Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# V14 컬럼 기준 이상치 확인\noutlier_index = get_outlier(df=card_df, column='V14', weight=1.5)\nprint('V14 기준 이상치 데이터 인덱스:', outlier_index)","metadata":{"execution":{"iopub.status.busy":"2024-06-27T06:31:37.299713Z","iopub.execute_input":"2024-06-27T06:31:37.300129Z","iopub.status.idle":"2024-06-27T06:31:37.313234Z","shell.execute_reply.started":"2024-06-27T06:31:37.300089Z","shell.execute_reply":"2024-06-27T06:31:37.312048Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# get_preprocessed_df 함수에 get_outlier 추가\n# 로그 변환 후 이상치 탐지 로직 추가\ndef get_preprocessed_df(df=None):\n    df_copy = df.copy()\n    amount_n = np.log1p(df_copy['Amount'])\n    df_copy.insert(0, 'Amount_Scaled', amount_n)\n    df_copy.drop(['Time', 'Amount'], axis=1, inplace=True)\n    \n    # 이상치 탐지 로직 추가\n    outlier_index = get_outlier(df=df_copy, column='V14', weight=1.5)\n    df_copy.drop(outlier_index, axis=0, inplace=True)\n    return df_copy\n\n\nX_train, X_test, y_train, y_test = get_train_test_dataset(card_df)\n\nprint('### 로지스틱 회귀 예측 성능 w.로그&이상치 ###')\nget_model_train_eval(lr_clf, ftr_train=X_train, ftr_test=X_test, tgt_train=y_train, tgt_test=y_test)\n\nprint('### LightGBM 예측 성능 w.로그&이상치 ###')\nget_model_train_eval(lgbm_clf, ftr_train=X_train, ftr_test=X_test, tgt_train=y_train, tgt_test=y_test)","metadata":{"execution":{"iopub.status.busy":"2024-06-27T06:31:37.315037Z","iopub.execute_input":"2024-06-27T06:31:37.315387Z","iopub.status.idle":"2024-06-27T06:32:20.045015Z","shell.execute_reply.started":"2024-06-27T06:31:37.315358Z","shell.execute_reply":"2024-06-27T06:32:20.043833Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# get_preprocessed_df 함수에 get_outlier 추가\n# 로그 변환 후 이상치 탐지 로직 추가\ndef get_preprocessed_df(df=None):\n    df_copy = df.copy()\n    df_copy.drop('Time', axis=1, inplace=True)\n    \n    # 이상치 탐지 로직 추가\n    outlier_index = get_outlier(df=df_copy, column='V14', weight=1.5)\n    df_copy.drop(outlier_index, axis=0, inplace=True)\n    return df_copy\n\n\nX_train, X_test, y_train, y_test = get_train_test_dataset(card_df)\n\nprint('### 로지스틱 회귀 예측 성능 w.그냥&이상치 ###')\nget_model_train_eval(lr_clf, ftr_train=X_train, ftr_test=X_test, tgt_train=y_train, tgt_test=y_test)\n\nprint('### LightGBM 예측 성능 w.그냥&이상치 ###')\nget_model_train_eval(lgbm_clf, ftr_train=X_train, ftr_test=X_test, tgt_train=y_train, tgt_test=y_test)","metadata":{"execution":{"iopub.status.busy":"2024-06-27T06:32:20.046627Z","iopub.execute_input":"2024-06-27T06:32:20.047057Z","iopub.status.idle":"2024-06-27T06:33:06.545689Z","shell.execute_reply.started":"2024-06-27T06:32:20.047017Z","shell.execute_reply":"2024-06-27T06:33:06.544504Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def get_preprocessed_df(df=None):\n    df_copy = df.copy()\n    scaler = StandardScaler()\n    amount_n = scaler.fit_transform(df_copy['Amount'].values.reshape(-1,1))\n    # 변환된 amount를 amount_scaled로 피처명 변경 후 데이터프레임 맨 앞 컬럼으로 추가\n    df_copy.insert(0, 'Amount_Scaled', amount_n)\n    # 기존 Time, Amount 피처 삭제\n    df_copy.drop(['Time', 'Amount'], axis=1, inplace=True)\n  \n    # 이상치 탐지 로직 추가\n    outlier_index = get_outlier(df=df_copy, column='V14', weight=1.5)\n    df_copy.drop(outlier_index, axis=0, inplace=True)\n    return df_copy\n\n\nX_train, X_test, y_train, y_test = get_train_test_dataset(card_df)\n\nprint('### 로지스틱 회귀 예측 성능 w.정규분포&이상치 ###')\nget_model_train_eval(lr_clf, ftr_train=X_train, ftr_test=X_test, tgt_train=y_train, tgt_test=y_test)\n\nprint('### LightGBM 예측 성능 w.정규분포&이상치 ###')\nget_model_train_eval(lgbm_clf, ftr_train=X_train, ftr_test=X_test, tgt_train=y_train, tgt_test=y_test)","metadata":{"execution":{"iopub.status.busy":"2024-06-27T06:33:06.547461Z","iopub.execute_input":"2024-06-27T06:33:06.547959Z","iopub.status.idle":"2024-06-27T06:33:53.273563Z","shell.execute_reply.started":"2024-06-27T06:33:06.547917Z","shell.execute_reply":"2024-06-27T06:33:53.272335Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# SMOTE 오버 샘플링 적용 후 모델 학습/예측/평가","metadata":{}},{"cell_type":"code","source":"from imblearn.over_sampling import SMOTE\n\nsmote = SMOTE(random_state=0)\nX_train_over, y_train_over = smote.fit_resample(X_train, y_train)\nprint('SMOTE 적용 전 학습용 피처/레이블 데이터 세트: ', X_train.shape, y_train.shape)\nprint('SMOTE 적용 후 학습용 피처/레이블 데이터 세트: ', X_train_over.shape, y_train_over.shape)\nprint('SMOTE 적용 후 레이블 값 분포: \\n',pd.Series(y_train_over).value_counts())","metadata":{"execution":{"iopub.status.busy":"2024-06-27T06:33:53.275229Z","iopub.execute_input":"2024-06-27T06:33:53.275633Z","iopub.status.idle":"2024-06-27T06:33:53.521858Z","shell.execute_reply.started":"2024-06-27T06:33:53.275599Z","shell.execute_reply":"2024-06-27T06:33:53.520675Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 로지스틱 먼저 적용해보기\nlr_clf = LogisticRegression(max_iter=1000)\n# ftr_train과 tgt_train 인자 값이 SMOTE 증식된 X_train_over와 y_train_over로 변경 유의\nget_model_train_eval(lr_clf, ftr_train=X_train_over, ftr_test=X_test, tgt_train=y_train_over, tgt_test=y_test)","metadata":{"execution":{"iopub.status.busy":"2024-06-27T06:33:53.523333Z","iopub.execute_input":"2024-06-27T06:33:53.523782Z","iopub.status.idle":"2024-06-27T06:33:55.505577Z","shell.execute_reply.started":"2024-06-27T06:33:53.523740Z","shell.execute_reply":"2024-06-27T06:33:55.504182Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from sklearn.metrics import precision_recall_curve\n\n# 레이블 값이 1일 때의 예측 확률 추출\npred_proba_class1 = lr_clf.predict_proba(X_test)[:,1]\n\n# 실제 데이터 세트와 레이블 값이 1일 때의 예측 확률을 precision_recall_curve 인자로 입력\nprecisions, recalls, thresholds = precision_recall_curve(y_test, pred_proba_class1)\nprint('반환된 분류 결정 임곗값 배열의 shape: ', thresholds.shape)\n","metadata":{"execution":{"iopub.status.busy":"2024-06-27T06:33:55.513294Z","iopub.execute_input":"2024-06-27T06:33:55.513773Z","iopub.status.idle":"2024-06-27T06:33:55.554080Z","shell.execute_reply.started":"2024-06-27T06:33:55.513738Z","shell.execute_reply":"2024-06-27T06:33:55.552815Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def precision_recall_curve_plot(y_test, pred_proba_):\n    # threshold ndarray와 이 threshold에 따른 정밀도, 재현율 ndarray 추출\n    precisions, recalls, thresholds = precision_recall_curve(y_test, pred_proba_class1)\n    \n    # x축을 threshold 값, y축은 정밀도, 재현율 값으로 각각 plot 수행. 정밀도는 점선 표시\n    plt.figure(figsize=(8,6))\n    threshold_boundry = thresholds.shape[0]\n    plt.plot(thresholds, precisions[0:threshold_boundry], linestyle='--', label='precision')\n    plt.plot(thresholds, recalls[0:threshold_boundry], label='recall')\n    \n    # threshold값 x축의 스케일을 0.1 단위로 변경\n    start, end = plt.xlim()\n    plt.xticks(np.round(np.arange(start, end, 0.1), 2))\n    \n    # x축, y축 label, legend, grid 설정\n    plt.xlabel('Threshold value'); plt.ylabel('Precision and Recall value')\n    plt.legend(); plt.grid()\n    plt.show()\n\nprecision_recall_curve_plot(y_test, lr_clf.predict_proba(X_test)[:,1])","metadata":{"execution":{"iopub.status.busy":"2024-06-27T06:33:55.555762Z","iopub.execute_input":"2024-06-27T06:33:55.556657Z","iopub.status.idle":"2024-06-27T06:33:56.149660Z","shell.execute_reply.started":"2024-06-27T06:33:55.556609Z","shell.execute_reply":"2024-06-27T06:33:56.147444Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# lightgbm도 적용해보기\n\nlgbm_clf = LGBMClassifier(n_estimators=1000, num_leaves=64, n_jobs=-1, boost_from_average=False)\nget_model_train_eval(lgbm_clf, ftr_train=X_train_over, ftr_test=X_test, tgt_train=y_train_over, tgt_test=y_test)","metadata":{"execution":{"iopub.status.busy":"2024-06-27T06:33:56.151601Z","iopub.execute_input":"2024-06-27T06:33:56.152141Z","iopub.status.idle":"2024-06-27T06:35:34.610243Z","shell.execute_reply.started":"2024-06-27T06:33:56.152096Z","shell.execute_reply":"2024-06-27T06:35:34.609074Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 결과 요약\n[그냥]\n- 로지스틱: 정확도: 0.9989, 정밀도: 0.8095, 재현율: 0.6296, ROC AUC: 0.9401\n- LightGBM: 정확도: 0.9996, 정밀도: 0.9474, 재현율: 0.8333, ROC AUC: 0.9739\n\n[정규분포로 변환 후]\n- 로지스틱: 정확도: 0.9989, 정밀도: 0.8533, 재현율: 0.5926, ROC AUC: 0.9507\n- LightGBM: 정확도: 0.9996, 정밀도: 0.9381, 재현율: 0.8426, ROC AUC: 0.9737\n\n[로그 변환 후]\n- 로지스틱: 정확도: 0.9988, 정밀도: 0.8000, 재현율: 0.5556, ROC AUC: 0.9332\n- LightGBM: 정확도: 0.9995, 정밀도: 0.9375, 재현율: 0.8333, ROC AUC: 0.9722\n\n[로그*이상치]\n- 로지스틱: 정확도: 0.9988, 정밀도: 0.7738, 재현율: 0.6075, ROC AUC: 0.9303\n- LightGBM:정확도: 0.9996, 정밀도: 0.9570, 재현율: 0.8318, ROC AUC: 0.9769\n\n[그냥*이상치]\n- 로지스틱: 정확도: 0.9990, 정밀도: 0.8434, 재현율: 0.6542, ROC AUC: 0.9328\n- LightGBM: 정확도: 0.9996, 정밀도: 0.9574, 재현율: 0.8411, ROC AUC: 0.9775\n\n[정규분포*이상치]\n- 로지스틱: 정확도: 0.9990, 정밀도: 0.8718, 재현율: 0.6355, ROC AUC: 0.9413\n- LightGBM: 정확도: 0.9996, 정밀도: 0.9474, 재현율: 0.8411, ROC AUC: 0.9778\n\n[SMOTE]\n- 로지스틱: 정확도: 0.9567, 정밀도: 0.0417, 재현율: 0.8972, ROC AUC: 0.9619\n- LightGBM: 정확도: 0.9995, 정밀도: 0.8846, 재현율: 0.8598, ROC AUC: 0.9792\n","metadata":{}},{"cell_type":"code","source":"test.head()","metadata":{"execution":{"iopub.status.busy":"2024-06-27T07:32:41.124642Z","iopub.execute_input":"2024-06-27T07:32:41.125173Z","iopub.status.idle":"2024-06-27T07:32:41.159530Z","shell.execute_reply.started":"2024-06-27T07:32:41.125133Z","shell.execute_reply":"2024-06-27T07:32:41.157802Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def aaa(df=None):\n    df_copy = df.copy()\n    scaler = StandardScaler()\n    amount_n = scaler.fit_transform(df_copy['Amount'].values.reshape(-1,1))\n    # 변환된 amount를 amount_scaled로 피처명 변경 후 데이터프레임 맨 앞 컬럼으로 추가\n    df_copy.insert(0, 'Amount_Scaled', amount_n)\n    # 기존 Time, Amount 피처 삭제\n    df_copy.drop(['Time', 'Amount'], axis=1, inplace=True)\n    return df_copy","metadata":{"execution":{"iopub.status.busy":"2024-06-27T07:36:23.718095Z","iopub.execute_input":"2024-06-27T07:36:23.718581Z","iopub.status.idle":"2024-06-27T07:36:23.729646Z","shell.execute_reply.started":"2024-06-27T07:36:23.718532Z","shell.execute_reply":"2024-06-27T07:36:23.727836Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"a = aaa(test)","metadata":{"execution":{"iopub.status.busy":"2024-06-27T07:36:44.433830Z","iopub.execute_input":"2024-06-27T07:36:44.434287Z","iopub.status.idle":"2024-06-27T07:36:44.456657Z","shell.execute_reply.started":"2024-06-27T07:36:44.434252Z","shell.execute_reply":"2024-06-27T07:36:44.455320Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_label = lgbm_clf.predict_proba(a)[:, 1]","metadata":{"execution":{"iopub.status.busy":"2024-06-27T07:37:43.533037Z","iopub.execute_input":"2024-06-27T07:37:43.533522Z","iopub.status.idle":"2024-06-27T07:37:50.235039Z","shell.execute_reply.started":"2024-06-27T07:37:43.533484Z","shell.execute_reply":"2024-06-27T07:37:50.233993Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission = pd.read_csv('/kaggle/input/affel-ds2-credit-card/sample_submission.csv')","metadata":{"execution":{"iopub.status.busy":"2024-06-27T07:38:33.134285Z","iopub.execute_input":"2024-06-27T07:38:33.134844Z","iopub.status.idle":"2024-06-27T07:38:33.173185Z","shell.execute_reply.started":"2024-06-27T07:38:33.134803Z","shell.execute_reply":"2024-06-27T07:38:33.171813Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission.head()","metadata":{"execution":{"iopub.status.busy":"2024-06-27T07:38:45.393701Z","iopub.execute_input":"2024-06-27T07:38:45.394176Z","iopub.status.idle":"2024-06-27T07:38:45.407969Z","shell.execute_reply.started":"2024-06-27T07:38:45.394139Z","shell.execute_reply":"2024-06-27T07:38:45.406370Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission['Class']=test_label","metadata":{"execution":{"iopub.status.busy":"2024-06-27T07:39:25.273975Z","iopub.execute_input":"2024-06-27T07:39:25.274465Z","iopub.status.idle":"2024-06-27T07:39:25.285089Z","shell.execute_reply.started":"2024-06-27T07:39:25.274430Z","shell.execute_reply":"2024-06-27T07:39:25.283731Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission.head()","metadata":{"execution":{"iopub.status.busy":"2024-06-27T07:39:33.953661Z","iopub.execute_input":"2024-06-27T07:39:33.954074Z","iopub.status.idle":"2024-06-27T07:39:33.969208Z","shell.execute_reply.started":"2024-06-27T07:39:33.954043Z","shell.execute_reply":"2024-06-27T07:39:33.967986Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission.to_csv('submission.csv', index=False)","metadata":{"execution":{"iopub.status.busy":"2024-06-27T07:40:19.713887Z","iopub.execute_input":"2024-06-27T07:40:19.714891Z","iopub.status.idle":"2024-06-27T07:40:20.143923Z","shell.execute_reply.started":"2024-06-27T07:40:19.714843Z","shell.execute_reply":"2024-06-27T07:40:20.142562Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}