본문 바로가기
Artificial Intelligence/Machine Learning

Hands-On Machine Learning(핸즈온 머신러닝) - 2장 연습문제

by EunjiBest 2022. 7. 17.

Hands-On Machine Learning(핸즈온 머신러닝) - 2장 연습문제

 

 

이 장에서 소개한 주택 가격 데이터셋을 사용해 문제를 푸세요.

 

 

 

1번

 

서포트 벡터 머신 회귀(sklearn.svm.SVR)를 kernel=“linear”(하이퍼파라미터 C를 바꿔가며)나 kernel=“rbf”(하이퍼파라미터 
C와 gamma를 바꿔가며) 등의 다양한 하이퍼파라미터 설정으로 시도해보세요. 지금은 이 하이퍼파라미터가 무엇을 의미하는지 너무 신경 쓰지 마세요. 최상의 SVR모델은 무엇인가요?

 

SVM(서포트 백터 머신)은 선형, 비선형, 회귀, 이상치 분석 등 다양하게 사용할 수 있는 매우 강력한 머신러닝 모델이다.

내가 알기로는 딥러닝이 사용되기 전까지는 SVM모델을 사용했다고 들었다.

 

SVM의 회귀를 SVR이라고 부르는데, 이 회귀모델의 하이퍼 파라미터를 조합하여 최상의 모델을 고르는 것이 이 문제의 목표이다.

 

사이킷런의 GridSearchCV를 사용하면 최적화된 하이퍼파라미터의 조합을 탐색할 수 있다.

가능한 모든 하이퍼파라미터 조합에 대해서 교차 검증을 사용해 평가를 해준다.

 

from sklearn.model_selection import GridSearchCV
from sklearn.svm import LinearSVR

 

위 코드로 GridSearchCV, SVR을 import 시켜준다.

 

param_grid = [
        {'kernel': ['linear'], 'C': [10., 30., 100., 300., 1000., 3000., 10000., 30000.0]},
        {'kernel': ['rbf'], 'C': [1.0, 3.0, 10., 30., 100., 300., 1000.0],
         'gamma': [0.01, 0.03, 0.1, 0.3, 1.0, 3.0]},
    ]

 

문제에 제시된대로, kernel=“linear”와 kernel=“rbf”의 파라미터를 측정하는 코드를 작성해보았다.

 

svm_reg = LinearSVR()
grid_search = GridSearchCV(svm_reg, param_grid, cv=5, scoring='neg_mean_squared_error', verbose=2)
grid_search.fit(housing_prepared, housing_labels)

 

책 115페이지 하단을 참고하면서, 위 코드를 작성해주고 실행을 시켜보았다.

구글 Colab pro기준으로 

 

grid_search.best_params_

 

최고의 파라미터를 출력시켜주면 {'C': 30000.0, 'kernel': 'linear'}

하이퍼 파라미터가 가장 최대값이 선택되었다. 그리고 선형 커널이 RBF 커널보다 성능이 나은 것으로 보여진다. 

 

만약 더 좋은 결과값을 얻고 싶다면 30000.0보다 더 큰 하이퍼파라미터를 조정하면 되겠다.

 

 

 

2번

 

GridSearchCV를 RandomizedSearchCV로 바꿔보세요.

 

1번의 GridSearchCV 즉, 그리드 탐색 방법은 비교적 적은 수의 조합을 탐색할 때에 좋다.

하지만 하이퍼파라미터 탐색 공간이 커진다면 RandomizedSearchCV(랜덤탐색)방법을 사용하는 것이 더 좋다.

랜덤 탐색은 모든 조합을 시도하는 대신, 각 반복마다 하이퍼파라미터에 임의의 수를 대입해서 지정한 횟수만큼 평가한다.

따라서 하이퍼파라미터 탐색에 투입될 컴퓨팅 자원을 제어할 수 있다. (책 118P)

 

다음 코드는, 책에 나와있지 않기때문에 정답을 참고했다.

 

from sklearn.model_selection import RandomizedSearchCV
from scipy.stats import expon, reciprocal


param_distribs = {
        'kernel': ['linear', 'rbf'],
        'C': reciprocal(20, 200000),
        'gamma': expon(scale=1.0),
    }

svm_reg = SVR()
rnd_search = RandomizedSearchCV(svm_reg, param_distributions=param_distribs,
                                n_iter=50, cv=5, scoring='neg_mean_squared_error',
                                verbose=2, random_state=42)
rnd_search.fit(housing_prepared, housing_labels)
rnd_search.best_params_

 

best_params_를 찍었을 때, 

