5 분 소요

🚩 Chapter 04


목차(Context)

  • 01.모델링을 위한 데이터 사전 준비
  • 02.Model Selection
  • 03.모델링 및 성능 비교 (1)
  • 04.모델링 및 성능 비교 (2)
  • 05.Model evaluation

01. 모델링을 위한 데이터사전 준비


모델이 이해할 수 있는 데이터의 형태로 가공

  • 모델은 숫자로 이루어진 형태의 Data만 인식 가능 (※ 문자형 변수 인코딩 필요)
  • 모델링을 수행하기 위해 Feature와 예측하고자하는 값인 Y로 데이터를 나눔
  • 학습과 예측을 위한 Train / Test set 분할

대표적인 Encoding의 방법

  1. One-hot encoding : 범주형(Categorical) 변수의 유형 만큼 새로운 Feature를 생성하고, 1과 0으로 표현
  2. Label encoding : 범주형(Categorical) 변수의 unique한 값만큼 증가하는 숫자를 부여

① One-hot encoding

  • 범주형 데이터의 unique한 값이 증가하면 증가할 수록 변수의 차원이 늘어나는 효과
  • 예측 성능의 저하
  • 범주형 변수의 Unique한 수준을 축소하고 사용하기를 권장

② Label encoding

  • Unique하고 증가하는 숫자값으로 변환되어 숫자의 ordianl한 특성이 반영되어 의도하지 않은 관계성이 생김
  • 숫자값을 가중치로 잘 못 인식하여 값에 왜곡이 생김
  • 예측 성능의 저하
  • 선형회귀와 같은 ML 알고리즘에는 적용하지 않음
  • Tree 계열의 알고리즘은 숫자의 ordinal한 특성을 반영하지 않으므로 진행 가능

image

# ▶ 최종 추출된 Mart read
import pandas as pd
df_mart = pd.read_csv('df_mart.csv')
df_mart.head()
# ▶ 학습에 필요없는 Column 제거
df_mart = df_mart.drop(['bsym', 'CustomerID', 'total_amt_grp', 'n_target', 'grp'], axis=1)
df_mart.head()
# ▶ 모델링을 학습하기 위한 Feature(X)와 Target(Y)데이터를 구분하는 단계 
from sklearn.model_selection import train_test_split

X = df_mart.drop(['target'], axis=1)
Y = df_mart['target']

x_train, x_test, y_train, y_test = train_test_split(X, Y, test_size=0.3, stratify=Y, random_state=1234)

print(x_train.shape)
print(y_train.shape)

print(x_test.shape)
print(y_test.shape)
  • x,y split
  • stratify=Y: 균등한 분류 가능, 넣어주면 좋음
# ▶ 숫자형(Integer), 범주형(Categorical) 변수 분할
numerical_list=[]
categorical_list=[]

for i in df_mart.columns :
  if df_mart[i].dtypes == 'O' :
    categorical_list.append(i)
  else :
    numerical_list.append(i)

print("categorical_list :", categorical_list)
print("numerical_list :", numerical_list)
  • O는 object-> categorical_list에 append
  • 나머지는 numerical
# ▶ (1) One hot encoding

from sklearn.preprocessing import OneHotEncoder

