{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.14","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"none","dataSources":[{"sourceId":88400,"databundleVersionId":10121331,"sourceType":"competition"},{"sourceId":23498,"sourceType":"datasetVersion","datasetId":310}],"dockerImageVersionId":30786,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import matplotlib.pyplot as plt\nimport numpy as np\nimport pandas as pd\nimport seaborn as sns","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2024-11-12T08:49:12.650081Z","iopub.execute_input":"2024-11-12T08:49:12.650635Z","iopub.status.idle":"2024-11-12T08:49:12.657898Z","shell.execute_reply.started":"2024-11-12T08:49:12.650590Z","shell.execute_reply":"2024-11-12T08:49:12.656356Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"df = pd.read_csv('/kaggle/input/aiffel-ds-3-credit-card-fraud-detection/train.csv')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-12T08:49:12.660238Z","iopub.execute_input":"2024-11-12T08:49:12.661290Z","iopub.status.idle":"2024-11-12T08:49:14.412077Z","shell.execute_reply.started":"2024-11-12T08:49:12.661228Z","shell.execute_reply":"2024-11-12T08:49:14.410740Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"df.info()\ndf.describe()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-12T08:49:14.413699Z","iopub.execute_input":"2024-11-12T08:49:14.414346Z","iopub.status.idle":"2024-11-12T08:49:14.776309Z","shell.execute_reply.started":"2024-11-12T08:49:14.414290Z","shell.execute_reply":"2024-11-12T08:49:14.774919Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"##결측치없음","metadata":{}},{"cell_type":"code","source":"df.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-12T08:49:14.778645Z","iopub.execute_input":"2024-11-12T08:49:14.779041Z","iopub.status.idle":"2024-11-12T08:49:14.806262Z","shell.execute_reply.started":"2024-11-12T08:49:14.779002Z","shell.execute_reply":"2024-11-12T08:49:14.804632Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"df.tail()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-12T08:49:14.807846Z","iopub.execute_input":"2024-11-12T08:49:14.808401Z","iopub.status.idle":"2024-11-12T08:49:14.838248Z","shell.execute_reply.started":"2024-11-12T08:49:14.808354Z","shell.execute_reply":"2024-11-12T08:49:14.837047Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#Time 데이터는 unix시간으로 간주\ndf['Hour'] = df['Time'] // 3600\nfraud_trans= df[df['Class'] == 1]","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-12T08:49:14.840359Z","iopub.execute_input":"2024-11-12T08:49:14.841065Z","iopub.status.idle":"2024-11-12T08:49:14.857744Z","shell.execute_reply.started":"2024-11-12T08:49:14.841006Z","shell.execute_reply":"2024-11-12T08:49:14.856039Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import matplotlib.pyplot as plt\nimport seaborn as sns\n\n# 시간대별 사기 거래 수\nfraud_by_hour = fraud_trans.groupby('Hour').size()\n\n# 그래프 크기 설정\nplt.figure(figsize=(12, 6))\nsns.set(style=\"darkgrid\")\n\n# 시간대별 사기 거래 수 선 그래프\nplt.plot(fraud_by_hour.index, fraud_by_hour.values, label='Fraud', color='red', marker='o', linestyle='-', linewidth=2)\n\n# 제목, 축 레이블, 범례 설정\nplt.title('Fraud Transactions by Hour (48 Hours)', fontsize=16)\nplt.xlabel('Hour of Day (0-48)', fontsize=12)\nplt.ylabel('Number of Fraud Transactions', fontsize=12)\nplt.legend(loc='upper left')\n\n# X축에 시간대 0~48을 24시간씩 나누어 표시 (날짜 구분 추가 가능)\nplt.xticks(range(0, 49, 2))  # 0~48시를 2시간 간격으로 표시\nplt.grid(True)\n\n# 그래프 출력\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-12T08:49:14.859410Z","iopub.execute_input":"2024-11-12T08:49:14.859854Z","iopub.status.idle":"2024-11-12T08:49:15.435802Z","shell.execute_reply.started":"2024-11-12T08:49:14.859810Z","shell.execute_reply":"2024-11-12T08:49:15.434485Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"'''Day1 10-12시 \nDay2 1-3시 가장 사기 거래 많음'''\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-12T08:49:15.437425Z","iopub.execute_input":"2024-11-12T08:49:15.437840Z","iopub.status.idle":"2024-11-12T08:49:15.445257Z","shell.execute_reply.started":"2024-11-12T08:49:15.437800Z","shell.execute_reply":"2024-11-12T08:49:15.444009Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# 박스 플롯 생성\nsns.boxplot(x='Class', y='Amount', data=df)\n\n# 제목 및 레이블 추가\nplt.title(\"Box Plot of Amount by Class\")\nplt.xlabel(\"Class (0: Normal, 1: Fraud)\")\nplt.ylabel(\"Amount\")\n\n# 시각화 표시\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-12T08:49:15.448369Z","iopub.execute_input":"2024-11-12T08:49:15.448790Z","iopub.status.idle":"2024-11-12T08:49:15.797146Z","shell.execute_reply.started":"2024-11-12T08:49:15.448752Z","shell.execute_reply":"2024-11-12T08:49:15.795811Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#구간 별 거래 금액 확인\ninf_amt=0\nsup_amt=5000\n\nfor i in range(6):\n    print('\\n# 거래금액 {}~{} 거래 건 수'.format(inf_amt,sup_amt))\n    print(df[(df['Amount'] >= inf_amt) & (df['Amount'] < sup_amt)]['Class'].value_counts())\n    inf_amt+=5000\n    sup_amt+=5000","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-12T08:49:15.799899Z","iopub.execute_input":"2024-11-12T08:49:15.800474Z","iopub.status.idle":"2024-11-12T08:49:15.853275Z","shell.execute_reply.started":"2024-11-12T08:49:15.800419Z","shell.execute_reply":"2024-11-12T08:49:15.851914Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"'''이상치 적음'''","metadata":{}},{"cell_type":"code","source":"corr = df.corr()\n\nplt.figure(figsize=(12, 10))\n\nsns.heatmap(corr, cmap=\"coolwarm\", fmt=\".2f\", linewidths=0.5)\n\nplt.title(\"Correlation Heatmap\", fontsize=16)\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-12T08:49:15.854855Z","iopub.execute_input":"2024-11-12T08:49:15.855370Z","iopub.status.idle":"2024-11-12T08:49:17.475124Z","shell.execute_reply.started":"2024-11-12T08:49:15.855319Z","shell.execute_reply":"2024-11-12T08:49:17.473731Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# V1부터 V28까지의 고유값 개수 확인\nfor col in df.columns[1:29]:\n    print(f'{col}: {df[col].nunique()} unique values')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-12T08:49:17.476990Z","iopub.execute_input":"2024-11-12T08:49:17.478045Z","iopub.status.idle":"2024-11-12T08:49:17.772332Z","shell.execute_reply.started":"2024-11-12T08:49:17.477987Z","shell.execute_reply":"2024-11-12T08:49:17.771082Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"'''V1~V28은 연속형 변수'''","metadata":{}},{"cell_type":"code","source":"import scipy.stats as stats\nfor col in df.columns[1:29]:\n    data = df[col]\n     # Shapiro-Wilk 검정 (정규성 검정)\n    stat, p_value = stats.shapiro(data)\n    print(f'{col} - Shapiro-Wilk Test p-value: {p_value}')\n    if p_value > 0.05:\n        print(f\"V{col} 데이터는 정규분포를 따릅니다.\\n\")\n    else:\n        print(f\"V{col} 데이터는 정규분포를 따르지 않습니다.\\n\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-12T08:49:17.773755Z","iopub.execute_input":"2024-11-12T08:49:17.774139Z","iopub.status.idle":"2024-11-12T08:49:18.293453Z","shell.execute_reply.started":"2024-11-12T08:49:17.774099Z","shell.execute_reply":"2024-11-12T08:49:18.292275Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# 'Amount' 컬럼의 히스토그램 그리기\nplt.hist(df['Amount'], bins=50, edgecolor='black')\nplt.title('Histogram of Amount')\nplt.xlabel('Amount')\nplt.ylabel('Frequency')\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-12T08:49:18.294878Z","iopub.execute_input":"2024-11-12T08:49:18.295304Z","iopub.status.idle":"2024-11-12T08:49:18.712008Z","shell.execute_reply.started":"2024-11-12T08:49:18.295256Z","shell.execute_reply":"2024-11-12T08:49:18.710637Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"'''V1~V28 그리고 Amount 칼럼 데이터는 정규분포 따르지 않음\n그리고 Class 컬럼의 0, 1 데이터의 비가 0.0017로 불균형함 '''","metadata":{}},{"cell_type":"markdown","source":"위에서 파악한 특성들을 토대로\nMinMaxScaler사용: 연속형 변수 및 정규분포 안 따르므로\n\n랜덤 포레스트(Random Forest)모델: 앙상블 모델인 랜덤 포레스트는 불균형 데이터에서 잘 작동\n\nStratified K-Fold: 불균형 데이터를 다룰 때, 각 fold마다 클래스의 비율을 일정하게 유지하여 모델 성능을 보다 정확하게 평가","metadata":{}},{"cell_type":"code","source":"import matplotlib.pyplot as plt\nfrom sklearn.metrics import roc_curve, auc\nfrom sklearn.model_selection import StratifiedKFold\nfrom sklearn.preprocessing import MinMaxScaler\nfrom sklearn.ensemble import RandomForestClassifier\nfrom sklearn.metrics import accuracy_score, roc_auc_score\nimport numpy as np\n\n# Scale features\nfeatures = df.drop(columns=['Class'])\nscaler = MinMaxScaler()\nscaled_features = scaler.fit_transform(features)\ntarget = df['Class']\n\n# Optimized RandomForest parameters\nkf = StratifiedKFold(n_splits=3, shuffle=True, random_state=42)\nrf_model = RandomForestClassifier(n_estimators=50, max_depth=10, n_jobs=-1, random_state=42)\n\naccuracies = []\nauc_scores = []\n\nplt.figure(figsize=(10, 8))\n\n# Cross-validation loop\nfor train_index, val_index in kf.split(scaled_features, target):\n    X_train, X_val = scaled_features[train_index], scaled_features[val_index]\n    y_train, y_val = target.iloc[train_index], target.iloc[val_index]\n    \n    # Train the model\n    rf_model.fit(X_train, y_train)\n    \n    # Accuracy calculation\n    y_pred = rf_model.predict(X_val)\n    acc = accuracy_score(y_val, y_pred)\n    accuracies.append(acc)\n    \n    # AUC-ROC score calculation (predicting positive class probabilities)\n    y_proba = rf_model.predict_proba(X_val)[:, 1]  # Probabilities for positive class\n    roc_auc_fold = roc_auc_score(y_val, y_proba)\n    auc_scores.append(roc_auc_fold)\n    \n    # ROC curve calculation\n    fpr, tpr, thresholds = roc_curve(y_val, y_proba)\n    roc_auc_value = auc(fpr, tpr)  # 변경된 변수명\n    plt.plot(fpr, tpr, lw=2, label=f'Fold AUC = {roc_auc_value:.2f}')\n\n# Plot random classifier line (diagonal)\nplt.plot([0, 1], [0, 1], color='navy', linestyle='--')\n\n# Title and labels\nplt.title('ROC Curve for Random Forest Classifier', fontsize=16)\nplt.xlabel('False Positive Rate', fontsize=12)\nplt.ylabel('True Positive Rate', fontsize=12)\nplt.legend(loc='lower right')\nplt.grid(True)\nplt.show()\n\n# Print results\nprint(f\"Cross-validation accuracies: {accuracies}\")\nprint(f\"Mean accuracy: {np.mean(accuracies):.4f}\")\nprint(f\"Cross-validation AUC-ROC scores: {auc_scores}\")\nprint(f\"Mean AUC-ROC score: {np.mean(auc_scores):.4f}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-12T08:51:43.954658Z","iopub.execute_input":"2024-11-12T08:51:43.955110Z","iopub.status.idle":"2024-11-12T08:52:30.482982Z","shell.execute_reply.started":"2024-11-12T08:51:43.955069Z","shell.execute_reply":"2024-11-12T08:52:30.481702Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"fold 별 roc 시각화","metadata":{}}]}