본문 바로가기
WIL

내배캠 TIL 38일차

by ColorConeHead 2024. 2. 13.
반응형

심화 프로젝트 관련

1) 결측치 대치

2) 이상치 제거


4분위수를 사용한 방법은 유실 데이터가 너무 많아 기각.

EDS를 사용한 방법 채택.
def remove_outliers(train_df, col, threshold=3):
    mean = np.mean(train_df[col])
    std_dev = np.std(train_df[col])
    lower_bound = mean - threshold * std_dev
    upper_bound = mean + threshold * std_dev
    train_df= train_df[(train_df[col] >= lower_bound) & (train_df[col] <= upper_bound)]
    return train_df

numeric_col = ['대출금액', '연간소득', '부채_대비_소득_비율', '총계좌수', '최근_2년간_연체_횟수', '총상환원금', '총상환이자', '총연체금액', '연체계좌수', '근로기간']
category_col = ['대출기간', '주택소유상태', '대출목적']

for col in numeric_col:
    df_simple = remove_outliers(df_simple, col, threshold=3)​

 

 

 

3) 스캐일링


numeric_col 컬럼 중에서 히스토그램의 개형을 토대로

sc_col = ['최근_2년간_연체_횟수', '총연체금액', '연체계좌수']
mm_col = ['대출금액', '연간소득', '부채_대비_소득_비율', '총계좌수', '총상환원금', '총상환이자', '근로기간']

위와 같이 스캐일링 방법을 정함.
from sklearn.model_selection import train_test_split

X = df.drop(['ID', '대출등급'], axis=1)
y = df[['대출등급']]

def numeric_scaler(X):
    
    sc_col = ['최근_2년간_연체_횟수', '총연체금액', '연체계좌수']
    mm_col = ['대출금액', '연간소득', '부채_대비_소득_비율', '총계좌수', '총상환원금', '총상환이자', '근로기간']
    
    from sklearn.preprocessing import StandardScaler, MinMaxScaler
    
    sc = StandardScaler()
    mm = MinMaxScaler()
    
    X[sc_col] = sc.fit_transform(X[sc_col])
    X[mm_col] = mm.fit_transform(X[mm_col])
    
    return X

X = numeric_scaler(X)

 

 

4) 인코딩


category_col = ['대출기간', '주택소유상태', '대출목적']
에서 우위를 따질 컬럼은 없어 보이기에 onehot 인코딩으로 통일.

종속변수 y, 대출등급은 Label 인코딩을 사용.
def category_encoder(X:pd.DataFrame):
     X_dummies = pd.get_dummies(X[category_col])
     
     X = pd.concat([X, X_dummies], axis=1)
     
     return X, X_dummies.columns.to_list()

X, dummies_col = category_encoder(X)

from sklearn.preprocessing import LabelEncoder

le = LabelEncoder()
le.fit(y['대출등급'])

y['대출등급'] = le.transform(y['대출등급'])​

 

 

5) 오버 샘플링


확인 결과 대출 등급이 낮은 데이터가 현저히 적다.
오버샘플링을 통해 보완한다.

오버샘플링을 위해 인코딩 먼저 하고 스캐일링을 진행.
이후 파생변수를 생성한다.
X = df.drop(['ID', '대출등급'], axis=1)
y = df[['대출등급']]

X, dummies_col = category_encoder(X)
X = X.drop(columns=category_col)

from sklearn.preprocessing import LabelEncoder

le = LabelEncoder()
le.fit(y['대출등급'])

y['대출등급'] = le.transform(y['대출등급'])

from imblearn.over_sampling import SMOTE
sm = SMOTE(random_state=42)

X, y = sm.fit_resample(X, y)

X = numeric_scaler(X)

### 대출 등급별 category_col 분포 특성을 반영
X['dv_category'] = ((2 * X['대출기간_ 36 months']) + X['주택소유상태_MORTGAGE'] + X['대출목적_부채 통합']) / 4

### 대출금액 대비 총상환원금(0인 값 처리를 위해 +1)
X['dv_ratio'] = (X['총상환원금'] + 1) / (X['대출금액'] + 1)

### 단기상환능력
X['dv_short_ability'] = (X['연간소득'] / 12) - (X['대출금액'] / 36)

### 잔여대출금
X['dv_left_debt'] = X['대출금액'] - X['총상환원금'] - X['총상환이자']

### 대출 금액 대비 총상환금 비율
X['dv_rent_p'] = X['총상환원금'] / X['대출금액']
X['dv_rent_i'] = X['총상환이자'] / X['대출금액']

dummies_col = dummies_col + ['dv_category']
numeric_col = numeric_col + ['dv_ratio', 'dv_short_ability', 'dv_left_debt', 'dv_rent_p', 'dv_rent_i']

 

 

6) 모델링


