• 카테고리

    질문 & 답변
  • 세부 분야

    딥러닝 · 머신러닝

  • 해결 여부

    해결됨

4.4 random forest부분, GridSearchCV 질문

22.12.21 17:25 작성 조회수 632

1

안녕하세요. 강의 잘 듣고 있습니다. 감사합니다.

 

강의 내용을 실습하던 중 궁금한 점이 생겨 질문 남깁니다.

 

4.4 랜덤포레스트를 실습하던 중, 그리드서치CV가 어떻게 작동하는지 궁금하여 여러번 실험해보다가, 답을 찾지 못해 교수님께 여쭙습니다.

 

제가 생각한 것은 이렇습니다.

 

먼저 데이터셋을 나눈 뒤,

random forest classifier를 하나 생성하여 f1스코어를 측정합니다.

(처음엔 accuracy로 했었는데 같은 결과였고, f1스코어를 선호하여 바꾸었습니다)

 

그후 GridSearchCV의 성능향상정도를 측정하기 위해

random forest classifier를 동일한 random_state로 생성하여,

max_depth, min_samples_split, min_samples_leaf 3가지 그리드 파라미터를 설정하여

GridSearchCV를 수행했습니다.

 

이후 같은 X_test셋으로 predict하여 f1스코어를 측정하였는데,

baseline이 되는 첫번째 랜덤포레스트 클래시파이어보다 성능이 떨어지는 경우가 생겼습니다.

 

샘플셋도 같고, 그리드파라미터 설정도 baseline estimator의 파라미터를 포함하여 설정했는데,

GridSearchCV() 어떻게 작동하길래 더 f1스코어가 더 낮게 파라미터를 선택하는 것일까요?

 

제가 놓치고 있는 부분이 있을 것 같은데, 무엇인지 알려주시면 정말정말 감사드리겠습니다.

 

코드와 실행결과를 첨부합니다.

(10번정도 돌린다고 하면, 6번정도는 두 f1스코어가 같고, 3번정도는 GridSearchCV의 best_estimator_가 더 높았으며, 1번정도는 첫번째 GridSearchCV를 적용하지 않은 랜덤포레스트가 더 높았습니다. 이 마지막 경우가 생기는 원인이 궁금합니다.)

 

from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import f1_score
from sklearn.model_selection import GridSearchCV
import random
import pandas as pd

# 위스콘신 유방암 데이터 로드, train_test_split으로 데이터 나누기
cancer = load_breast_cancer()
X_train, X_test, y_train, y_test = train_test_split(cancer.data, cancer.target, test_size=0.2)

# 대조군과 변수를 통일시키기 위해 같은 난수 이용
rs = random.randrange(1,50)

# 기본설정 랜덤포레스트 돌려보기. 디폴트 n_estimators=100
rf = RandomForestClassifier(n_jobs=-1, random_state=rs) # 모든 코어 사용
rf.fit(X_train, y_train)
pred = rf.predict(X_test)
f1 = f1_score(y_test, pred)
print('랜덤 포레스트 f1스코어: {0:.4f}'.format(f1))
print('\trf max_depth:', rf.get_params()['max_depth'])
print('\trf min_samples_split:', rf.get_params()['min_samples_split'])
print('\trf min_samples_leaf:', rf.get_params()['min_samples_leaf'])
print('\trf random_state:', rf.get_params()['random_state'], '\n')

# 그리드서치 적용해보기
# 비교를 위해 디폴트값인 None, 2, 1을 모두 포함했다.
params = {
    'max_depth': [None, 4,9,16],
    'min_samples_split':[2,6,12],
    'min_samples_leaf':[1,4,8]
}

# 같은 random_state로 RF 랜덤포레스트 재생성
rf = RandomForestClassifier(n_jobs=-1, random_state=rs)
grid = GridSearchCV(rf, param_grid = params, n_jobs=-1, scoring='f1')
grid.fit(X_train, y_train)

# refit된 rf에 테스트데이터를 돌려보기
pred = grid.best_estimator_.predict(X_test)
f1 = f1_score(y_test, pred)

print('GridSearchCV 후 refit된 RF f1스코어: {0:.4f}'.format(f1))

print('\tgrid max_depth:', grid.best_params_['max_depth'])
print('\tgrid min_samples_split:', grid.best_params_['min_samples_split'])
print('\tgrid min_samples_leaf:', grid.best_params_['min_samples_leaf'])
print('\trf random_state:', rf.get_params()['random_state'])

화면 캡처 2022-12-21 171445.png

답변 1

답변을 작성해보세요.

0

안녕하십니까,

좋은 질문 이군요.

일반적으로 이런 경우는 아래 2가지 경우일 경우 발생할 수도 있습니다.

  1. GridSearchCV에 나열한 하이퍼 파라미터가 충분하지 않을 때

  2. 학습, 검증, 테스트 데이터 세트가 모두 작을 경우

트리 기반 모델은 하이퍼 파라미터 튜닝이 그렇게 쉽지는 않습니다. 랜덤 포레스트는 하이퍼 파라미터 개수가 다른 모델 보다는 적지만, 개별 하이퍼 파라미터 값의 범위가 넓을 수도 있습니다.

더구나 데이터 세트가 작을 경우, 학습 모델 생성, 검증, 테스트 시마다 결과가 균일하지 못하고 변동성이 커질 수 있습니다.

예를 들어 지정된 하이퍼 파라미터 max_depth가 Null (즉 depth의 제한이 없는)인 경우가 GridSearchCV로 찾아낸 하이퍼 파라미터 보다 더 성능이 뛰어났습니다.

일반적으로 작은 학습 데이터를 다시 학습과 검증 데이터로 쪼갠 뒤에 더 작아진 학습 데이터와 검증 데이터로 모델 학습 및 성능 검증을 하게 되면 이처럼 GridSearchCV의 결과가 예상과 다른 결과가 도출 될 수 있습니다.

100% 장담은 어렵지만, 데이터 크기가 어느정도 수준 이상만 유지되면 질문해 주신 내용과 같은 결과는 잘 발생하지 않을 것 같습니다.

 

감사합니다.