- 사용자 정의 변환기 생성
from sklearn.base import BaseEstimator, TransformerMixin
rooms_ix, bedrooms_ix, population_ix, households_ix = 3,4,5,6
class CombinedAttributesAdder(BaseEstimator, TransformerMixin):
def __init__(self,add_bedrooms_per_room = True):
self.add_bedrooms_per_room = add_bedrooms_per_room
def fit(self, X, y=None):
return self
def transform(self,X):
rooms_per_household = X[:,rooms_ix] / X[:, households_ix]
population_per_household = X[:, population_ix] / X[:, households_ix]
if self.add_bedrooms_per_room:
bedrooms_per_room = X[:,bedrooms_ix] / X[:,rooms_ix]
return np.c_[X,rooms_per_household, population_per_household, bedrooms_per_room]
else:
return np.c_[X, rooms_per_household, population_per_household]
attr_adder = CombinedAttributesAdder(add_bedrooms_per_room = False)
housing_extra_attribs = attr_adder.transform(housing.values)
이전 포스팅에서 언급했듯이 baseestimator 상속 시, *args 나 **kwargs를 지정하지 않았을 경우 자동으로 하이퍼 파라미터 튜닝에 필요한 두 메서드 get_params()과 set_params()를 추가로 얻게된다.
이러한 사용자 정의 변환기를 생성할 경우 더 많은 하이퍼파라미터 조합을 시행하여 최상의 조합을 찾는 것에 도움을 준다.
특성 스케일링
- 트리 기반 알고리즘을 제외하고 대부분의 머신러닝 알고리즘은 입력 숫자 특성들의 스케일에 민감함. ex) 특성 1 : 6~30000 // 특성 2 : 0~1 이러한 경우 각 특성의 스케일링 필요
- min-max 스케일링 (정규화)
1. normalization, 정규화
2. 0 ~ 1 범위로 스케일링
3. (data-min) / (max-min)
4. 사이킷런의 MinMaxScaler 변환기 (feature_range 매개변수 설정으로 0~1 이외의 값 설정 가능)
- 표준화
1. (data-mean) / 표준편차 --> 분산 1이 되도록
2. 상한과 하한 존재 x --> 민감한 알고리즘에서는 문제 but 이상치에 영향을 덜 받음
3. StandardScaler 변환기
변환 파이프라인
- 연속된 변환을 순서대로 처리할 수 있도록 도와주는 Pipeline 클래스
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
num_pipeline = Pipeline([
#1단계 : 누락값 -> median 대체
('imputer', SimpleImputer(strategy="median")),
#2단계 : 사용자 정의 변환기 활용, 하이퍼파라미터의 조합 도출
('attribs_adder', CombinedAttributesAdder()),
#3단계 : 표준화
('std_scaler', StandardScaler()),
])
housing_num_tr = num_pipeline.fit_transform(housing_num)
- 입력 : 연속된 단계를 나타내는 이름/추정기 쌍의 목록
- 출력 : fit_transform() 메서드 포함
각 열마다 사용자 정의 함수를 적용하여 모든 열을 처리하는 변환기
- 앞서 만든 파이프라인 활용한 ColumnTransformer 클래스
- drop : 열 삭제
- passthrough : 변환 적용 x 그냥 지나감
from sklearn.compose import ColumnTransformer
num_attribs = list(housing_num)
cat_attribs = ["ocean_proximity"]
full_pipeline = ColumnTransformer([
('num', num_pipeline, num_attribs),
#이름, 변환기, 변환기가 적용될 열 이름
('cat', OneHotEncoder(), cat_attribs),
])
housing_prepared = full_pipeline.fit_transform(housing)
모델 선택과 훈련
훈련 세트에서 훈련하고 평가하기
from sklearn.linear_model import LinearRegression
lin_reg = LinearRegression()
lin_reg.fit(housing_prepared, housing_labels)
some_data = housing.iloc[:5]
some_labels = housing_labels.iloc[:5]
some_data_prepared = full_pipeline.transform(some_data)
print("예측 : ", lin_reg.predict(some_data_prepared))
print("예측 : ", list(some_labels))
- 첫 번째 예측은 40% 가까이 벗어남 --> 정확한 예측은 아님
- mean_square_error 함수를 사용해 회귀모델의 RMSE 측정
from sklearn.metrics import mean_squared_error
housing_predictions = lin_reg.predict(housing_prepared)
lin_mse = mean_squared_error(housing_labels, housing_predictions)
lin_rmse = np.sqrt(lin_mse)
lin_rmse
$68,628의 좋지 못한 예측오차 발생 --> 과대적합 or 과소적합 의심
==> 다른 모델 적용, 규제추가 or 완화, 데이터 추가를 활용하여 좋지 못한 점수를 향상시키기
성능 향상을 위한 예시 1. (의사결정 나무를 활용해보자)
- 과소적합 발생 시 : 규제를 완화하거나, 더 좋은 특성을 활용, or 더 강력한 모델 활용
- 위의 예시가 과소적합이라는 가정 하에 더욱 강력한 모델인 결정나무 모델을 활용하여 재시도
from sklearn.tree import DecisionTreeRegressor
tree_reg = DecisionTreeRegressor()
tree_reg.fit(housing_prepared, housing_labels)
housing_predictions = tree_reg.predict(housing_prepared)
tree_mse = mean_squared_error(housing_labels, housing_predictions)
tree_rmse = np.sqrt(tree_mse)
tree_rmse
모델이 데이터에 너무 심하게 '과대적합'되어 0이라는 오차가 발생한 것임.
--> 이러한 과대적합을 방지하기 위해 k-fold 교차 검증 기능을 사용하여 데이터 셋을 나눠보자 (split_train_test보다 우수한 성능)
훈련 데이터를 10개의 폴드로 분리 --> 1~9까지의 폴드를 훈련에, 10번째 폴드를 검증에 --> 2~10까지의 폴드를 훈련에, 1번째 폴드를 검증에, --> 3,4,5,6,7,8,9,10,1 의 폴드를 훈련에, 2번째 폴드를 검증에 ------- 매번 다른 폴드를 선택해 평가에 사용하는 방식!!
from sklearn.model_selection import cross_val_score
scores = cross_val_score(tree_reg, housing_prepared, housing_labels,
scoring = "neg_mean_squared_error", cv=10)
tree_rmse_scores = np.sqrt(-scores)
def display_scores(scores):
print("점수", scores)
print("평균", scores.mean())
print("표준편차", scores.std())
display_scores(tree_rmse_scores)
과대적합 방지
- 1. 모델을 간단히
- 2. 제한(규제)
- 3. 더 많은 훈련 데이터
즉, 이렇게 여러 모델을 선정하여 시도해보고 가장 높은 점수의 모델을 선택한다.
적절한 모델 선정 후, 모델 세부 튜닝
- 그리드 탐색
수동 or 자동으로 하이퍼파라미터를 조정해가며 최적의 조건을 찾는 방법
#랜덤포레스트 모델에 대해 그리드 탐색 적용
from sklearn.model_selection import GridSearchCV
from sklearn.ensemble import RandomForestRegressor
param_grid = [
{'n_estimators' : [3,10,30], 'max_features' : [2,4,6,8]},
{'bootstrap' : [False], 'n_estimators' : [3,10], 'max_features' : [2,3,4]},
]
forest_reg = RandomForestRegressor()
grid_search = GridSearchCV(forest_reg, param_grid, cv=5,
scoring = 'neg_mean_squared_error',
return_train_score = True)
grid_search.fit(housing_prepared, housing_labels)
grid_search.best_estimator_
cvres = grid_search.cv_results_
for mean_score, params in zip(cvres["mean_test_score"], cvres["params"]):
print(np.sqrt(-mean_score), params)
49897 로 이전에 시행하였을 때 발생한 오차보다 낮은 오차를 얻을 수 있다. (해당 파라미터가 최적이라는 의미)
'핸즈온머신러닝&딥러닝' 카테고리의 다른 글
MNIST 활용, 분류 2 (0) | 2021.05.19 |
---|---|
MNIST 활용, 분류 (0) | 2021.05.18 |
캘리포니아 주택 가격 예측 (0) | 2021.05.15 |
RNN과 어텐션을 사용한 자연어 처리 2 (0) | 2021.05.05 |
RNN과 어텐션을 사용한 자연어 처리 1 (0) | 2021.05.02 |