Python/머신러닝, 딥러닝

Python 머신러닝 LightGBM

dustKim 2024. 6. 16. 00:53
Credit Dataset
더보기
# 필요한 모듈
import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
# credit 데이터셋 데이터프레임으로 읽어오기
credit_df = pd.read_csv("파일경로")
credit_df
결과

 

 

# 데이터프레임 정보확인
credit_df.info()
결과
정보

 

 

# 사용하지 않을 column 제외
credit_df.drop(["ID", "Customer_ID", "SSN", "Name"], axis=1, inplace=True)

# 다시 정보확인
credit_df.info()
결과

 

 

# Credit_Score의 값들 확인
credit_df["Credit_Score"].value_counts()
결과

 

 

# Credit_Score의 값들을 숫자로 변경
credit_df["Credit_Score"] = credit_df["Credit_Score"].replace({"Poor": 0, "Standard": 1, "Good": 2})
credit_df.head()
결과

 

 

# 데이터프레임 통계정보 확인
credit_df.describe()
결과

 

 

# corr() 함수로 관계성 한번에 확인하기
plt.figure(figsize=(12, 12))
sns.heatmap(credit_df.corr(numeric_only=True), cmap="coolwarm", vmin=-1, vmax=1, annot=True)
결과

 

 

# dtype이 object인 것들 확인
for i in credit_df.columns:
  if credit_df[i].dtype == 'O':
    print(i)
결과

 

 

# column에 값들 중 _로 되어있는게 있음
# _지우기
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_History_Age 값 확인
credit_df["Credit_History_Age"]
결과

 

 

# Credit_History_Age의 데이터를 개월로 변경
# 22 Year and 1 Months -> 22 * 12 + 1 = 265
credit_df['Credit_History_Age'] = credit_df['Credit_History_Age'].str.replace(' Months', '')

# 22 Year and 1
# expand=True 데이터프레임으로 만들어줌
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()
결과

 

 

# Age column 값 확인
sns.boxplot(y=credit_df["Age"])
결과



# 나이가 110세 미만의 값만 저장한다.
credit_df = credit_df[credit_df["Age"] < 110]
결과

 

 

# 카드를 갖고있는 개수를 20개로 제한
credit_df = credit_df[credit_df["Num_Credit_Card"] <= 20]

# 통계정보 확인
credit_df.describe()
결과

 

 

# 이자 40퍼센트 이하로 제한
credit_df = credit_df[credit_df["Interest_Rate"] <= 40]

# 통계정보 확인
credit_df.describe()
결과

 

 

# 대출 수는 20 이하로 제한
credit_df = credit_df[(credit_df["Num_of_Loan"] <= 20) & (credit_df["Num_of_Loan"] >= 0)]

# 통계정보 확인
credit_df.describe()
결과

 

 

# 연체 기간이 0보다 큰 값으로 제한
credit_df = credit_df[credit_df["Delay_from_due_date"] >= 0]

# 연체된 결제 수를 30개 이하로 제한
credit_df = credit_df[(credit_df["Num_of_Delayed_Payment"] < 30) & (credit_df["Num_of_Delayed_Payment"] >= 0)]

# 통계정보 확인
credit_df.describe()
결과

 

 

# Num_Credit_Inquiries의 null값을 0으로 대체
credit_df["Num_Credit_Inquiries"] = credit_df["Num_Credit_Inquiries"].fillna(0)
# 데이터프레임 결측값(null값) 확인
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의 모든 대출 상품을 변수에 저장
# NaN인 데이터는 "No Loan"으로 대체
# 대출상품 만큼의 컬럼을 만들고 해당 대출 상품을 받았다면 1 아니면 0으로 데이터 처리

# Auto Loan, Auto Loan and Not Specified => Auto Loan, Auto Loan, Not Specified 
credit_df["Type_of_Loan"] = credit_df["Type_of_Loan"].str.replace("and ", '')


# NaN인 데이터는 "No Loan"으로 대체
credit_df["Type_of_Loan"] = credit_df["Type_of_Loan"].fillna("No Loan")


# 각 값을 추출하기, 같은 값은 set을 사용하여 한번만 표현됨
type_list = set(credit_df["Type_of_Loan"].str.split(", ").sum())


