1번 문제
- 2.7장 그리드 서치에서 했던 걸 떠 올리기.
- 이제 서포트 벡터 머신(SVM)이라는 모델을 추가해 보자.
- SVM은 파라미터 중 kernel을 조정하므로써 값을 다르게 할 수 있다.
- kernel의 종류 : linear, rbf 등등
- 다양한 커널을 넣어보고 뭐가 제일 좋은지 보자.
from sklearn.model_selection import GridSearchCV
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]},
]
svm_reg = SVR()
grid_search = GridSearchCV(svm_reg, param_grid, cv=5, scoring='neg_mean_squared_error', verbose=2)
grid_search.fit(housing_prepared, housing_labels)
시간이 상당히 많이 걸린다.
param_grid 속 ‘C’값, gamma값, GridSearchCV 속 cv를 조정해가며 보자.
최상 모델의 점수는 다음과 같다.
negative_mse = grid_search.best_score_
rmse = np.sqrt(-negative_mse)
print("RMSE:", rmse)
RMSE: 70286.61838178603 가 나온다.
하이퍼 파라미터도 확인해보자.
grid_search.best_params_
{'C': 30000.0, 'kernel': 'linear'} ; 즉, 선형커널이 RBF 커널보다 낫다.
2번 문제
- 2.7장의
GridSearchCV를RandomizedSearchCV로 바꿔보자.
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=30, cv=3, scoring='neg_mean_squared_error',
verbose=2, random_state=42)
rnd_search.fit(housing_prepared, housing_labels)
시간이 상당히 많이 걸린다. RandomizedSearchCV의 파라미터 중 n_iter, cv 값을 조정해보자.
최상 모델의 점수는 다음과 같다.
negative_mse = rnd_search.best_score_
rmse = np.sqrt(-negative_mse)
print("RMSE:", rmse)
RMSE: 55312.44715561121가 나온다.
하이퍼 파라미터도 확인해보자.
rnd_search.best_params_
{'C': 157055.10989448498, 'gamma': 0.26497040005002437, 'kernel': 'rbf'} 가 나온다.
보통 랜덤서치가 같은 시간안에 그리드서치보다 더 좋은 하이퍼파라미터를 찾는다.
3번 문제
- 2.5장에서 변환기에 대해 배웠다.
- 가장 중요한 특성을 선택하는 변환기를 준비 파이프라인에 추가해 보자.
from sklearn.base import BaseEstimator, TransformerMixin
def indices_of_top_k(arr, k):
return np.sort(np.argpartition(np.array(arr), -k)[-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_]
선택할 특성의 갯수를 지정하고, 최상의 k개 특성 인덱스를 확인
k = 5
top_k_feature_indices = indices_of_top_k(feature_importances, k)
top_k_feature_indices
array([ 0, 1, 7, 9, 12], dtype=int64)
np.array(attributes)[top_k_feature_indices]
array(['longitude', 'latitude', 'median_income', 'pop_per_hhold', 'INLAND'], dtype='<U18')
맞는지 다시 확인!
sorted(zip(feature_importances, attributes), reverse=True)[:k]
# 결과
[(0.3790092248170967, 'median_income'),
(0.16570630316895876, 'INLAND'),
(0.10703132208204355, 'pop_per_hhold'),
(0.06965425227942929, 'longitude'),
(0.0604213840080722, 'latitude')]
새로운 파이프라인 만들기
preparation_and_feature_selection_pipeline = Pipeline([
('preparation', full_pipeline),
('feature_selection', TopFeatureSelector(feature_importances, k))
])
housing_prepared_top_k_features = preparation_and_feature_selection_pipeline.fit_transform(housing)
샘플의 특성 & 최상의 k개 특성 확인
# 처음 3개 샘플 특성
print(housing_prepared[0:3, top_k_feature_indices])
# 최상의 k개 특성 확인
print(housing_prepared[0:3, top_k_feature_indices])
결과는 다음과 같다.
[[-0.94135046 1.34743822 -0.8936472 0.00622264 1. ]
[ 1.17178212 -1.19243966 1.292168 -0.04081077 0. ]
[ 0.26758118 -0.1259716 -0.52543365 -0.07537122 1. ]]
[[-0.94135046 1.34743822 -0.8936472 0.00622264 1. ]
[ 1.17178212 -1.19243966 1.292168 -0.04081077 0. ]
[ 0.26758118 -0.1259716 -0.52543365 -0.07537122 1. ]]
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)
몇 개의 샘플에 전체 파이프라인 적용.
some_data = housing.iloc[:4]
some_labels = housing_labels.iloc[:4]
print("Predictions:\t", prepare_select_and_predict_pipeline.predict(some_data))
print("Labels:\t\t", list(some_labels))
결과는 다음과 같다. 잘 작동하는 것 같다.
Predictions: [ 83384.49158095 299407.90439234 92272.03345144 150173.16199041]
Labels: [72100.0, 279600.0, 82700.0, 112500.0]
5번 문제
-
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=3,
scoring='neg_mean_squared_error', verbose=2)
grid_search_prep.fit(housing, housing_labels)
- 굉장히 처리 과정이 많으므로 GridSearchCV의 cv 값을 조정하자. 기본적으로 48 candidate이기 때문에 잘 계산해야 한다.
- ISLAND 특성은 데이터 값이 1개라 중간중간 오류가 나오겠지만, 잘못된 것이 아니므로 계속 실행! 중간중간 다음과 같은 문구가 나오면 성공이다.
[CV] END feature_selection__k=2, preparation__num__imputer__strategy=mean; total t...
최상의 Imputer 정책을 찾아보자.
grid_search_prep.best_params_
{'feature_selection__k': 1, 'preparation__num__imputer__strategy': 'mean'}
most_frequent가 제일 중요하고, 거의 모든 특성이 유효하다.
단, 마지막 ISLAND 특성은 제외!