학습목표
데이터가 충분하지 않을 경우의 문제를 극복하고자 고안된 검증 방법으로 훈련 세트에서 검증 세트를 떼어 내어 평가하는 과정을 여러번 반복하고 이 점수를 평균하여 최종 검증 점수를 얻어내는 방법
모든 데이터셋을 훈련에 활용할 수 있다.
모든 데이터셋을 평가에 활용할 수 있다.
*hold-out 교차검증
충분한 데이터가 있을때 사용하는 것으로 원시(Raw)데이터를 학습, 검증, 테스트 이렇게 세가지의 데이터 셋으로 나누어 train데이터로 학습하는 방식이다. 그러나 만약 데이터셋 전체가 개수가 크지 않다면, 모델 예측 성능에 대한 추정이 부정확해진다. 즉 홀드아웃 셋을 만들어 내는 것 자체에 대단한 신경을 써야한다
k개의 집합에서 k-1 개의 부분집합을 훈련에 사용하고 나머지 부분집합을 테스트 데이터로 검증하는 것으로 학습 데이터의 일정 부분을 검증 데이터로 쓰되, k번의 검증 과정을 통해 학습 데이터의 모든 데이터를 한 번씩 검증 데이터로 사용해서 k개의 검증 결과를 평균낸 값을 검증 성능 평가 지표로 사용하는 방식
pipe = make_pipeline(
OneHotEncoder(use_cat_names=True),
SimpleImputer(strategy='mean'),
StandardScaler(),
SelectKBest(f_regression, k=20),
Ridge(alpha=1.0)
)
# 3-fold 교차검증을 수행합니다.
k = 3
scores = cross_val_score(pipe, X_train, y_train, cv=k,
scoring='neg_mean_absolute_error')
#일반적으로 scoring을 값이 클 수록 모델 성능이 좋은 것으로 사이킷런에서 인식하는데, mae는 값이 클 수록 모델 성능이 저하되는 것이므로 Negative 키워드를 붙여서 사용
print(f'MAE ({k} folds):', -scores)
#평균&정규화
-scores.mean()
scores.std()
from category_encoders import TargetEncoder
from sklearn.ensemble import RandomForestRegressor
pipe = make_pipeline(
# TargetEncoder: 범주형 변수 인코더로, 타겟값을 특성의 범주별로 평균내어 그 값으로 인코딩
TargetEncoder(min_samples_leaf=1, smoothing=1),
SimpleImputer(strategy='median'),
RandomForestRegressor(max_depth = 10, n_jobs=-1, random_state=2)
)
k = 3
scores = cross_val_score(pipe, X_train, y_train, cv=k,
scoring='neg_mean_absolute_error')
#일반적으로 scoring을 값이 클 수록 모델 성능이 좋은 것으로 사이킷런에서 인식하는데, mae는 값이 클 수록 모델 성능이 저하되는 것이므로 Negative 키워드를 붙여서 사용합니다.
print(f'MAE for {k} folds:', -scores)
-scores.mean()
scores.std()
범주형 변수 인코더로, 타겟값을 특성의 범주별로 평균내어 그 값으로 인코딩한다.
#범주형 데이터만 출력
X_train.describe(exclude='number')
from category_encoders import TargetEncoder
from sklearn.ensemble import RandomForestRegressor
pipe = make_pipeline(
# TargetEncoder: 범주형 변수 인코더로, 타겟값을 특성의 범주별로 평균내어 그 값으로 인코딩
TargetEncoder(min_samples_leaf=1, smoothing=1),
SimpleImputer(strategy='median'),
RandomForestRegressor(max_depth = 10, n_jobs=-1, random_state=2)
)
머신러닝 모델을 만들 때 중요한 이슈는 다음 2가지이며,
이상적인 모델은 과소적합과 과적합 사이에 존재한다.
import matplotlib.pyplot as plt
from category_encoders import OrdinalEncoder
from sklearn.model_selection import validation_curve
from sklearn.tree import DecisionTreeRegressor
pipe = make_pipeline(
OrdinalEncoder(),
SimpleImputer(),
DecisionTreeRegressor()
)
depth = range(1, 30, 2)
ts, vs = validation_curve(
pipe, X_train, y_train
, param_name='decisiontreeregressor__max_depth'
, param_range=depth, scoring='neg_mean_absolute_error'
, cv=3
, n_jobs=-1
)
train_scores_mean = np.mean(-ts, axis=1)
validation_scores_mean = np.mean(-vs, axis=1)
fig, ax = plt.subplots()
# 훈련세트 검증곡선
ax.plot(depth, train_scores_mean, label='training error')
# 검증세트 검증곡선
ax.plot(depth, validation_scores_mean, label='validation error')
# 이상적인 max_depth
ax.vlines(5,0, train_scores_mean.max(), color='blue')
# 그래프 셋팅
ax.set(title='Validation Curve'
, xlabel='Model Complexity(max_depth)', ylabel='MAE')
ax.legend()
fig.dpi = 100
이대로 트리의 깊이를 정해야 한다면 max_depth = 5 부근에서 설정해 주어야 과적합을 막고 일반화 성능을 지킬 수 있다.
현실적으로 사용자가 직접 정해줘야 하는 하이퍼파라미터는 수작업으로 정해주는 것이 어려우므로 사이킷런에 최적의 하이퍼파라미터 조합을 찾아주는 도구를 사용한다.
from sklearn.model_selection import RandomizedSearchCV
from scipy.stats import randint, uniform
pipe = make_pipeline(
TargetEncoder(),
SimpleImputer(),
RandomForestRegressor(random_state=2)
)
dists = {
'targetencoder__smoothing': [2.,20.,50.,60.,100.,500.,1000.], # int로 넣으면 error(bug)
'targetencoder__min_samples_leaf': randint(1, 10),
'simpleimputer__strategy': ['mean', 'median'],
'randomforestregressor__n_estimators': randint(50, 500),
'randomforestregressor__max_depth': [5, 10, 15, 20, None],
'randomforestregressor__max_features': uniform(0, 1) # max_features
}
clf = RandomizedSearchCV(
pipe,
param_distributions=dists,
n_iter=50,
cv=3,
scoring='neg_mean_absolute_error',
verbose=1,
n_jobs=-1
)
#일반적으로 scoring을 값이 클 수록 모델 성능이 좋은 것으로 사이킷런에서 인식하는데, mae는 값이 클 수록 모델 성능이 저하되는 것이므로 Negative 키워드를 붙여서 사용합니다.
clf.fit(X_train, y_train);
print('최적 하이퍼파라미터: ', clf.best_params_)
print('MAE: ', -clf.best_score_)
#각 하이퍼파라미터 조합으로 만들어진 모델들을 순위별로 나열
pd.DataFrame(clf.cv_results_).sort_values(by='rank_test_score').T
#테스트 데이터에 대한 예측 결과
# 만들어진 모델에서 가장 성능이 좋은 모델을 불러옵니다.
pipe = clf.best_estimator_
from sklearn.metrics import mean_absolute_error
y_pred = pipe.predict(X_test)
mae = mean_absolute_error(y_test, y_pred)
print(f'테스트세트 MAE: ${mae:,.0f}')
best_estimator : estimator
Estimator that was chosen by the search, i.e. estimator which gave highest score (or smallest loss if specified) on the left out data. Not available if refit=False. ... See refit parameter for more information ...
=> best_estimator 는 CV가 끝난 후 찾은 best parameter를 사용해 모든 학습데이터(all the training data)를 가지고 자동으로 다시 학습(refit)한 상태
refit : boolean, string, or callable, default=True
Refit an estimator using the best found parameters on the whole dataset.
=> 만약 hold-out 교차검증(훈련/검증/테스트 세트로 한 번만 나누어 실험)을 수행한 경우에는, 반드시 (훈련 + 검증) 데이터셋에서 최적화된 하이퍼파라미터로 최종 모델을 재학습(refit) 해야 합니다.