본문 바로가기
IT - 코딩/AI, 예측모델

[데이콘]데이크루 6 _ 신용카드 연체 예측

by 조기정 2023. 9. 17.

 

 

 

신용카드 사용은 현대 사회의 필수적인 결제 수단이다. 그러나 연체와 같은 신용 위험이 증가하고 있다.
연체를 미리 예측하는 것은 중요하며, 그 문제를 머신러닝을 활용해 해결하는 방법을 초보자를 위해 설명합니다.

 

 

신용 카드 연체 예측 모델을 구축하고 평가하는 방법을 학습하는 것이 목표입니다.
학습 과정은 데이터 전처리, 모델 선택 및 학습, 모델 성능 평가, 모델 최적화로 구성됩니다.

 

모델 성능 향상을 위해 사용한 방법은

 

1. 파생변수 생성
2. 데이터 스케일링
3. 하이퍼파라미터 튜닝
4. 다중공선성 처리
5. 추가 데이터 확보
6. 앙상블

이렇게 6가지 방법들이 되겠고,

import numpy as np # 전처리 라이브러리 임포트
# 파생변수 생성 및 주석

# 1. 파생변수 생성을 위해 음수값 양수로 전환
# 일부 변수들에서의 일수는 음수로 표시되어 있어 계산의 편의성을 위해 양수로 전환합니다.
negative_list = ['DAYS_EMPLOYED', 'DAYS_BIRTH', 'begin_month']
for i in negative_list:
    train[f"{i}"] = -train[f"{i}"]

# 2. 사용자의 나이 계산
# 사용자가 태어난 지 몇 일이 지났는지를 기반으로 나이를 계산합니다.
train['Age'] = abs((train['DAYS_BIRTH']) / 365)

# 3. 사용자의 고용된 연수 계산
# 얼마나 오래 전에 고용되었는지를 나타내는 변수입니다.
train['Years_Employed'] = train['DAYS_EMPLOYED'].apply(lambda x: -x / 365 if x < 0 else 0)  # 양수값은 무직자로 간주하고 0 처리
train.loc[train['DAYS_EMPLOYED'] < 0, 'DAYS_EMPLOYED'] = 0

# 4. 사용자의 연락 수단 수 계산
# 사용자가 가지고 있는 연락 수단의 총 수를 계산합니다.
train['Contact_Count'] = train['FLAG_MOBIL'] + train['work_phone'] + train['phone'] + train['email']

# 5. 소득 대비 자녀 수
# 각 사용자의 소득에 대한 자녀 수의 비율을 계산합니다.
train['income_per_child'] = train['income_total'] / (train['child_num'] + 1)

# 6. 부양가족 수당 소득
# 사용자의 총 소득을 부양가족 수로 나누어 한 부양가족 당 평균 소득을 계산합니다.
train['income_per_family'] = train['income_total'] / (train['family_size'])

# 7. 고용전 일수
# 사용자가 처음으로 고용되기 전까지의 전체 일수를 계산합니다.
train['before_EMPLOYED'] = train['DAYS_BIRTH'] - train['DAYS_EMPLOYED']

# 8. 고용되기 전까지의 시간 대비 총 소득
# 사용자의 총 소득을 고용되기 전까지의 일수로 나눈 값을 계산합니다.
train['income_total_befofeEMP_ratio'] = train['income_total'] / train['before_EMPLOYED']

# 9. 사용자가 처음으로 고용되기 전까지의 월 수
# 사용자가 처음으로 고용되기 전까지의 월 수를 계산합니다.
train['before_EMPLOYED_m'] = np.floor(train['before_EMPLOYED'] / 30) - ((np.floor(train['before_EMPLOYED'] / 30) / 12).astype(int) * 12)

# 10. 가장의 명수
# 부양 가족 수에서 자녀의 수를 뺀 값은 경제 활동을 할 수 있는 가장의 수를 나타냅니다.
train["active_parents"] = train["family_size"]-train["child_num"]
train.loc[train['active_parents'] < 0, 'active_parents'] = 0

