[머신러닝] 하이퍼파라미터 튜닝

hyun·2022년 8월 24일

머신러닝

목록 보기
8/10

📚 하이퍼파라미터 튜닝

머신러닝 모델이 학습하는 파라미터를 모델 파라미터라고 한다.
이 때 모델이 학습할 수 없어서 사람이 직접 지정해야 하는 파라미터를 하이퍼파라미터라고 한다.

하이퍼파라미터 : 모델이 자동으로 학습할 수 없어 사용자가 지정해줘야 하는 파라미터

이를 튜닝하는 것은, 먼저 모델이 제공하는 기본값으로 모델을 훈련하고, 검증 세트 점수나 교차 검증을 통해 매개변수를 조금씩 바꿔주는 과정으로 이루어진다.

사람의 도움 없이 자동으로 하이퍼파라미터 튜닝을 하는 기술을 AutoML이라고 한다.

🎣 튜닝 방법

하지만 모델의 적정 파라미터를 찾는 것은 쉬운 일이 아니다.
가령 모델이 여러 하이퍼파라미터를 가지고 있을 때, 각 값은 다른 요인에 의해 영향을 받을 수 있다.
따라서 파라미터를 하나하나 설정해가며 값을 찾아야 한다.
이 때 그리드 서치를 이용해서 모든 모델을 훈련해보는 방법과 랜덤 서치를 이용하는 방법이 있다.

💻 실습

실습은 [혼자 공부하는 머신러닝 + 딥러닝] 에 수록된 예제를 이용했다.
우선 데이터를 가져와 훈련 데이터와 테스트 데이터로 나누자.

import pandas as pd

wine = pd.read_csv("https://bit.ly/wine-date")

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)

그리드 서치 실습

사이킷런의 GridSearchCV 객체를 통해 하이퍼파라미터 그리드 서치를 해볼 수 있다.
얘는 교차검증도 알아서 해준다 !

# 그리드 서치
from sklearn.model_selection import GridSearchCV
# min_impurity_decrease = 노드 분할을 위한 불순도 최소치

# min_impurity_decrease 파라미터는 노드 분할을 위한 불순도 감소 최소량 지정
params = {'min_impurity_decrease' : [0.0001, 0.0002, 0.0003, 0.0004, 0.0005]}

# cv 디폴트는 5, 5폴드 교차검증 진행
# - 따라서 5*5, 25개 모델
# 이 때 n-jobs는 병렬처리에 쓰일 코어의 개수, -1로 하면 전체, 디폴트 1
gs = GridSearchCV(DecisionTreeClassifier(random_state=42), params, n_jobs=-1)

gs.fit(train_input, train_target)

최고 점수를 낸 파라미터는 다음과 같이 볼 수 있다.

# 최적 params는
print(gs.best_params_)

따라서 min_impurity_decrease가 0.0001일 때 성능이 가장 좋다는 것을 확인했다.

랜덤 서치 실습

위에서는 0.0001 단위로 파라미터를 변화시켜봤지만, 값을 줄 기준이 없을 때도 있다.
혹은 변수가 너무 많아 테스트할 모델의 수가 지나치게 많아질 수도 있다.
이럴 때는 랜덤 서치를 통해 학습한다.

여러 개의 파라미터를 한 번 튜닝해보자!
우선 랜덤 난수를 뽑아주는 객체를 만들자.

from scipy.stats import uniform, randint
# 주어진 범위 안에서 고르게 추출하는 라이브러리
# randint는 정수, uniform은 실수
rgen = randint(0, 10)
rgen.rvs(10)

1000개를 한 번 뽑아볼까 ??

np.unique(rgen.rvs(1000), return_counts=True)


0~9까지의 수가 랜덤으로 생성된 것을 볼 수 있다.
이런 식으로 파라미터를 난수로 생성해서 테스트하면 좋을 것 같다~

# 0~1 사이 연속균등분포 생성
ugen = uniform(0, 1)

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)
}

이렇게 범위를 대략적으로만 설정해서 맞춰줬다.
RandomizedSearchCV를 사용해서 한 번 구해보자 !

# 랜덤 서치
from sklearn.model_selection import RandomizedSearchCV
# 샘플링 횟수는 n_iter 매개변수에 주어짐, 100번 샘플링 반복해서 다른 값으로 교차검증
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_)


이렇게 최적 점수를 내는 파라미터를 찾아준다.

서치에 대한 결과는 cvresults 안에 모두 들어 있다.
그 중에서 최대 평균 테스트점수를 출력해보자.

print(np.max(gs.cv_results_['mean_test_score']))

최고 모델은 다음처럼 객체로 받을 수 있따.

dt = gs.best_estimator_
print(dt.score(test_input, test_target))

얘는 학습이 이미 되어있는 객체이다!

0개의 댓글