Hands-On Machine Learning(핸즈온 머신러닝) - 2장 연습문제
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)
탐색하고자하는 하이퍼파리미터와 시도할 값을 지정하면 ,
가능한 모든 하이퍼파라미터 조함에 대해 교차검증을하여 평가를한다. (시간이 많이 드는 이유)