본문 바로가기

소소한/#Python

[ML-Python] 회귀 분류 학습

일반적인 데이터셋을 활용한 모델 학습 - 검증 과정에 대한 대략적인 내용을 정리해 보았다.

 

1) 불러오기

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import warnings; warnings.filterwarnings(action='ignore') #경고 메세지 무시

from sklearn.model_selection import train_test_split #훈련 데이터, 테스트 데이터 분리
#from sklearn.ensemble import RandomForestClassifier as RFC #랜덤 포레스트 분류 알고리즘

from sklearn.preprocessing import StandardScaler #정규화
from sklearn.tree import DecisionTreeClassifier as DTC #의사결정나무 분류 알고리즘
from sklearn.ensemble import GradientBoostingClassifier as GBC #그래디언트 부스팅 분류 알고리즘

from sklearn.metrics import accuracy_score, precision_score, 
recall_score, f1_score, plot_confusion_matrix #모델평가를 위한 metrics

 

 

2)  데이터 불러오기

train = pd.read_csv("train_2weeks.csv")
test = pd.read_csv("test_2weeks.csv")

 

3) 데이터 확인(정보 및 그래프 활용)

train.info()
test.info()
train.head()
test.head()
train.describe()
test.describe()

pd.options.display.max_columns = None  #화면에 컬럼 모두 display하기
  • Plot을 활용한 데이터 확인(hist)
import matplotlib.pyplot as plt 
import seaborn as sns 
plt.figure(figsize = (40,40)) 
cols = train.columns 
for i in range(len(cols)):
	plt.subplot(8 , 3 , i +1) 
    plt.title(cols[i] , fontsize = 25)
    plt.hist(train[cols[i]] , bins = 40)
    
plt.show()

### 분류문제일때 , 회귀일때는 hue 사용안함

for i in range(len(cols)):
	plt.subplot(8 , 3 , i +1) 
    plt.title(cols[i] , fontsize = 25)
    sns.histplot(x = cols[i]  , hue = "target" , bins = 40 , data = train)
    
plt.show()
  • Scatter
import matplotlib.pyplot as plt 
import seaborn as sns 

cols = train.columns 
for i in range(len(cols)):
	plt.subplot(8 , 3 , i +1) 
    plt.title(cols[i] , fontsize = 25)
    plt.scatter(x= train[cols[i]] , y = train["Target"])
    
plt.show()

#Seaborn 활용한 데이터간 상관관계 확인
sns.pairplot(train)
  • Heatmap 활용하여 상관관계 보기
plt.figure(figsize = (25,25))
sns.heatmap(train.corr(), annot = True, annot_kws = {'fontsize': 10} )
#Correlation을 활용하여 상관관계 높은것만 뽑아내기
np.abs(train01.corr()["target"]) > 0.3

feature = ['A','B','C','D','E','F','G','H']
train_feature = ['A','B','C','D','E','F','G','H', 'target']

4) 결측치 확인 및 결측치 채우기, 이상치 제거

train.isnull().sum()
test.isnull().sum()
train_01 = train.fillna(train.mean()) # 평균값으로 일괄 채우는것 
train_01 = train.fillna(train.max()) # 최대값으로 일괄 채우는것 
train_01 = train.fillna(method = 'bfill') # 이전값으로 채우는것 
  
  df.dropna()
  df.dropna(how = 'all')
  df.dropna(axis = 1, how = 'all)
  df.dropna(thresh = x)
  • 이상치 제거
train[train["A"] > 1000] # 이상치가 있는 컬럼 "A"에서 대략 평균보다 훨씬 큰 1000보다 큰것으로 indexing

#특정 행 드랍

train_01 = train.drop([1248,1249] , axis = 0) ## 행을 삭제 axis = 0 으로 설정
  • 데이터가 정규분포를 따르지 않는경우 log 활용
y_train = train["Target"]
y_train_loged = np.log1p(y_train) 

#train의 종속변수를 log를 씌워 모델을 학습
model.fit(X_train ,y_train_loged)     
pred = model.predict(X_test)

# 역함수해서
pred_exp = np.expm1(pred)
  • MinMaxScaler
from sklearn.preprocessing import MinMaxScaler
# 데이터 스케일링 -> 민맥스/스텐다드 모두 성능 비슷함
scaler=MinMaxScaler()
scaler.fit(X)
X=scaler.transform(X)
# 테스트 데이터도 동일 스케일러로
test=scaler.transform(test)

5) Data Type 확인후  'Object'가 있을 때 숫자형으로 변경(Encoding)