해당 방법들로 하여금 파생변수를 생성하였습니다.

  1. 음수값을 양수로 전환: 일부 변수들에서의 일수는 음수로 표시되어 있습니다. 이러한 음수값은 데이터셋에서 어떤 기준 시점으로부터의 경과일을 나타내기 때문입니다. 이 값들을 양수로 변환하여 계산의 편의성을 높입니다.
  2. Age: DAYS_BIRTH 변수를 사용하여 사용자의 나이를 계산합니다. DAYS_BIRTH는 사용자가 태어난 지 몇 일이 지났는지를 나타내므로, 이를 365로 나누어 나이를 계산합니다.
  3. Years_Employed: 사용자가 얼마나 오래 전에 고용되었는지를 나타내는 변수입니다. DAYS_EMPLOYED의 값은 고용된 일수를 나타냅니다. 양수 값은 무직 상태를 나타내므로 0으로 처리하고, 음수 값은 고용된 기간을 나타냅니다.
  4. Contact_Count: 사용자가 가지고 있는 연락 수단의 총 수를 나타냅니다. 여기에서는 모바일, 직장 전화, 개인 전화, 이메일의 유무를 합하여 총 연락 수단 수를 계산합니다.
  5. income_per_child: 이 파생변수는 각 사용자의 소득에 대한 자녀 수의 비율을 나타냅니다. 소득이 높아도 자녀 수가 많으면 부담이 클 수 있으므로, 이 비율로 그 부담을 나타낼 수 있습니다.
  6. income_per_family: 사용자의 총 소득을 부양가족 수로 나누어 한 부양가족 당 평균 소득을 계산합니다.
  7. before_EMPLOYED: before_EMPLOYED는 사용자가 처음으로 고용되기 전까지의 전체 일수를 나타냅니다. 이는 사용자의 전체 생애 (DAYS_BIRTH)에서 고용된 일수 (DAYS_EMPLOYED)를 뺀 값으로 계산됩니다.
  8. income_total_befofeEMP_ratio: 사용자의 총 소득을 고용되기 전까지의 일수로 나눈 값을 나타냅니다.
  9. before_EMPLOYED_m: 사용자가 처음으로 고용되기 전까지의 월 수를 나타냅니다.
  10. active_parents: 부양 가족 수에서 자녀의 수를 뺀 값입니다. 이 값은 경제 활동을 할 수 있는 부모님의 수를 나타냅니다.
    이렇게 다양한 파생변수를 생성함으로써 모델의 성능을 향상시킬 수 있는 추가 정보를 데이터에 포함시킬 수 있습니다.

 

Kmeans 클러스터링 학습

# 두 범주형 변수 선택
kmeans_cols = ['income_type', 'edu_type']

# Label Encoding
label_encoders = {}
for col in kmeans_cols:
    le = LabelEncoder()
    kmeans_data[col] = le.fit_transform(kmeans_data[col])
    label_encoders[col] = le

kmeans_data[['income_type', 'edu_type']].head()

각 범주형 데이터인 'income_type'과 'edu_type'이 숫자로 매핑된 것을 확인할 수 있습니다.

KMeans 알고리즘 적용 및 WCSS 값 계산

이제 변환된 수치형 데이터를 사용하여 KMeans 알고리즘을 적용하고, 다양한 k 값에 대한 WCSS 값을 계산하겠습니다. WCSS는 클러스터 내의 제곱 거리의 합을 나타내며, 이 값을 사용하여 최적의 k 값을 선택하는 데 도움을 받을 수 있습니다.

WCSS 값이 급격히 감소하는 지점, 즉 "elbow point"를 찾아서 최적의 클러스터 개수를 결정할 수 있습니다. 여기서는 k의 범위를 1부터 10까지로 설정하고 WCSS 값을 계산해보겠습니다.

 

하이퍼파라미터 튜닝



GridSearchCV는 하이퍼파라미터 튜닝 작업을 수행하기 위한 함수입니다.
xgb_grid는 최적의 파라미터를 찾기 위해 테스트할 모델입니다.
param_grid는 연구자가 선정한 파라미터의 조합을 정의합니다. 이 안에서 최적의 파라미터가 선정됩니다.
scoring 인자의 값으로 입력한 'accuracy'는 파라미터 탐색을 위한 평가 지표로 정확도를 사용하겠다는 의미입니다.
cv 값이 3이란 것은 3-폴드 교차 검증을 수행하겠다는 것을 의미합니다.
verbose의 값을 1로 입력한 것은 그리드 서치의 진행 상황을 출력하겠다는 것을 의미합니다.
n_jobs의 값을 -1로 입력한 것은 가능한 모든 CPU 코어를 사용하여 파라미터 탐색 작업을 병렬로 수행하겠다는 것을 의미합니다.

그리드서치 수행

 

from sklearn.model_selection import GridSearchCV
from xgboost import XGBClassifier

# XGBoost 모델 객체 생성
xgb_grid = XGBClassifier()

# 그리드 서치를 위한 파라미터 그리드 정의
param_grid = {
    'learning_rate': [0.01, 0.05, 0.1],
    'n_estimators': [100, 200],
    'max_depth': [3, 5, 7],
    'subsample': [0.8, 0.9, 1],
    'colsample_bytree': [0.8, 0.9, 1]
}

# GridSearchCV 객체 생성
grid_search = GridSearchCV(xgb_grid, param_grid, scoring='accuracy', cv=3, verbose=1, n_jobs=-1) #cv로 교차 검증

# 그리드 서치 수행
grid_search.fit(X_train, y_train)

# 최적의 파라미터 출력
grid_search.best_params_

최적 모델 결과 확인

from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score # 평가지표 라이브러리 import

# 모델 학습
xgb_best.fit(X_train, y_train)

# 추론
best_pred = xgb_best.predict(X_val)

# 성능 평가
accuracy_2 = accuracy_score(y_val, best_pred)
precision_2 = precision_score(y_val, best_pred, average='macro')
recall_2 = recall_score(y_val, best_pred, average='macro')
f1_2 = f1_score(y_val, best_pred, average='macro')

print("Accuracy: ", accuracy_2)
print("Precision: ", precision_2)
print("Recall: ", recall_2)
print("F1-score: ", f1_2)

 

