Python/머신러닝(ML)
Python(25)- LightGBM
두설날
2024. 6. 19. 08:49

*이 글을 읽기전에 작성자 개인의견이 있으니, 다른 블로그와 교차로 읽는것을 권장합니다.*
1. credit 데이터셋
import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
credit_df = pd.read_csv('/content/drive/MyDrive/KDT/6. 머신러닝과 딥러닝/Data/credit.csv')
credit_df
credit_df.info()
- ID: 고유 식별자
- Customer_ID: 고객 ID
- Name: 이름
- Age: 나이
- SSN: 주민등록번호
- Occupation: 직업
- Annual_Income: 연간 소득
- Num_Bank_Accounts: 은행 계좌 수
- Num_Credit_Card: 신용 카드 수
- Interest_Rate: 이자율
- Num_of_Loan: 대출 수
- Type_of_Loan: 대출 유형
- Delay_from_due_date: 마감일로부터 연체 기간
- Num_of_Delayed_Payment: 연체된 결제 수
- Num_Credit_Inquiries: 신용조회 수
- Outstanding_Debt: 미상환 잔금
- Credit_Utilization_Ratio: 신용카드 사용률
- Credit_History_Age: 카드 사용 기간
- Payment_of_Min_Amount: 리볼빙 여부
- Total_EMI_per_month: 월별 총 지출 금액
- Amount_invested_monthly: 매월 투자 금액
- Payment_Behaviour: 지불 행동
- Monthly_Balance: 월별 잔고
- Credit_Score: 신용 점수
credit_df.drop(['ID', 'Customer_ID', 'SSN', 'Name'], axis=1, inplace=True)
credit_df.info()
credit_df['Credit_Score'].value_counts()
credit_df['Credit_Score'] = credit_df['Credit_Score'].replace({'Poor':0, 'Standard':1, 'Good':2})
credit_df.head()
credit_df.describe()
sns.barplot(x='Payment_of_Min_Amount', y='Credit_Score', data=credit_df)
plt.figure(figsize=(20,5))
sns.barplot(x='Occupation', y='Credit_Score', data=credit_df)
plt.figure(figsize=(12,12))
sns.heatmap(credit_df.corr(numeric_only=True), cmap='coolwarm', vmin=-1, vmax=1, annot=True)
credit_df.info()
for i in credit_df.columns:
if credit_df[i].dtype == 'O':
print(i)
credit_df
for i in ['Age', 'Annual_Income', 'Num_of_Loan', 'Num_of_Delayed_Payment', 'Outstanding_Debt', 'Amount_invested_monthly']:
credit_df[i] = pd.to_numeric(credit_df[i].str.replace('_', ''))
credit_df.info()
credit_df['Credit_History_Age']
# Credit_History_Age의 데이터를 개월로 변경
# 22 Years and 1 Months -> 22 * 12 + 1 = 265
credit_df['Credit_History_Age'] = credit_df['Credit_History_Age'].str.replace(' Months', '')
# 22 Years and 1
credit_df['Credit_History_Age'] = pd.to_numeric(credit_df['Credit_History_Age'].str.split(' Years and ', expand=True)[0])*12 + pd.to_numeric(credit_df['Credit_History_Age'].str.split(' Years and ', expand=True)[1])
credit_df.head()
credit_df.describe()
credit_df[credit_df['Age'] < 0]
# <0 제거
credit_df = credit_df[credit_df['Age'] >= 0]
credit_df.sort_values('Age').head(5)
credit_df.sort_values('Age').tail(20)
sns.boxplot(y=credit_df['Age'])
# 100세보다 큰사람 범위
credit_df[credit_df['Age'] >= 100].sort_values('Age')
credit_df = credit_df[credit_df['Age']<110]
credit_df.describe()
len(credit_df[credit_df['Num_Bank_Accounts'] > 10]) / len(credit_df)
# 갯수가 50~10개 사이가 거의 없음
# 통장 10개에서 타협
credit_df = credit_df[credit_df['Num_Bank_Accounts'] <= 10]
credit_df.describe()
len(credit_df[credit_df['Num_Credit_Card'] > 20]) / len(credit_df)
credit_df = credit_df[credit_df['Num_Credit_Card'] <= 20]
credit_df.describe()
# 이자
credit_df = credit_df[credit_df['Interest_Rate'] <= 40]
credit_df.describe()
len(credit_df[credit_df['Num_of_Loan']>20])
credit_df = credit_df[(credit_df['Num_of_Loan'] <= 20) & (credit_df['Num_of_Loan'] >= 0)]
# 카드대출 0~20이하 저장
credit_df.describe()
credit_df = credit_df[credit_df['Delay_from_due_date']>=0]
len(credit_df[credit_df['Num_of_Delayed_Payment'] > 30])
# 연체횟수 0~30
credit_df = credit_df[(credit_df['Num_of_Delayed_Payment'] <= 30) & (credit_df['Num_of_Delayed_Payment'] >= 0)]
credit_df.describe()
credit_df.info()
credit_df['Num_Credit_Inquiries'] = credit_df['Num_Credit_Inquiries'].fillna(0)
credit_df.isna().mean()
# 얼마만큼 카드를 오래 썼는지
sns.displot(credit_df['Credit_History_Age'])
sns.displot(credit_df['Amount_invested_monthly'])
sns.displot(credit_df['Monthly_Balance'])
credit_df = credit_df.fillna(credit_df.median(numeric_only=True))
credit_df.isna().mean()
# Type_of_Loan 제외 null값 처리
credit_df.head()
# 문제
# Type_of_Loan의 모든 대출 상품을 변수에 저장
# NaN인 데이터는 'No Loan'으로 대체
# 마지막은 대출상품 만큼의 column을 만들고 해당 대출 상품을 받았다면 1 아니면 0으로 데이터 처리
# 원핫인코딩처럼
# Auto Loan, Auto Loan, and Not Specified
credit_df['Type_of_Loan'] = credit_df['Type_of_Loan'].str.replace('and ', '')
credit_df.isna().mean()
credit_df['Type_of_Loan'] = credit_df['Type_of_Loan'].fillna('No Loan')
credit_df.isna().mean()
# set()로 중복 처리
type_list = set(credit_df['Type_of_Loan'].str.split(', ').sum())
type_list
for i in type_list:
credit_df[i] = credit_df['Type_of_Loan'].apply(lambda x: 1 if i in x else 0)
credit_df.head()
credit_df.drop('Type_of_Loan', axis=1, inplace=True)
credit_df.info()
# Occupation
# _______ 를 'Unknown'
credit_df['Occupation'].value_counts()
credit_df['Occupation'] = credit_df['Occupation'].replace('_______', 'Unknown')
credit_df['Occupation'].value_counts()
# Payment_of_Min_Amount
# '!@9#%8'를 'Unknown'
credit_df['Payment_of_Min_Amount'].value_counts()
# Payment_Behaviour
credit_df['Payment_Behaviour'].value_counts()
credit_df['Payment_Behaviour'] = credit_df['Payment_Behaviour'].replace('!@9#%8', 'Unknown')
credit_df['Payment_Behaviour'].value_counts()
credit_df.info()
# 위 object를 원핫인코딩
credit_df = pd.get_dummies(credit_df, columns=['Occupation', 'Payment_of_Min_Amount', 'Payment_Behaviour'])
credit_df.head()
credit_df.info()
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(credit_df.drop('Credit_Score', axis=1), credit_df['Credit_Score'], test_size=0.2, random_state=2024)
X_train.shape, y_train.shape
X_test.shape, y_test.shape
2. lightGBM(LGBM)
- Microsoft에서 개발한 Gradient Boosting Framework
- 리프 중심 히스토그램 기반 알고리즘
- 작은 데이터셋에서도 높은 성능을 보이며, 특히 대용량 데이터셋에서 다른 알고리즘보다 빠르게 학습
- 메모리 사용량이 상대적으로 적은편
- 적은 데이터셋을 사용할 경우 과적합 가능성이 매우 큼(일반적으로 데이터가 10, 000개 이상은 사용해야 함)
- 조기 중단(early stopping)을 지원
2-1. 리프 중심 히스토그램 기반 알고리즘
- 리프(나뭇가지 모형)
- 데이터를 나눌 수 있는 피쳐를 데이터의 특징을 짚어서, 오류가 난다면 다른 트리로 넘어가는 방식
- 트리를 균형적으로 분할하는 것이 아니라, 최대한 불균형하게 분할
- 특성들의 분포를 히스토그램으로 나타내고, 해당 히스토그램을 이용하여 빠르게 후보 분할 기준을 선택
- 후보 분할 기준 중에서 최적의 분할 기준으로 선택하기 위해, 데이터 포인트들을 히스토그램에 올바르게 배치하고 이를 이용하여 최적의 분할 기준을 선택
2-2. GBM(Gradient Boostring Model)
- 순차적으로 모델을 학습시킴
- 첫번째 모델을 학습시키고, 두번째 모델은 첫번째 모델의 오류를 학습하는 식으로 진행
- 부스팅에서는 각 데이터 포인트에 가중치를 부여, 초기에는 모든 데이터 포인트에 동일한 가중치를 부여하지만, 이후 모델이 학습되면서 잘못 예측된 데이터 포인트의 가중치를 증가시켜 다음 모델이 데이터 포인트에 더 주의를 기울이도록 함
- 트리가 모두 학습된 후 예측 결과를 결합하여 최종 예측을 만드는데, 일반적으로 분류 문제에서는 다수결 투표 방식으로, 회귀 문제에서는 예측값의 평균을 사용
- Gradient: 다변수 함수의 각 변수에 대한 변화율을 나타내는 벡터
2-3. 부스팅 모델의 주요 개념
- 약한 학습기(Weak Leaner): 단독으로는 성능이 좋지 않은 간단한 모델(주로 깊이가 얕은 결정 트리, 깊이가 1인 매우 간단한 학습기)을 사용
- 약한 학습기를 순차적으로 학습시키고 그 다음에는 첫번째 학습기의 오류를 보완하는 두번째 학습기를 학습시킴
from lightgbm import LGBMClassifier
base_model = LGBMClassifier(randome_state=2024)
base_model.fit(X_train, y_train)
pred = base_model.predict(X_test)
from sklearn.metrics import accuracy_score, confusion_matrix, classification_report, roc_auc_score
accuracy_score(y_test, pred)
confusion_matrix(y_test, pred)
print(classification_report(y_test, pred))
proba = base_model.predict_proba(X_test)
proba
5.31741083e-02, 5.47962223e-01, 3.98863668e-01
roc_auc_score(y_test, proba, multi_class='ovr')
# 2진분류일땐 상관없으나, 분류가 여러개일땐 적어놓아야함