{"metadata":{"kernelspec":{"display_name":"Python 3 (ipykernel)","language":"python","name":"python3"},"language_info":{"codemirror_mode":{"name":"ipython","version":3},"file_extension":".py","mimetype":"text/x-python","name":"python","nbconvert_exporter":"python","pygments_lexer":"ipython3","version":"3.12.3"},"kaggle":{"accelerator":"none","dataSources":[{"sourceId":88400,"databundleVersionId":10121331,"sourceType":"competition"}],"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import numpy as np\nimport pandas as pd","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import os\nfor dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n        print(os.path.join(dirname, filename))","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_df = pd.read_csv(\"train.csv\") \ntest_df = pd.read_csv(\"test.csv\")\nsubmission_df = pd.read_csv(\"sample_submission.csv\")","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_df.head()","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_df.head()","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_df.info()","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_df.shape","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_df.duplicated().sum() #중복 없음","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_df.isna().sum() #Null 값 없음","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_df.describe()","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_df['Class'].value_counts()","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"360/170523*100 # Class 값 경우 data 불균형 있음.","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import matplotlib.pyplot as plt\nimport seaborn as sns\nimport warnings\nwarnings.filterwarnings(\"ignore\")\n%matplotlib inline","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.figure(figsize=(7, 4))\nsns.countplot(x='Class', data=train_df ) # data 불균형 정상0이 사기거래1 보다 월등히 많음.","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.figure(figsize=(7, 4))\nsns.histplot(train_df['Amount'], bins=100, kde=True)\nplt.title(\"Amount\")\nplt.xlabel(\"Amount\")\nplt.ylabel(\"Frequency\")\nplt.show() # Amount 분포 확인. 이상치로 보이지는 않음 ","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.figure(figsize=(7, 4))\nsns.histplot(train_df['Time'], bins=100, kde=True)\nplt.title(\"Time\")\nplt.xlabel(\"Time\")\nplt.ylabel(\"Frequency\")\nplt.show() #분포 확인","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import seaborn as sns\n\nplt.figure(figsize=(9, 9))\ncorr = train_df.corr()\nsns.heatmap(corr, cmap='RdBu')","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# V14, V17이 음의 상관관계가 높은 진한 빨강 \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    # 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    # 최대값 보다 크거나, 최소값 보다 작은 값을 아웃라이어로 설정하고 DataFrame index 반환. \n    outlier_index = fraud[(fraud < lowest_val) | (fraud > highest_val)].index\n    return outlier_index","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"outlier_index = get_outlier(df=train_df, column='V17', weight=1.5)\nprint('V17 이상치 데이터 인덱스:', outlier_index) #없음","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"outlier_index = get_outlier(df=train_df, column='V14', weight=1.5)\nprint('V14 이상치 데이터 인덱스:', outlier_index)","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# get_processed_df( )를 로그 변환 후 V14 피처의 이상치 데이터를 삭제하는 로직으로 변경. \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    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","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import seaborn as sns\n\nplt.figure(figsize=(8, 4))\nplt.xticks(range(0, 30000, 1000), rotation=60)\nsns.histplot(train_df['Amount'], bins=100, kde=True)\nplt.show()","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 이상치는 크게 발견되지 않으나 데이터가 많이 치우쳐 있어 Amount, Time 은 standardscaler로 분포 변환\nfrom sklearn.preprocessing import StandardScaler\n\nss = StandardScaler()\ntrain_df['Amount_Scaled'] = ss.fit_transform(train_df[['Amount']])\ntrain_df['Time_Scaled'] = ss.fit_transform(train_df[['Time']])\ntrain_df_scaled = train_df.drop(['Amount', 'Time'], axis=1)","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_df_scaled.head()","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 입력 특성과 타겟 변수 분리\nX_train = train_df_scaled.drop(['id', 'Class'], axis=1)\ny_train = train_df_scaled['Class']\n\nX_test = test.drop(['id'], axis=1)","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from sklearn.model_selection import train_test_split\nfrom sklearn.metrics import roc_auc_score\nfrom sklearn.linear_model import LogisticRegression\nfrom sklearn.ensemble import RandomForestClassifier\nfrom xgboost import XGBClassifier\nfrom lightgbm import LGBMClassifier","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Stratified 기반의 학습(데이터불균형으로), 검증 데이터 분리\nX_tr, X_val, y_tr, y_val = train_test_split(X_train, y_train, test_size=0.3, random_state=1112, stratify=y_train)","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# LogisticRegression - 간단, 해석용이, 빠른 학습\n\nlr = LogisticRegression(class_weight='balanced', random_state=1112)\nlr.fit(X_tr, y_tr)\nlr_pred = lr.predict_proba(X_val)[:,1]\nroc_auc_lr = roc_auc_score(y_val, lr_pred)\nprint(\"ROC AUC Logistic Regression:\", roc_auc_lr)","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# RandomForest -복잡한 패턴에 유리, 과적합 방지, 높은 정확도\nrfc = RandomForestClassifier(class_weight='balanced', random_state=1112)\nrfc.fit(X_tr, y_tr)\nrfc_pred = rfc.predict_proba(X_val)[:,1]\nroc_auc_rfc = roc_auc_score(y_val, rfc_pred)\nprint(\"ROC AUC RandomForestClassifier:\", roc_auc_rfc)","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#XGBoost - 불균형 데이터에 잘 작용, 하이퍼 파라미터 조정해 과적합 방지\nxgb = XGBClassifier(scale_pos_weight=0.2, random_state=1112, use_label_encoder=False, eval_metric='logloss')\nxgb.fit(X_tr, y_tr)\nxgb_pred = xgb.predict_proba(X_val)[:,1]\nroc_auc_xgb = roc_auc_score(y_val, xgb_pred)\nprint(\"ROC AUC Logistic XGBClassifier:\", roc_auc_xgb)\n","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# xgb 하이퍼파라미터 튜닝\nfrom xgboost import XGBClassifier\nfrom sklearn.model_selection import GridSearchCV\nxgb_model = XGBClassifier(random_state=1112, use_label_encoder=False, eval_metric='logloss')\nparam_grid_xgb = {\n    'n_estimators': [100, 200, 300],\n    'max_depth': [3, 5 ,7],\n    'learning_rate': [0.01, 0.1, 0.3],\n    'subsample': [0.6, 0.8],\n    'colsample_bytree': [0.6, 0.8]\n}\n\ngrid_search_xgb = GridSearchCV(estimator=xgb_model, \n                               param_grid=param_grid_xgb, \n                               scoring='roc_auc', \n                               cv=3, \n                               verbose=2)\ngrid_search_xgb.fit(X_train, y_train)\n\nprint(\"XGB Best Params:\", grid_search_xgb.best_params_)\nprint(\"XGB Best ROC-AUC Score:\", grid_search_xgb.best_score_)","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"ss = StandardScaler()\n# train_df['Amount_Scaled'] = ss.fit_transform(train_df[['Amount']])\n# train_df['Time_Scaled'] = ss.fit_transform(train_df[['Time']])\n# train_df_scaled = train_df.drop(['Amount', 'Time'], axis=1)\n\ntest_df['Amount_Scaled'] = ss.fit_transform(test_df[['Amount']])\ntest_df['Time_Scaled'] = ss.fit_transform(test_df[['Time']])\nX_test = test_df.drop(['id', 'Amount', 'Time'], axis=1)\n\n\n# best_xgb = grid_search_xgb.best_estimator_\n# xgb_pred_proba = best_xgb.predict_proba(X_test)[:, 1]","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#하이퍼파라미터 값 적용\n# XGB Best Params: {'colsample_bytree': 0.6, 'learning_rate': 0.1, 'max_depth': 7, 'n_estimators': 200, 'subsample': 0.8}\n# XGB Best ROC-AUC Score: 0.9807201961025784\nxgb = XGBClassifier(\n    n_estimators=100,             \n    max_depth=7,                 \n    learning_rate=0.1,            \n    subsample=0.8,                \n    colsample_bytree=0.6,           \n    random_state=1112,\n    use_label_encoder=False,\n    eval_metric='logloss'\n)\n\nxgb.fit(X_train, y_train)\n\nxgb_val_pred = xgb.predict_proba(X_val)[:, 1]\nroc_auc = roc_auc_score(y_val, xgb_val_pred)\nprint(\"ROC-AUC Score on Validation Data:\", roc_auc)\n\ny_pred = xgb.predict(X_test)\n# 과적합이라 n_estimator를 100 으로 낮춤.","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission = pd.DataFrame({'id': test_df['id'], 'Class': y_pred})\nsubmission.to_csv('submission.csv', index=False)","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission.head()","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission['Class'].value_counts()","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"- 저장의 중요성\n- 에러로 노트북이 사라져서 다시진행하느라 많은 부분 놓쳐 아쉽습니다.\n- 일단 1버전 제출 후 모델별 평가하는 부분부터 다시 한 번 차근차근 해봐야겠습니다.\n- ","metadata":{}},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}