본문 바로가기
Python/머신러닝+딥러닝 Ⅰ

교차검증

by Mr.DonyStark 2024. 3. 22.

□ 교차검증이란 테스트 세트만으로 모델학습의 일반화 정도를 검증하기에 부족하여, 기존 트레이닝세트에서 검증세트를 분리 후 Fold 교차검증을 통해 모델에 대한 학습 일반화를 향상시키는 것.

 

□ 예제

 ○ 데이터 호출

import pandas as pd
wine = pd.read_csv("https://bit.ly/wine_csv_data")

 

 ○인풋/타깃 데이터 분리

#타깃데이터
target = wine["class"].to_numpy()
#특성데이터
data = wine[["alcohol", "sugar", "pH"]].to_numpy()
print(data.shape)

 

 ○트레이닝, 테스트 데이터 나누기

#훈련/테스트 세트 나누기
from sklearn.model_selection import train_test_split

train_input, test_input, train_target, test_target = train_test_split(data, target, test_size=0.2, random_state=42) #트레이닝 80% + 테스트 20%

print(f"트레이닝 세트(분리 전) : {train_input.shape}")

 

 ○검증세트 나누기

#검증 세트 나누기
sub_input, val_input, sub_target, val_target = train_test_split(train_input, train_target, test_size=0.2, random_state=42)
print(f"트레이닝 세트(분리 후) : {sub_input.shape}")
print(f"검증세트 : {val_input.shape}")

검증세트는 하이퍼파라미터 튜닝을위해 나눔

 

 ○ 모델생성 : Decision_Tree

#모델생성
from sklearn.tree import DecisionTreeClassifier
dt = DecisionTreeClassifier(random_state=42)
#학습
dt.fit(sub_input,sub_target)
#점수
print(f"트레이닝 세트 훈련점수 : {dt.score(sub_input,sub_target)}")
print(f"검증 세트 훈련점수 : {dt.score(val_input,val_target)}")

훈련세트에 과대적합된 것을 확인할 수 있음. 검증세트를 너무 조금 떼어놓으면 점수가 들쑥날쑥 불안정할 것임. 이를 위해 우리는 교차검증을 이용함.<br>교차검증은 검증세트를 떼어 내어 평가하는 과정을 여러번하는 반복후 이점수를 평균내어 최종 검증점수를 산출함.

 

※ k-폴드교차 검증(k-fold cross validation) 훈련세트를 몇 부분으로 나누냐에 따라 다르게 부름.
※ k겹 교차검증.
※ 사이킷런의 cross_validate() 사용.
 - fit_time: 모델훈련시간
 - score_time: 모델검증시간(스코어를 산출하기위한 시간)
 - test_score: 검증폴드점수

from sklearn.model_selection import cross_validate
scores = cross_validate(dt, train_input, train_target)
print(scores)
출력값
{'fit_time': array([0.00897694, 0.00814533, 0.00896764, 0.01017714, 0.00892115]),
'score_time': array([0.00099778, 0.00199533, 0.0015521 , 0.00209641, 0.00199223]),
'test_score': array([0.86923077, 0.84615385, 0.87680462, 0.84889317, 0.83541867])} 

 

import numpy as np
final_k_score = np.mean(scores["test_score"])
print(f"최종 폴드교차검증 점수 : {final_k_score}")

5폴드값이 기본값이며 5번 검증한 값에 대한 평균값이 최종 폴드교차검증 점수임

※ cross_validate()은 훈련세트를 섞어 폴드를 나누지않음. 때문에 우리는 앞에서 train_test_split()함수로 전체 데이터를 섞었음.
※ 하지만 교차검증을 할 때 훈련세트를 섞으려면 *분할기*를 사용해야함.
※ 분할기는 교차검증에서 폴드를 어떻게 나눌지결정함.
※ corss_validate은 기본적으로 회귀모델인 경우 KFOLD 분할기 사용, 분류모델일경우 타깃클래스를 골고로 나누기위해 StratifiedKFOLD 사용.

※ 분할기를 사용한 교차검증
※ cross_validate()
※ cv crosvaild는 기본적으로 5개 폴드로 교차검증함
※ 분류모델일때는 StratifiedkFold(), 회귀모델일때는 KFOLD

※ cross_validate 파라미터로는 모델명, 훈련데이터, 훈련타겟데이터, cv인 회귀/분류에 따른 폴드 방식을 지정

from sklearn.model_selection import StratifiedKFold
#cross_validate 파라미터로는 모델명, 훈련데이터, 훈련타겟데이터, cv인 회귀/분류에 따른 폴드 방식을 지정
scores = cross_validate(dt, train_input, train_target, cv=StratifiedKFold())
print(np.mean(scores["test_score"]))

 

 ○ 만약 10-폴드교차검증을 하고자할시