train["Column"].value_counts() #Object 인 컬럼의 value 별로 counting
train["Column"].nunique() #컬럼의 value의 개수 확인
  • Value가 5개 넘는 경우 Label Encoding 
from sklearn.preprocessing import LabelEncoder

Le = LabelEncoder() #LabelEncoder함수
Le.fit(train["Column"]) 
L_encoding = Le.transform(train["Column"]) # transform으로 변환

train["Column_Encoding"] = L_encoding #새로운 컬럼에 대입

#test data encoding
Le.transform(test["Column"])
  • Value가 5개 이하일 경우 One-Hot Encoding
train01 = pd.get_dummies(train) #One hot encoding, Object로 구성된 모든 column을 encoding
#특정 컬럼만 one hot encoding 할 경우
train01 = pd.get_dummies(train["Column01", "Column02", "Column03"])
train02 = pd.concat([train, train01], axis = 1)
  • X_train, y_train, X_test 데이터셋 준비
#설명변수만분리
X_train = train[train.columns.difference(['target'])]
y_train = train["target"]
X_test = test

6) 모델 선정

  • 적당한 모델을 선정한다
  • 모델선정을 위해서는 기존 이론으로 접근하는 방법과 Pycaret을 통해 가능성 있는 모델을 찾는 방법도 유효하다
from pycaret.classification import *
setup(train, "Target")
top3 = compare_models(n_select = 3, sort = "Accuracy") #모델 앙상블
tuned = [tune_model(i) for i in top3]
blended = blend_models(tuned,  method = 'soft') #soft voting
final = finalize_model(blended)
prediction = predict_model(final, test)
pred_caret = prediction["Label"]
  • Hyperparameter 튜닝을 통해 성능을 끌어올린다
# 회귀(Regressor)문제로 작성
# 분류문제는 regressor -> classifier로 대체
from sklearn.ensemble import RandomForestRegressor 
rf_reg = RandomForestRegressor() 

from lightgbm import LGBMRegressor
lgbm_reg = LGBMRegressor()

from xgboost import XGBRegressor 
xgb_reg = XGBRegressor()

from catboost import CatBoostRegressor
cat_reg = CatBoostRegressor()
  • Hyperparameter 튜닝은 수동으로 진행 할 수 있지만  아래와 같이 GridSearch라는 툴을 활용하여 최적화 할 수 있다
#Grid Search
from sklearn.model_selection import GridSearchCV

##Parameter Set
param_GS_lgbm = {'num_leaves':[20],
           'min_child_samples':[5],
           'max_depth':[6],
           'learning_rate':[0.1],
           'reg_alpha':[0.02]}
param_GS_rf = {
    'n_estimators' : [125],
    'max_depth' : [18],
    'min_samples_split' : [0.01],
    'min_samples_leaf' : [1],
    'max_features' : ['auto']
}
param_GS_gbc = {
    'random_state' : [2],
    'max_depth' : [5],
    'learning_rate' : [0.06]
}

#Grid Search 모델 생성
lgbm_GS = GridSearchCV(estimator = lgbm,
                    param_grid = param_GS_lgbm,
                    n_jobs = -1,
                    verbose = 2)
rf_GS = GridSearchCV(estimator = rf,
                    param_grid = param_GS_rf,
                    n_jobs = -1,
                    verbose = 2)
gbc_GS = GridSearchCV(estimator = gbc,
                    param_grid = param_GS_gbc,
                    n_jobs = -1,
                    verbose = 2)                    

#Grid Search 학습
rf_GS.fit(X_train, y_train)
lgbm_GS.fit(X_train, y_train)
gbc_GS.fit(X_train, y_train)

#최적의 파라미터 확인
rf_GS.best_params_
lgbm_GS.best_params_
gbc_GS.best_params_
  • 베이지안최적화
from bayes_opt import BayesianOptimization

