Programming

Credit Card Fraud Detection 1편 : Feature Engineering과 Baseline 모델 성능 분석

Lucas.Kim 2025. 12. 26. 14:25
반응형

신용카드 사기 탐지는 대표적인 극심한 클래스 불균형(Class Imbalance) 문제입니다.
전체 거래 중 사기 거래 비율은 0.2% 미만으로, 단순 정확도(Accuracy)만으로는 모델 성능을 제대로 평가할 수 없습니다.

본 글(1편)에서는 다음을 목표로 합니다.

  • 원본 데이터의 레이블 불균형 구조 파악
  • Feature Engineering 이전 상태에서의 Baseline 모델 성능 확인
  • Logistic Regression, LightGBM의 기본 성능 비교
  • 왜 이후 단계에서 Feature Engineering이 필수적인지 문제의식 정리

데이터 로드 및 기본 구조 확인

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

card_df = pd.read_csv('./creditCard/creditcard.csv')
card_df.head(3)
# amount 중요 컬럼

card_df.shape

 

  • creditcard.csv 데이터는 유럽 카드 거래 데이터로,
  • Class 컬럼이 타겟 레이블입니다.
    • 0 : 정상 거래
    • 1 : 사기 거래
  • Amount 컬럼은 거래 금액으로 유일한 원본 스케일 피처입니다.

데이터 전처리 함수 구성

Time 컬럼 제거

from sklearn.model_selection import train_test_split

def get_prepreocessed_df(df=None):
    df_copy = df.copy()
    df_copy.drop('Time', axis=1, inplace = True)
    return df_copy

 

 

  • Time 컬럼은 거래 발생 시점을 나타내지만,
  • 본 실험에서는 모델 성능에 직접적인 의미를 주기 어렵다고 판단하여 제거합니다.
  • 원본 데이터 보호를 위해 항상 copy()를 사용합니다.

학습 / 테스트 데이터 분리

def get_train_test_dataset(df=None):
    df_copy = get_prepreocessed_df(df)

    X_features = df_copy.iloc[:,:-1]
    y_target = df_copy.iloc[:,-1]

    X_train, X_test, y_train, y_test = train_test_split(
        X_features,
        y_target,
        test_size=0.3,
        random_state=0,
        stratify=y_target
    )
    
    return X_train, X_test, y_train, y_test

 

 

  • Train : Test = 70 : 30
  • stratify=y_target을 적용하여
    사기/정상 비율이 학습·테스트 데이터에서 동일하게 유지되도록 합니다.

레이블 불균형 확인

X_train, X_test, y_train, y_test = get_train_test_dataset(card_df)

print(f'학습 데이터 레이블 값 비율 : {y_train.value_counts()/y_train.shape[0]*100}')
print(f'테스트 데이터 레이블 값 비율 : {y_test.value_counts()/y_test.shape[0]*100}')

 

실행 결과:

  • 학습 데이터
    • 정상(Class 0): 99.83%
    • 사기(Class 1): 0.17%
  • 테스트 데이터 역시 동일한 비율을 유지합니다.

👉 모델은 아무런 처리 없이 학습할 경우 정상 거래만 예측해도 높은 정확도를 얻게 되는 구조입니다.

 

모델 평가 함수 정의

from sklearn.metrics import confusion_matrix,accuracy_score, precision_score, recall_score, f1_score
from sklearn.metrics import roc_auc_score

def get_clf_eval(y_test, pred=None, pred_proba = None):
    confusion = confusion_matrix(y_test, pred)
    accuracy = accuracy_score(y_test, pred)
    precision = precision_score(y_test, pred)
    recall = recall_score(y_test,pred)
    f1 = f1_score(y_test,pred)
    roc_auc = roc_auc_score(y_test, pred_proba)
    print(
        f"Confusion Matrix\n{confusion}\n"
        f"(1)정확도 : {accuracy}\n"
        f"(2)정밀도 : {precision}\n"
        f"(3)재현율 : {recall}\n"
        f"(4)F1 : {f1}\n"
        f"(5)roc_auc : {roc_auc}"
    )

 

  • 사기 탐지 문제에서는 **재현율(Recall)**이 가장 중요합니다.
  • 단 하나의 사기 거래라도 놓치지 않는 것이 비즈니스적으로 더 중요하기 때문입니다.

Baseline ① Logistic Regression

from sklearn.linear_model import LogisticRegression

lr_clf = LogisticRegression(max_iter=1000)
lr_clf.fit(X_train, y_train)
lr_pred = lr_clf.predict(X_test)
lr_pred_proba = lr_clf.predict_proba(X_test)[:,1]

get_clf_eval(y_test, lr_pred, lr_pred_proba)


결과 해석
[[85281    14]
 [   58    90]]

 

  • 실제 사기 거래 중 58건을 놓침(False Negative)
  • 재현율(Recall): 0.608

👉 정확도는 99.9%로 매우 높지만
👉 사기 거래의 약 40%를 놓치는 심각한 문제가 있습니다.

 

공통 학습/평가 함수 구성

def get_model_train_eval(model, ftr_train=None,ftr_test=None, tgt_train=None, tgt_test=None):
    model.fit(ftr_train, tgt_train)
    pred=model.predict(ftr_test)
    pred_proba = model.predict_proba(ftr_test)[:,1]
    get_clf_eval(y_test, pred, pred_proba)

이후 Feature Engineering을 적용할 때
모델 구조는 그대로 두고 데이터만 변경하여 성능 비교하기 위함입니다.

 

Baseline ② LightGBM

boost_from_average 설명

  • LightGBM 2.1.0 이상에서는 boost_from_average=True가 기본값입니다.
  • 클래스 불균형이 극심한 경우:
    • 초기 score가 평균값 기준으로 설정되면서
    • 재현율과 ROC-AUC가 급격히 저하될 수 있습니다.
  • 따라서 사기 탐지에서는 False로 설정하는 것이 유리합니다.
from lightgbm import LGBMClassifier

lgbm_clf = LGBMClassifier(
    n_estimators=1000,
    num_leaves=64,
    n_jobs=-1,
    boost_from_average=False
)

get_model_train_eval(
    lgbm_clf,
    ftr_train=X_train,
    ftr_test=X_test,
    tgt_train=y_train,
    tgt_test=y_test
)

[[85290     5]
 [   36   112]]
  • 재현율(Recall): 0.756
  • Logistic Regression 대비 사기 검출 성능이 확연히 개선

👉 하지만 여전히 약 25%의 사기 거래를 놓침

 

모델 Recall ROC-AUC
Logistic Regression 0.608 0.970
LightGBM 0.756 0.979
  • 단순 모델 학습만으로는 사기 탐지 성능에 명확한 한계가 존재합니다.
  • 다음 문제가 확인됩니다.
    • 거래 금액(Amount) 분포 왜곡
    • 이상치(Outlier) 존재
    • 극단적인 클래스 불균형

👉 2편에서는 Feature Engineering(분포 변환, 이상치 제거, SMOTE)을 통해 이 문제를 단계적으로 개선합니다.

반응형