splitter = StratifiedKFold(n_splits=10, shuffle=True, random_state=42)
scores = cross_validate(dt, train_input, train_target, cv=splitter)
print(np.mean(scores["test_score"]))

폴드 회수를 올리니 좀더 정확도점수가 오름

 

 ○ GridSearchCV : 클래스는 친절하게도 하이퍼파라미터 탐색과 교차검증을 한번에 수행함

from sklearn.model_selection import GridSearchCV

params = {"min_impurity_decrease": [0.0001,0.0002,0.0003,0.0004,0.0005]}  #매개변수 지정 

gs = GridSearchCV(DecisionTreeClassifier(random_state=42), params, n_jobs=-1)  #모델객체생성 파라미터, 객체모델의 파라미터, CPU코어개수 사숑에 대한 파라미터
gs.fit(train_input,train_target)

dt = gs.best_estimator_
print(dt.score(train_input,train_target))

print(f"min_impurity_decrease : {gs.best_params_}")

print(f'''5번 교차검증 점수 : {gs.cv_results_["mean_test_score"]}''')
print(f'''최종 교차검증 점수 : {np.mean(gs.cv_results_["mean_test_score"])}''')

디시즌트리 모델의 매개변수인 min_impurity_decrease에 대한 값들이 담긴 리스트를 지정 후 GridSearchCV를 진행하면 알아서 최적의 파라미터를 찾아서 학습해줌.

 

※ 그리드 서치(Grid Search)와 랜덤 서치(Random Search)는 머신 러닝 모델에서 하이퍼파라미터 튜닝을 위해 사용되는 두 가지 주요 기법임.
  ▶ 검색 공간 탐색 방식
    - 그리드 서치: 사전에 지정된 하이퍼파라미터 조합 그리드를 사용하여 탐색합니다. 이 그리드는 사전에 정의된 값들의 조합으로 구성되며, 각 조합에 대해 교차 검증(Cross-validation) 또는 검증 데이터셋을 사용하여 모델을 평가함.
    - 랜덤 서치: 가능한 하이퍼파라미터 공간에서 무작위로 하이퍼파라미터를 선택하여 탐색함. 그리드 서치와 달리 랜덤 서치는 하이퍼파라미터의 값들을 사전에 정의된 그리드로 나열하는 것이 아니라 랜덤하게 선택함.
  ▶ 하이퍼파라미터 탐색 효율성
    - 그리드 서치: 사전에 정의된 그리드에 따라 특정 값들의 조합만을 평가하기 때문에 모든 조합을 검색하기 위해 시간이 많이 소요될 수 있음. 특히 하이퍼파라미터 공간이 크고 가능한 조합이 많을 때 효율성이 낮을 수 있음.
    - 랜덤 서치: 랜덤하게 선택된 하이퍼파라미터 조합을 평가하기 때문에 더 빠르게 하이퍼파라미터 공간을 탐색할 수 있습니다. 이는 특히 하이퍼파라미터 공간이 매우 크거나 중요한 하이퍼파라미터가 복수 개일 때 유용함.

  ▶ 결론 : 모델의 파라메터가 범주형일경우 랜덤서치 적용, 특정 후보 값들을 알고 있다면, 그리드서치 적용

from scipy.stats import uniform, randint
#rgen.rvs(10)는 rgen에서 10개의 난수를 생성. 이는 0부터 9까지의 정수 중에서 무작위로 10개를 선택하여 반환
rgen = randint(0,10)

print(rgen.rvs(10))
print("\n")
print(np.unique(rgen.rvs(1000),return_counts=True))
print("\n")
ugen = uniform(0,1)
print(ugen.rvs(10))

params ={"min_impurity_decrease" : uniform(0.0001,0.001),
         "max_depth": randint(20,50),
         "min_samples_split":randint(2,25),
         "min_samples_leaf":randint(1,25)}

from sklearn.model_selection import RandomizedSearchCV
gs=RandomizedSearchCV(DecisionTreeClassifier(random_state=42),params,
                      n_iter=100,n_jobs=-1,random_state=42)
gs.fit(train_input,train_target)
print(gs.best_params_)
print(np.max(gs.cv_results_["mean_test_score"]))
dt=gs.best_estimator_
print(dt)
print(dt.score(test_input,test_target))

'Python > 머신러닝+딥러닝 Ⅰ' 카테고리의 다른 글

비지도학습 : 군집 알고리즘 기본  (0) 2024.03.26
Ensemble Model  (0) 2024.03.25
Decision Tree(결정트리 알고리즘)  (0) 2024.03.22
확률적경사하강법  (1) 2024.03.22
Logistic_KNN  (0) 2024.03.22