Feature Importances 및 변수 Customizing

모델의 성능은 불필요한 변수를 제거함으로써 향상될 수 있으며 여러 가지 이유가 있습니다:

1. 차원의 저주 (Curse of Dimensionality):

고차원의 데이터 공간에서는 데이터 포인트 간의 거리가 크게 증가하기 때문에, 예측 모델이 올바른 판단을 내리기가 어려워집니다. 이는 특히 군집화, 최근접 이웃 검색과 같은 거리 기반 알고리즘에서 중요합니다. 불필요한 변수를 제거함으로써 차원을 줄이면, 데이터 포인트 간의 관계를 더 쉽게 파악할 수 있게 됩니다.
2. 과적합 (Overfitting):

불필요한 변수가 많을수록 모델은 훈련 데이터에 대한 불필요한 패턴까지 학습할 위험이 있습니다. 이로 인해 테스트 데이터나 실제 환경에서의 성능이 저하될 수 있습니다. 변수를 제거하면 모델의 복잡성이 감소하고, 과적합을 방지할 수 있습니다.
3. 계산 효율성:

변수의 수가 줄어들면 학습, 예측, 검증 과정의 계산 비용이 줄어듭니다. 이로 인해 모델의 학습과 추론 속도가 빨라집니다.
4. 모델의 해석성 (Interpretability):

중요하지 않은 변수가 제거되면, 남아있는 변수들 사이의 관계가 더 명확해집니다. 따라서 모델의 예측을 해석하기가 더 쉬워집니다.
5. 다중공선성 (Multicollinearity):

변수들 사이에 강한 상관관계가 있을 경우, 다중공선성이 발생할 수 있습니다. 이는 회귀 모델에서 계수의 추정치가 불안정해질 수 있게 만듭니다. 불필요한 변수를 제거함으로써 다중공선성 문제를 줄일 수 있습니다.
6. 노이즈 감소:

불필요한 변수는 종종 데이터의 노이즈를 증가시키는 원인이 됩니다. 이러한 변수를 제거함으로써 노이즈가 감소하고, 모델의 일반화 성능이 향상될 수 있습니다.
7. 특성 선택의 중요성:

특성 선택을 통해 가장 중요한 변수들만을 사용하면, 해당 변수들이 예측에 얼마나 큰 영향을 미치는지 더 잘 이해할 수 있습니다. 요약하면, 불필요한 변수를 제거함으로써 모델의 성능은 물론, 학습 속도, 모델의 해석성 등 여러 면에서 이점을 얻을 수 있습니다.

이제 모델의 Feature Importances를 추출하고 그에 맞게 변수를 조절하며 모덜 성능을 개선해보겠습니다.

 

 

import matplotlib.pyplot as plt
importances = xgb_best.feature_importances_

# Feature names 가져오기
features = X_train.columns

# Feature importance와 함께 정렬된 순서의 index 가져오기
indices = np.argsort(importances)

# Plot
plt.figure(figsize=(10, 12))
plt.title('Feature Importances')
plt.barh(range(len(indices)), importances[indices], align='center')
plt.yticks(range(len(indices)), [features[i] for i in indices])
plt.xlabel('Relative Importance')
plt.show()

 

 

 

 

이제 낮은 중요도의 변수를 제거하고 모델을 재학습시키겠습니다

# Feature importances를 낮은 중요도 순으로 정렬
sorted_indices = np.argsort(importances)

# 정렬된 순서에 따라 feature names 가져오기
sorted_features = [features[i] for i in sorted_indices]


# drop 변수 리스트
drop_list = sorted_features[:6]

# 모델 학습
xgb_best.fit(X_train.drop(columns = drop_list, axis = 1), y_train.drop(columns = drop_list, axis = 1))

# 추론
best_pred = xgb_best.predict(X_val.drop(columns = drop_list, axis = 1))

# 성능 평가
accuracy_2 = accuracy_score(y_val, best_pred)
precision_2 = precision_score(y_val, best_pred, average='macro')
recall_2 = recall_score(y_val, best_pred, average='macro')
f1_2 = f1_score(y_val, best_pred, average='macro')

print("Accuracy: ", accuracy_2)
print("Precision: ", precision_2)
print("Recall: ", recall_2)
print("F1-score: ", f1_2)

 

 

 

 

 

 

 

데이콘 링크 

https://dacon.io/competitions/official/236116/codeshare/8753

 

[월곡동솜주먹] 신용카드 사용자 연체 예측

데이크루 6기

dacon.io

 

 

전체 코드 => https://github.com/GiJungCho/AI_project_/blob/main/%EC%8B%A0%EC%9A%A9%EC%B9%B4%EB%93%9C%EC%97%B0%EC%B2%B4%EC%98%88%EC%B8%A1/%5B%EC%9B%94%EA%B3%A1%EB%8F%99%EC%86%9C%EC%A3%BC%EB%A8%B9%5D_%EC%8B%A0%EC%9A%A9%EC%B9%B4%EB%93%9C%20%EC%82%AC%EC%9A%A9%EC%9E%90%20%EC%97%B0%EC%B2%B4%20%EC%98%88%EC%B8%A1.ipynb