#목적함수 생성
def lgbm_cv(learning_rate, num_leaves, max_depth, min_child_weight, colsample_bytree, feature_fraction, bagging_fraction, lambda_l1, lambda_l2):
    model = lgbm.LGBMClassifier(learning_rate=learning_rate,
                                n_estimators = 300,
                                #boosting = 'dart',
                                num_leaves = int(round(num_leaves)),
                                max_depth = int(round(max_depth)),
                                min_child_weight = int(round(min_child_weight)),
                                colsample_bytree = colsample_bytree,
                                feature_fraction = max(min(feature_fraction, 1), 0),
                                bagging_fraction = max(min(bagging_fraction, 1), 0),
                                lambda_l1 = max(lambda_l1, 0),
                                lambda_l2 = max(lambda_l2, 0)
                               )
    scoring = {'roc_auc_score': make_scorer(roc_auc_score)}
    result = cross_validate(model, X, y, cv=5, scoring=scoring)
    auc_score = result["test_roc_auc_score"].mean()
    return auc_score
    
    # 입력값의 탐색 대상 구간
pbounds = {'learning_rate' : (0.0001, 0.05),
           'num_leaves': (300, 600),
           'max_depth': (2, 25),
           'min_child_weight': (30, 100),
           'colsample_bytree': (0, 0.99),
           'feature_fraction': (0.0001, 0.99),
           'bagging_fraction': (0.0001, 0.99),
           'lambda_l1' : (0, 0.99),
           'lambda_l2' : (0, 0.99),
          }
          
          #객체 생성
lgbmBO = BayesianOptimization(f = lgbm_cv, pbounds = pbounds, verbose = 2, random_state = 0 )

lgbmBO.maximize(init_points=5, n_iter = 20, acq='ei', xi=0.01)

lgbmBO.max

fit_lgbm = lgbm.LGBMClassifier(learning_rate=lgbmBO.max['params']['learning_rate'],
                               num_leaves = int(round(lgbmBO.max['params']['num_leaves'])),
                               max_depth = int(round(lgbmBO.max['params']['max_depth'])),
                               min_child_weight = int(round(lgbmBO.max['params']['min_child_weight'])),
                               colsample_bytree=lgbmBO.max['params']['colsample_bytree'],
                               feature_fraction = max(min(lgbmBO.max['params']['feature_fraction'], 1), 0),
                               bagging_fraction = max(min(lgbmBO.max['params']['bagging_fraction'], 1), 0),
                               lambda_l1 = lgbmBO.max['params']['lambda_l1'],
                               lambda_l2 = lgbmBO.max['params']['lambda_l2']
                               )
                               
model = fit_lgbm.fit(X,y)
  • K-Fold 를 통하여 Cross Validation(교차 검증)
from sklearn.model_selection import KFold
kfold = KFold(n_splits = 10)

for train_idx, test_idx in kfold.split(X_train ,y_train):
    X_tr , y_tr = X_train.iloc[train_idx] , y_train.iloc[train_idx]
    X_val , y_val = X_train.iloc[test_idx] , y_train.iloc[test_idx]
    
    #검증할 모델 선언
    rf_clf = RandomForestClassifier(max_depth = 18, 
                                    max_features = 'auto', 
                                    min_samples_leaf = 1, 
                                    min_samples_split = 0.01, 
                                    n_estimators = 125)
                                    
    
    #모델활용검증@classifier
    rf_clf = RandomForestClassifier()
    rf_clf.fit(X_tr , y_tr)
    pred_rf = rf_clf.predict(X_val)
    rf_accuracy = accuracy_score(y_val , pred_rf)
    print("rf 정확도는 {0}% 입니다".format(rf_accuracy * 100))
    
    #모델활용검증@Regressor
    xgb_reg = XGBRegressor()
    xgb_reg.fit(X_tr ,y_tr)
    pred_xgb = model.predict(X_val)
    xgb_score = rmse(y_val , pred_xgb)
    print("rf 정확도는 {0}% 입니다".format(xgb_score * 100))
  • 분류문제의 경우 여러 모델을 구성할 경우 Voting 필요
from sklearn.ensemble import VotingClassifier

VC = VotingClassifier(estimators=[('rf',rf_clf),('cat',cat_clf),
                                        ('lgbm',lgbm_clf),('gbc',gbc_clf)],
                                       voting = 'hard')
                                       
VC.fit(X_tr,y_tr)

pred_VC = VC.predict(X_val)
VC_accuracy = accuracy_score(y_val , pred_VC)
print("VC 정확도는 {0}% 입니다".format(VC_accuracy * 100))
pred_VC = VC.predict(X_test)

7) 모델 학습 및 결과

rf_reg.fit(X_train, y_train) #학습
pred = rf_reg.predict(X_test) #결과 예측

 

8) 제출파일 작성

submission = pd.read_csv("submission.csv")
submission["Target"] = pred
submission.to_csv("submission_횟수_이름.csv", index = False) #index = False는 인덱스 미생성