머신러닝

머신 러닝(with Google Colab) - 5일차(2)

aisw7984 2024. 10. 18. 11:34
반응형

교차검증과 그리드 서치

이전까지 우리가 머신러닝에 학습을 위해 데이터를 훈련과 테스트 세트로 나눠서 훈련을 하고 테스트를 확인해 보았다. 하지만 테스트 세트로 일반화 성능을 올바르게 확인하기 위해서는 테스트 세트를 최종적으로 모델을 만들고 나서 한 번만 확인해야 할 것이다. 그렇다면 테스트 세트를 대체할 새로운 세트가 필요하다. 가장 간단한 방법은 훈련세트를 나눠서 사용하는 것이다 이런 세트를 검사 세트라고 한다.

우선 데이터를 훈련,테스트 까지 나누어 보자


import pandas as pd
wine = pd.read_csv('https://bit.ly/wine_csv_data')
data = wine[['alcohol','sugar','pH']].to_numpy()
target = wine['class'].to_numpy()

#훈련 테스트 세트
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)

여기까지가 이전까지 해오던 것인데 여기서 훈련세트를 한 번 더 나누어 주면 검사세트를 만들 수 있다.

#훈련세트에서 -> 검증세트 나누기
sub_input, val_input, sub_target, val_target = train_test_split(train_input, train_target, test_size =0.2, random_state=42)
# 테스트세트 ,훈련세트와 검증세트 확인
print(train_input.shape, test_input.shape)
print(sub_input.shape, val_input.shape)
-> (5197, 3) (1300, 3)
   (4157, 3) (1040, 3)

훈련세트가 잘 나누어진것을 볼 수 있다. 이제 검사세트로 정확도를 확인해 보자

#모델 평가
from sklearn.tree import DecisionTreeClassifier
dt = DecisionTreeClassifier(random_state=42)
dt.fit(sub_input, sub_target)
print(dt.score(sub_input, sub_target))
print(dt.score(val_input, val_target))
-> 0.9971133028626413
   0.864423076923077

결과가 잘 줄력됬지만 이 모델이 과대적합이 되었으므로 매개변수를 바꿔 좋은 모델을 찾아야 한다.


교차검증

앞서 훈련세트를 나눠 검사세트를 만들었는데 이렇게 되면 문제가 훈련세트가 너무 작아져서 학습이 잘되지 않을 수 있다. 이럴 때 교차 검증을 이용하면 안정적인 훈련을 할 수 있다. 교차검증은 훈련세트에서 검증 세트를 떼어 여러 번 학습시킴으로써 훈련의 효과를 높인다. 이때 검증세트는 훈련세트 내에서 검사세트를 따로 나누지 않아도 사이킷런에 포함된 cross_validat() 함수에서 자동으로 검증세트의 크기만큼 추출해서 훈련에 사용한다. 코드를 살펴보자

from sklearn.model_selection import cross_validate
scores = cross_validate(dt, train_input, train_target)
print(scores)

교차검증은 K-폴드를 앞에 붙이는데 이는 몇 번을 겹쳐 검증했는지를 말한다 기본적으로는 5 폴드 교차검증이다.

{'fit_time': array([0.02935529, 0.03942084, 0.03544116, 0.0191133 , 0.02794933]),
'score_time': array([0.00270844, 0.00207043, 0.01895332, 0.00274873, 0.01134157]), 
'test_score': array([0.86923077, 0.84615385, 0.87680462, 0.84889317, 0.83541867])}

아래와 같이 딕셔너리 형태로 5개의 값을 가지는 것을 볼 수 있다. 이제 검증의 점수를 평균내서 확인해 보자.

import numpy as np
print(np.mean(scores['test_score']))
-> 0.855300214703487

cross_validat() 함수는 자동으로 검증 세트를 나누어 줄 뿐 훈련세트를 섞어 폴드를 하진 않는다 이때 필요한 것이 분할기이다. 분할기는 교차 검증에서 폴드를 어떻게 나눌 것인지를 결정해 주는데. cross_validat() 함수는 기본적으로 회귀 모델의 경우 KFold 분할기분류 모델의 경우 StratifiedKFold를 사용한다.

from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import cross_validate
from sklearn.model_selection import StratifiedKFold
#트리 객체 생성
dt = DecisionTreeClassifier(random_state=42)
# 데이터를 섞어줌(데이터 전처리)
# n_splits 는 몇번의 폴드 교차 검증할지
splitter = StratifiedKFold(n_splits=8, shuffle=True, random_state=42)
scores = cross_validate(dt, train_input, train_target, cv=splitter)
import numpy as np
print(np.mean(scores['test_score']))
-> 0.8589569752281616

 교차 검증은 위와 같은 방식으로 사용할 수 있고 결정 트리를 이용해서 가장 좋은 성능의 모델을 찾아보자


하이퍼파라미터 튜닝

앞서도 언급했듯이 모델이 학습을 할수 없어 사용자가 지정해야 되는 파라미터를 하이퍼 파라미터라고 했고 

그 과정을 하이퍼파라미터 튜닝이라고 부른다. 사이킷런에서 제공하는 GridSearchCV 클래스는 이러한 하이퍼파라미터 탐색과 교차검증을 한번 해 수행시켜 주는 역할을 한다. 아래에서 알아가 보자

import pandas as pd
wine = pd.read_csv('https://bit.ly/wine_csv_data')
data = wine[['alcohol','sugar','pH']].to_numpy()
target = wine['class'].to_numpy()

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)

from sklearn.model_selection import GridSearchCV
params = {'min_impurity_decrease' : [0.0001, 0.0002, 0.0003, 0.0004, 0.0005]} 
dt = DecisionTreeClassifier(random_state=42)
gs = GridSearchCV(dt, params, n_jobs= -1)
#GridSearchCV의 객체의 안에는 n_jobs 가있는데 이는 병렬 실행에 사용할 코어수를 지정하는거
#기본값은 1인데 -1로하면 알아서 설정하라는 의미
gs.fit(train_input, train_target)

파라미터는 사용자가 입력해 줘야 한다. 따라서 구하고자 하는 파라미터의 정보를 딕셔너리 형태로 저장해서 넣어주면 되는데 여러 개의 파라미터 정보를 넣어도 된다. 추가로 n_jobs는 동작에 사용할 코어수를 말하는데 -1로 설정해 주면 알아서 계산해 준다.

GridSearchCV는 객체 안에서 최적의 경우의 수를 알려주는 기능도 한다.

best_model = gs.best_estimator_
print(best_model.score(train_input, train_target))
print(gs.best_params_)
#교차검증 결과
gs.cv_results_['mean_test_score']
->
0.8672310948624207
{'max_depth': 5}
array([0.81393555, 0.84125583, 0.85337806, 0.85780355, 0.8558801 ])

 

반응형