# 대출상품 만큼의 컬럼을 만들고 해당 대출 상품을 받았다면 1 아니면 0으로 데이터 처리
for i in type_list:
  credit_df[i] = credit_df["Type_of_Loan"].apply(lambda x: 1 if i in x else 0)
  
  
  # Type_of_Loan 제외
  credit_df.drop("Type_of_Loan", axis=1, inplace=True)
  
  
  credit_df.info()
결과

 

 

# Occupation
# "-----"를 "Unknown"로 바꿈
credit_df["Occupation"] = credit_df["Occupation"].str.replace("_______", "Unknown")
credit_df.head()
결과

 

 

# Payment_Behaviour
# "!@9#%8"를 "Unknown"로 바꿈
credit_df["Payment_Behaviour"] = credit_df["Payment_Behaviour"].str.replace("!@9#%8", "Unknown")
credit_df["Payment_Behaviour"].value_counts()
결과

 

# 위 Object를 원핫인코딩
credit_df = pd.get_dummies(credit_df, columns=["Occupation", "Payment_of_Min_Amount", "Payment_Behaviour"])
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
결과

 

lightGBM(LGBM)

 

- Microsoft에서 개발한 Gradient Boosting Framework이다

- 리프 중심 히스토그램 기반의 알고리즘이다.

- 작은 데이터셋에서도 높은 성능을 보이며, 특히 대용량 데이터셋에서 다른 알고리즘보다 빠르게 학습한다.

- 메모리 사용량이 상대적으로 적은 편이다.

- 적은 데이터셋을 사용할 경우 과적합 가능성이 매우 크다.(일반적으로 데이터가 10,000개 이상은 있어야 함)

      과적합 : 학습에 친화적인고 테스트는 엉망, train 데이터는 좋은데 test 데이터는 성능이 안 좋음

- 조기 중단(early stopping)

 

  • 리프 중심 히스토그램 기반 알고리즘

- 트리를 균형적으로 분할할 것이 아니라, 최대한 불균형하게 분할한다.

- 특성들의 분포를 히스토그램으로 나타내고, 해당 히스토그램을 이용하여 빠르게 후보 분할 기준을 선택한다.

- 후보 분할 기준 중에서 최적의 분할 기준을 선택하기 위해, 데이터 포인트들을 히스토그램에 올바르게 배치하고, 이를 이용하여 최적의 분할기준을 선택한다.

 

 

  • GBM(Gradient Boosting Model)

- 순차적으로 모델을 학습 시킨다.

- 첫 번째 모델을 학습시키고, 두 번째 모델은 첫 번째 모델의 오류를 학습하는 식으로 진행(이런 방식으로 각 모델이 이전 모델의 오류를 보완한다.

- 부스팅에서는 각 데이터 포인트에 가중치를 부여. 초기에는 모든 데이터 포인트에 가중치를 부여하지만, 이후 모델이 학습되면서 잘못 예측된 데이터 포인트의 가중치를 증가시켜 다음 모델이 이 데이터 포인트에 더 주의를 기울이도록 한다.

- 트리가 모두 학습된 후 예측 결과를 결합하여 최종 예측을 만드는데 일반적으로 분류 문제에서는 다수결 투표 방식으로, 회귀 문제에서는 예측값의 평균을 사용한다.

 

  • 부스팅 모델의 주요 개념

- 약한 학습기(Wesk Learner): 단독으로 성능이 좋지 않은 간단한 모델(주로 깊이가 얕은 결정 트리, 깊이가 1인 매우 간단한 학습기)을 사용한다.

- 약한 학습기를 순차적으로 학습시키고 그다음에는 첫 번째 학습기의 오류를 보완하는 두 번째 학습기를 학습시킨다.

 

더보기
# import 
from lightgbm import LGBMClassifier

# 객체 생성
base_model = LGBMClassifier(random_state=2024)

# 훈련
base_model.fit(X_train, y_train)

# 예측
pred = base_model.predict(X_test)

# 평가지표 import
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
결과

 

 

proba = base_model.predict_proba(X_test)
proba
결과

 

roc_auc_score(y_test, proba, multi_class="ovr")
결과