for col in categorical_list :
  encoder = OneHotEncoder()
  encoder.fit(x_train[col](https://code7ssage.github.io/col//))
  onehot_train = pd.DataFrame(encoder.transform(x_train[col](https://code7ssage.github.io/col//)).toarray(), columns = encoder.get_feature_names(), index=x_train.index)
  onehot_test = pd.DataFrame(encoder.transform(x_test[col](https://code7ssage.github.io/col//)).toarray(), columns = encoder.get_feature_names(), index=x_test.index)
  # 기존 Col은 삭제
  x_train = pd.concat([x_train,onehot_train], axis = 1).drop(columns = [col])
  x_test = pd.concat([x_test,onehot_test], axis = 1).drop(columns = [col])
  • fit은 항상 train data로
  • x_train을 0,1 array로 변환, column은 feature에서 가져오고, index(행)는 기존과 동일
  • concat: 두 column을 먼저 붙이고, drop: 이후 기존 column drop
x_train.iloc[0,:], x_test.iloc[0,:]
# ▶ (2) label encoding

from sklearn.preprocessing import LabelEncoder

for col in categorical_list :
  encoder = LabelEncoder()
  encoder.fit(x_train[col](https://code7ssage.github.io/col//))
  
  # 기존 Col 대체
  x_train[col] = encoder.transform(x_train[col]) 
  x_test[col] = encoder.transform(x_test[col]) 
  • columns의 개수가 바뀌지 않아 더 간단
x_train.iloc[0,:], x_test.iloc[0,:]

02. Model Selection


학습할 Model들을 List-up하는 과정

  • 대표적인 알고리즘에 대해서는 모두 Test 하는 것이 유리
  • 분석하고자하는 데이터의 특성이 모두 다르므로 완벽한 알고리즘은 없음
  • “All models are wrong, but some are useful”
  • 최신 개발되고 복잡한 알고리즘이 가장 성능이 높은 것은 아님
  • Data by Data
  • 동일한 작동원리의 알고리즘을 사용하기보다는, 다른 작동원리를 가지고 있는 다양한 알고리즘을 선정

Regression

  • 선형회귀 모델 (Ridge, Lasso, Elastic Net)
  • 비선형회귀 모델 (polynomial, log모형)
  • Tree 계열 Regression 모델
    • bagging 앙상블 (Randomforest)
    • boosting 앙상블 (lightGBM)

Classification

  • 로지스틱 모델 (logistic regression)
  • Tree 계열 Classification 모델
    • bagging 앙상블 (Randomforest)
    • boosting 앙상블 (lightGBM)

image <그림 - 베깅, 부스팅>

03. 모델링 및 성능비교 (1)


Model 학습

  • Model Selection 단계에서 선정한 모델들을 학습하고 성능을 기록
  • 동일한 Data set, 동일한 환경에서 동일한 비교 지표로 성능을 비교
    • randomstate 동일한거(=seed고정)

성능평가

  • Regression
    • MAE(Mean Absolute Errors) : 평균절대오차, 단위 자체가 기존 데이터와 동일
    • MSE(Mean Squared Errors) : 평균제곱오차, 제곱으로 인해 원래의 오차보다 민감하게 오차가 표현됨, 오차의 민감도를 높이는 효과
    • RMSE(Root Mean Square of Errors) : MSE에 Root를 씌어 단위를 맞춤
    • R^2(R Squared Score) : 결정계수, 관측값의 분산대비 예측값의 분산을 비교하여 모델의 정확도 성능을 측정, 0~1까지 표현
  • Classification
    • Precision(정밀도) : True(정답)이라고 예측한 것 들 중에 실제 True(정답)인 것의 비율
    • Recall(재현율, sensitivity) : 실제 True(정답)인 것 중에 모델이 True(정답)이라고 예측한 것의 비율
    • F1-score(조화평균) : Precision과 Recall의 조화평균, 데이터의 label이 불균형일 때, 모델의 성능을 객관적으로 평가할 수 있음
    • AUC, AUROC(Area Under ROC Curve) : X축(FPR, False Positive Rate), False인데 True라고 잘 못 예측하 비율 / Y축(Recall)

image

04. 모델링 및 성능비교 (2)


Model 학습

* Model (1) : Logistic Regression
* Model (2) : Random Forest
* Model (3) : LightGBM

└ Logistic Regression

# ▶ Logistic Regression 표준화(standardization) (※정규화(0~1), Normalization)
from sklearn.preprocessing import StandardScaler

scaler = StandardScaler()
x_train_sc = scaler.fit_transform(x_train)
x_test_sc = scaler.transform(x_test)
  • 회귀 모델에서 표준화 vs 정규화 뭐 쓸지 선택해야함
  • 여기서는 표준화로 진행
# ▶ 표준화된 데이터 확인 
x_train_sc
# ▶ Model 학습
from sklearn.linear_model import LogisticRegression

LR = LogisticRegression()
LR.fit(x_train_sc, y_train)
# ▶ 계수 확인
print(LR.coef_)
print(x_train.columns)
# ▶ 계수 확인
df_coef = pd.DataFrame(x_train.columns, columns=['val'])
df_coef['coef'] = LR.coef_.reshape(-1,1)
df_coef.sort_values(by=['coef'],ascending =False)
  • 양의 상관 관계, 음의 상관 관계 파악
from sklearn.metrics import classification_report

# ▶ 예측 및 성능 확인
y_pred_train = LR.predict(x_train_sc)
y_pred_test = LR.predict(x_test_sc)

print(classification_report(y_train, y_pred_train))
print(classification_report(y_test, y_pred_test))
  • classification report: precision, recall, f1 score, support 등 확인 가능
  • train, test 둘 다 보기
# ▶ 과적합 문제, Train과 Test set에 성능을 최대한 줄여주는 것이 과적합을 방지
from sklearn.metrics import roc_auc_score

y_pred_train_proba = LR.predict_proba(x_train_sc)[:, 1] 
y_pred_test_proba = LR.predict_proba(x_test_sc)[:, 1] 


roc_score_train = roc_auc_score(y_train, y_pred_train_proba)
roc_score_test = roc_auc_score(y_test, y_pred_test_proba)

print("roc_score_train :", roc_score_train)
print("roc_score_test :", roc_score_test)
  • predict_proba: 0에 속할 확률, 1에 속할 확률 예측하는 2가지 출력 [;, 1] 은 1에 속할 확률만 표시
  • roc_auc_score: y값과 proba를 비교하여 점수를 산출
# ▶ 여러 Model의 성능 비교를 위한 빈 DataFrame 생성
df_comparison = pd.DataFrame(columns = {'model', 'f1_train', 'f1_test', 'AUC_train', 'AUC_test'})
df_comparison.columns = ['model', 'f1_train', 'f1_test', 'AUC_train', 'AUC_test']
df_comparison
# ▶ LR model에 대한 성능 값 추가
import sklearn.metrics as metrics

lr_re = pd.DataFrame({ 'model' : ['LR'],
                      'f1_train' :  metrics.f1_score(y_train,y_pred_train),
                      'f1_test' : metrics.f1_score(y_test,y_pred_test),
                      'AUC_train' : roc_auc_score(y_train, y_pred_train_proba),
                      'AUC_test' : roc_auc_score(y_test, y_pred_test_proba),}
                    )

df_comparison = df_comparison.append(lr_re)
df_comparison

└ Random Forest

# ▶ RandomForest
from sklearn.ensemble import RandomForestClassifier

rfc = RandomForestClassifier()
#rfc = RandomForestClassifier(max_depth=2)
rfc.fit(x_train, y_train)

# ▶ 예측
y_pred_train = rfc.predict(x_train)
y_pred_test = rfc.predict(x_test)

print(classification_report(y_train, y_pred_train))
print(classification_report(y_test, y_pred_test))
  • 일단은 hyperparameter 튜닝은 안하고 디폴트 값으로 진행
  • 근데 train f1이 1.00이 나오네? -> overfitting
# ▶ AUC
y_pred_train_proba = rfc.predict_proba(x_train)[:, 1] 
y_pred_test_proba = rfc.predict_proba(x_test)[:, 1] 

roc_score_train = roc_auc_score(y_train, y_pred_train_proba)
roc_score_test = roc_auc_score(y_test, y_pred_test_proba)

print("roc_score_train :", roc_score_train)
print("roc_score_test :", roc_score_test)
# ▶ RFC model에 대한 성능 값 추가
rfc_re = pd.DataFrame({ 'model' : ['RFC'],
                      'f1_train' :  metrics.f1_score(y_train,y_pred_train),
                      'f1_test' : metrics.f1_score(y_test,y_pred_test),
                      'AUC_train' : roc_auc_score(y_train, y_pred_train_proba),
                      'AUC_test' : roc_auc_score(y_test, y_pred_test_proba),}
                    )

df_comparison = df_comparison.append(rfc_re)
df_comparison

└ LightGBM

# ▶ lightGBM
import lightgbm as lgbm
from lightgbm import LGBMClassifier

LGBM = lgbm.LGBMClassifier()
LGBM.fit(x_train, y_train)
# ▶ 예측
y_pred_train = LGBM.predict(x_train)
y_pred_test = LGBM.predict(x_test)

print(classification_report(y_train, y_pred_train))
print(classification_report(y_test, y_pred_test))
# ▶ AUC
y_pred_train_proba = LGBM.predict_proba(x_train)[:, 1] 
y_pred_test_proba = LGBM.predict_proba(x_test)[:, 1] 

roc_score_train = roc_auc_score(y_train, y_pred_train_proba)
roc_score_test = roc_auc_score(y_test, y_pred_test_proba)

print("roc_score_train :", roc_score_train)
print("roc_score_test :", roc_score_test)
  • 얘도 random forest 보다는 덜하지만 overfitting인 듯
lgbm_re = pd.DataFrame({ 'model' : ['LGBM'],
                      'f1_train' :  metrics.f1_score(y_train,y_pred_train),
                      'f1_test' : metrics.f1_score(y_test,y_pred_test),
                      'AUC_train' : roc_auc_score(y_train, y_pred_train_proba),
                      'AUC_test' : roc_auc_score(y_test, y_pred_test_proba),}
                    )

df_comparison = df_comparison.append(lgbm_re)
df_comparison

05. Model evaluation


전체 모델 성능 평가

  • Hyper-parameter tunning 전 전체 모델 성능 비교

과적합(Over-fitting)

  • train data를 활용하여 학습된 모델의 성능과 test data를 예측한 성능의 Gap이 큰것
  • train data에 너무 치중되어 학습한 결과로 발생함
  • 과적합이 발생하면, Robust한 모델이 될 수 없고, 모델 운영시 일정한 성능을 유지할 확률이 낮음

과적합(Over-fitting) 해결방법

  • 다양한 방법들이 존재하지만, 현업에서는 하이퍼파라미터 조절을 통한 규제로 과적합을 방지
  • Tree modle을 예시로 max_depth(분기의 깊이) 값을 작은 값으로 설정하여 모델이 학습 데이터를 덜 학습하게 만듬
  • 더 Robust한 모델을 만들기 위해서 Train/Test data를 활용하여 하이퍼파라미터를 튜닝하고, Validation set으로 최종 성능평가를 진행함
  • Train / Validation / Test의 성능 차이의 Gap을 최소화하면서 성능을 향상시킬 수 있는 튜닝을 진행

image

df_comparison = df_comparison.reset_index(drop=True)
df_comparison

댓글남기기