{'C': 157055.10989448498, 'gamma': 0.26497040005002437, 'kernel': 'rbf'} 이런 출력이 나온다.

 

이번에는 rbf에 대해서 최적값을 찾았다.

보통 랜덤서치가 같은시간 안에 더 좋은 하이퍼파라미터를 가진다고한다.

 

왜냐하면

 

>>> negative_mse = grid_search.best_score_
>>> rmse = np.sqrt(-negative_mse)
>>> rmse

70286.61835383571


>>> negative_mse = rnd_search.best_score_
>>> rmse = np.sqrt(-negative_mse)
>>> rmse

54751.69009488048

 

rmse로 오차를 보았을 때, 랜덤서치가 더 낮은 오차확률을 내었기 때문이다.

 

 

 

3번

 

가장 중요한 특성을 선택하는 변환기를 준비 파이프라인에 추가해보세요.

 

특별한 정제 작업이나, 어떤 특성들을 조합 할 때에 나만의 변환기를 만들어야 할 수 있다.

사이킷런에서는 duck typing을 지원하기 때문에 fit, transform(), fit_transform을 이용해서 파이썬 클래스를 만들면 된다.

(책105p)

 

from sklearn.base import BaseEstimator, TransformerMixin

 

먼저 BaseEstimator와 TransformerMixin을 가져온다.

위 함수를 하이퍼라파미터 튜닝에 필요한 get_params()와 set_params()를 얻을 수 있다.

 

def indices_of_top_k(arr, k):
    return np.sort(np.argpartition(np.array(arr), -k)[-k:])

 

위 함수는 리스트(arr) 순서와 상관없이 큰 값 k개를 뽑아서 오른쪽에 놓아 정렬하겠다는 함수이다.

 

class TopFeatureSelector(BaseEstimator, TransformerMixin):
    def __init__(self, feature_importances, k):
        self.feature_importances = feature_importances
        self.k = k
    def fit(self, X, y=None):
        self.feature_indices_ = indices_of_top_k(self.feature_importances, self.k)
        return self
    def transform(self, X):
        return X[:, self.feature_indices_]

 

앞서 import시킨 TransformerMixin과 BaseEstimater를 상속하고,

 책 106페이지를 참고해서 파이썬 클래스로 변환기를 다음과 같이 만들어준다.

 

 

preparation_and_feature_selection_pipeline = Pipeline([
    ('preparation', full_pipeline),
    ('feature_selection', TopFeatureSelector(feature_importances, k))
])

 

만든 변환기를 기존 파이프라인에 추가해주면 완성.

 

 

 

 

4번

 

전체 데이터 준비 과정과 최종 예측을 하나의 파이프라인으로 만들어보세요.

 

prepare_select_and_predict_pipeline = Pipeline([
    ('preparation', full_pipeline),
    ('feature_selection', TopFeatureSelector(feature_importances, k)),
    ('svm_reg', SVR(**rnd_search.best_params_))
])

 

앞에서 만들었던 준비과정, 예측모델을 모두 파이프라인으로 만들었다.

 

prepare_select_and_predict_pipeline.fit(housing, housing_labels)

 

housing과 housing_labels를 fit시켜주면 된다.

 

 

 

 

 

5번

 

GridSearchCV를 사용해 준비 단계의 옵션을 자동으로 탐색해보세요.

 

책 155p에 그리드 탐색을 하는 방법이 나와있다.

준비 단계(1번)에서는 수동으로 최적의 하이퍼파라미터를 직접찾았지만,

GridSearchCV를 이용한다면, 자동으로 찾을 수 있다. 하지만 이 방법은 시간이 많이 들고 비효율적이여서 실무에서 사용하지 않는다고 한다.

 

가장 최적의 하이퍼파라미터를 찾는 것은 전문가의 통찰이 필요한 일이다.

하지만 문제에서 만들어보라고 하니, 코드는 다음과 같다.

 

full_pipeline.named_transformers_["cat"].handle_unknown = 'ignore'

param_grid = [{
    'preparation__num__imputer__strategy': ['mean', 'median', 'most_frequent'],
    'feature_selection__k': list(range(1, len(feature_importances) + 1))
}]

grid_search_prep = GridSearchCV(prepare_select_and_predict_pipeline, param_grid, cv=5,
                                scoring='neg_mean_squared_error', verbose=2)
grid_search_prep.fit(housing, housing_labels)

 

탐색하고자하는 하이퍼파리미터와 시도할 값을 지정하면 ,

가능한 모든 하이퍼파라미터 조함에 대해 교차검증을하여 평가를한다. (시간이 많이 드는 이유)

 

 

 

 

 

 

반응형

댓글