Introduction
지금까지 validation(검증)(or holdout) data set을 사용하여 model을 quality(품질)을 측정했습니다.
그러나 이같은 접근 방식에는 몇가지 단점이 존재합니다.
예로 5000개의 행(row)가 있는 data set이 있다고 가정해봅시다.
일반적으로 데이터의 약 20%을, 또는 1000개의 행을 validation data set으로 둡니다.
이는 모델의 점수(MAE가 낮은지 확인하기)를 결정할 때 운이 따릅니다.(it leaves some random chance)
즉, 모델이 1000개의 행 중 한 집합에서 잘 수행될 수 있지만 다른 1000개의 행에서는 정확하지 않을 수 있죠.
극단적인 경우를 가정한다면, validation set에 데이터가 오로지 1 row만 있는 것입니다.
대체가능한 모델(alternative model)과 비교하는 경우,
단일 데이터 지점에서 가장 잘 예측하는 모형의 대부분의 운에 따를 수 밖에 없죠.
일반적으로 validation set가 클수록 model quality의 측정값에서
randomness( aka "noise")이 감소하고 신뢰성이 높아집니다.
그런데 말이죠, train data에서 행을 제거해야만 더 큰 대규모의 validation set을 얻을 수 있으므로,
train set가 작다는 것은 더 나쁜 모델을 의미합니다!
진퇴양난이 따로 없습니다.
What is Cross-Validation?
교차 검증에서는 여러 가지 model quality에 대한 측정값을 얻기 위해
데이터의 여러 하위 집합(subsets)에서 모형화 프로세스(modeling process)를 실행합니다.
예를 들어, 전체 data set에서 20% 분리하여 5조각으로 나눈 뒤, 각 조각을 5개의 "fold(배수)"라고 부릅니다.
그 다음엔, 각 fold에 대해 실험을 하는 거죠.
- 첫번째 실험에서, 1st fold를 validation set (or holdout)으로 두고 다른 data는 training data로 둡니다. 이는 20%의 holdout set을 기반한 model quality의 측정값을 돌려주겠죠.
- 두번째 실험에서, 2nd fold부터 hold out 합니다. (당연히 2nd fold 외 data는 model을 train하는데 쓰입니다) 이 holdout set은 이후에 또다른 두번째 model quality 측정값을 내놓겠죠
- 이러한 과정을 반복합니다. 각 fold를 holdout set(validation)으로 두고 실행해보는 거죠. 그럼 전체 데이터가 한번쯤은 holdout set이 될테며, 모든 행을 동시에 사용하지 않지만 모든 행을 기반으로 한 model quality의 측정도를 얻게 됩니다.
When should you use cross-validation?
각 fold 별로 validation set을 정해서 전체 data에 대해 해본다는 건 시간이 오래 걸리는 일이긴 합니다.
그렇다면 언제 사용해야 좋을까요?
컴퓨터에 무리가지 않는 소규모 data set에서는 대단히 좋습니다.
이 때는 굳이 train set과 valid set을 구분하여 그 과정을 추적하지 않고
바로 cross-validation을 사용하는 것이 효율적입니다.
대규모의 data set의 경우, 하나의 validation set으로 충분합니다. 코드는 더 빨리 실행되며, 데이터 용량은 충분하므로 일부 코드를 hold out 해둔 뒤 다시 사용할 필요는 없습니다.
대규모와 소규모를 구분짓는 단순한 임계값은 없습니다.
그러나 model 실행에 몇 분 또는 그 이하로 소요되면 cross-validation으로 전환할 가치가 있습니다.
또는 cross-validation을 실행하여 각 실험의 score가 점수에 근접한지 확인할 수 있습니다.
각 실험에서 동일한 결과를 얻을 경우, 하나의 validation set으로 충분하겠지요?
Example
시작 전에 작업 좀 미리 해두겠습니다.
missing values를 imputer로 채워주는 pipeline을 정의하고 random forest 모델로 예측을 해볼게요.
pipeline 없이 cross-validation이 가는하지만, 그건 좀 어렵습니다!
pipeline을 사용하여 code를 놀랍도록 깔끔하게 만들어봅시다.
from sklearn.pipeline import Pipeline
from sklearn.impute import SimpleImputer
my_pipeline = Pipeline(steps=[('preprocessor', SimpleImputer()),
('model', RandomForestRegressor(n_estimators=50, random_state=0))])
- n_estimators: the number of trees in the forest
cross_val_score()
이 함수는 scikit-learn 모듈 속에 있으며 cross-validation scores를 반환해주는 함수입니다.
- "cv" parameter: fold의 수를 정합니다.
- "scoring" parameter: model quality의 측정해주는 방법(측정 도구)의 이름을 적습니다. 아래 예시는 negative MAE를 선택했습니다.
- negative MAE란 그저 "-1"을 곱해준 것 뿐이예요
from sklearn.model_selection import cross_val_score
# Multiply by -1 since sklearn calculates *negative* MAE
scores = -1 * cross_val_score(my_pipeline, X, y,
cv=5,
scoring='neg_mean_absolute_error')
print("MAE scores:\n", scores)
위와 같이 scores를 print해보면 각 fold 별로 MAE를 산출한 결과를 리스트 형식으로 출력합니다.
negative MAE로 해보니 조금 다르죠? Scikit-learn은 모든 행렬에 대해 정의되어 있으므로 수가 클 수록 좋습니다.
negative MAE는 다른 곳에서 들어본 적은 없을 테지만, 이 대회에서만 일관성을 유지해주네요.
보통 다른 model들과 비교하여 단 하나의 model quality 측정값을 원하죠. 그래서 위의 결과의 평균을 내봤습니다.
print("Average MAE score (across experiments):")
print(scores.mean())
Exercise
Step 1. Write a useful function
- using the data in X and Y to create folds
- SimpleImputer() to replace missing values, and
- RandomForestRegressor() to fit random forest model
from sklearn.model_selection import cross_val_score
from sklearn.ensemble import RandomForestRegressor
from sklearn.pipeline import Pipeline
from sklearn.impute import SimpleImputer
def get_score(n_estimators):
my_pipeline = Pipeline(steps =[('preprocessor',SimpleImputer()),
('model',RandomForestRegressor(n_estimators=n_estimators, random_state=0))])
scores = -1 * cross_val_score(my_pipeline,X,y,
cv=3,
scoring='neg_mean_absolute_error')
return scores.mean()
Step 2. Test different parameter values
get score의 parameter는 n_estimators.
즉, RandomForest model 속 tree의 수이다.
tree의 수에 따라 어떻게 달라지는 result라는 딕셔너리에 저장해보자.
result[i]가 get_score(i)의 평균 MAE값을 담고 있도록.
#Way1
numTrees=[50*i for i in range(1,9)]
results = {numTree : get_score(numTree) for numTree in numTrees}
#Way2
results = {}
for i in range(1,9):
results[50*i] = get_score(50*i)
Step 3. Find the best parameter value
Step2를 시각화해주는 코드입니다. 한 번 써보세요.
import matplotlib.pyplot as plt
%matplotlib inline
plt.plot(list(results.keys()), list(results.values()))
plt.show()
가장 낮은 값을 산출하는 n_estimator가 어디인지 찾아보세요. 그게 바로 best_n_estimators랍니다.
해당 n_estimator로 get_score()를 하면 됩니다!
+) 추가적으로 공부하고 싶다면 "Hyperparameter optimization"에 대해서 알아보세요. "grid search"쪽으로 시작해보시고
'Machine Learning > [Kaggle Course] ML (+ 딥러닝, 컴퓨터비전)' 카테고리의 다른 글
[Kaggle Course] How to prevent "Data Leakage" (0) | 2020.11.01 |
---|---|
[Kaggle Course] XGBoost (gradient boosting) + Ensemble method (0) | 2020.10.24 |
[Kaggle Course] Pipelines + How to make and submit CSV in Kaggle (0) | 2020.10.21 |
[Kaggle Course] Categorical Variables (0) | 2020.10.12 |
[Kaggle Course] Missing Values (0) | 2020.10.11 |