여러 모델을 돌려보고 점수가 잘 나오는 모델로 선정.
def get_score(train:pd.DataFrame,  test:pd.DataFrame, x_var_list:list):
    
    X_train = train 
    X_test = test

    X_train = X_train[x_var_list]
    X_test = X_test[x_var_list]
    
    from sklearn.linear_model import LogisticRegression
    from sklearn.tree import DecisionTreeClassifier
    from sklearn.ensemble import RandomForestClassifier, GradientBoostingClassifier
    from xgboost import XGBClassifier
    from lightgbm import LGBMClassifier
    from sklearn.metrics import f1_score, accuracy_score
    
    logit = LogisticRegression()
    decision = DecisionTreeClassifier(random_state=42)
    rfc = RandomForestClassifier(random_state=42)
    gbc = GradientBoostingClassifier(random_state=42)
    xgb = XGBClassifier(random_state=42)
    light = LGBMClassifier(random_state=42)
    
    logit.fit(X_train, y_train)
    decision.fit(X_train, y_train)
    rfc.fit(X_train, y_train)
    gbc.fit(X_train, y_train)
    xgb.fit(X_train, y_train)
    light.fit(X_train, y_train)
    
    y_pred_train = logit.predict(X_train)
    y_pred_test = logit.predict(X_test)
    
    result_logit = pd.DataFrame({'acc' : [accuracy_score(y_train, y_pred_train), accuracy_score(y_val, y_pred_test)],
                            'f1_score' : [f1_score(y_train, y_pred_train, average='macro'), f1_score(y_val, y_pred_test, average='macro')]},
                            index = ['train','test'])
    
    y_pred_train = decision.predict(X_train)
    y_pred_test = decision.predict(X_test)
    
    result_decision = pd.DataFrame({'acc' : [accuracy_score(y_train, y_pred_train), accuracy_score(y_val, y_pred_test)],
                            'f1_score' : [f1_score(y_train, y_pred_train, average='macro'), f1_score(y_val, y_pred_test, average='macro')]},
                            index = ['train','test'])
    
    y_pred_train = rfc.predict(X_train)
    y_pred_test = rfc.predict(X_test)
    
    result_rfc = pd.DataFrame({'acc' : [accuracy_score(y_train, y_pred_train), accuracy_score(y_val, y_pred_test)],
                            'f1_score' : [f1_score(y_train, y_pred_train, average='macro'), f1_score(y_val, y_pred_test, average='macro')]},
                            index = ['train','test'])
    
    y_pred_train = gbc.predict(X_train)
    y_pred_test = gbc.predict(X_test)
    
    result_gbc = pd.DataFrame({'acc' : [accuracy_score(y_train, y_pred_train), accuracy_score(y_val, y_pred_test)],
                            'f1_score' : [f1_score(y_train, y_pred_train, average='macro'), f1_score(y_val, y_pred_test, average='macro')]},
                            index = ['train','test'])
    
    y_pred_train = xgb.predict(X_train)
    y_pred_test = xgb.predict(X_test)
    
    result_xgb = pd.DataFrame({'acc' : [accuracy_score(y_train, y_pred_train), accuracy_score(y_val, y_pred_test)],
                            'f1_score' : [f1_score(y_train, y_pred_train, average='macro'), f1_score(y_val, y_pred_test, average='macro')]},
                            index = ['train','test'])
    
    y_pred_train = light.predict(X_train)
    y_pred_test = light.predict(X_test)
    
    result_light = pd.DataFrame({'acc' : [accuracy_score(y_train, y_pred_train), accuracy_score(y_val, y_pred_test)],
                            'f1_score' : [f1_score(y_train, y_pred_train, average='macro'), f1_score(y_val, y_pred_test, average='macro')]},
                            index = ['train','test'])
    
    print('로지스틱')
    display(result_logit.round(2))
    print()
    print('의사결정나무')
    display(result_decision.round(2))
    print()
    print('랜덤포레스트')
    display(result_rfc.round(2))
    print()
    print('그라디언트 부스팅')
    display(result_gbc.round(2))
    print()
    print('XG 부스팅')
    display(result_xgb.round(2))
    print()
    print('Light GBM')
    display(result_light.round(2))

get_score(X_train, X_val, dummies_col + numeric_col)​
기본 골조는 여기서 바뀌지 않을 듯 하다.

후에 나온 결과들을 가지고 파생변수를 추가한다던지 정도?

지금까지의 결과는 다음과 같다.

1) 중위 등급을 잘 분류하지 못한다.
2) 파생변수 dv_rent_i가 중요도가 높은데 이는 상환이자, 즉 이자율을 반영한 것으로 보임.
반응형

'WIL' 카테고리의 다른 글

내배캠 WIL 11주차  (0) 2024.03.08
내배캠 WIL 10주차  (3) 2024.02.29
내배캠 WIL 8주차  (0) 2024.02.08
내배캠 WIL 7주차  (0) 2024.02.02
내배캠 6주차 WIL  (0) 2024.01.26