Cross-validation(교차검증)
-
일반화 성능을 평가하는데에 트레인/테스트 데이터로 한 번 나누는 것보다 더 안정적이고 뛰어난 통계적 평가 방법
-
교차 검증에서는 데이터를 여러번 반복해서 나누고 여러 모델을 학습함
-
대표적으로 k-fold cross-validation(k-겹 교차검증)
1.1 scikit-learn의 교차검증(KFold)
- model_selection 모듈의 cross_val_score 함수로 구현
from sklearn import datasets
from sklearn.model_selection import cross_val_score
from sklearn.linear_model import LogisticRegression
# 1. load iris
iris = datasets.load_iris()
# 2. create model object
logreg = LogisticRegression()
# 3. cross-validation
scores = cross_val_score(logreg, iris.data, iris.target)
print("cross validation scores : {}".format(scores))
# 결과 : cross validation scores : [0.96078431 0.92156863 0.95833333]
# 3.1 cross-validation: k=5
scores_K5 = cross_val_score(logreg, iris.data, iris.target,cv =5)
print("cross validation scores : {}".format(scores_K5))
# 결과 :cross validation scores : [1. 0.96666667 0.93333333 0.9 1. ]
# 3.1.1 cross-validation: k=5 -> 평균
print("cross validation scores : {:.2f}".format(scores_K5.mean()))
# 결과 : cross validation scores : 0.96
- 3. 과 3.1 은 cv의 값이 다르기 때문에 cv값에 따라 폴드되어 검증하기 때문에 결과가 k=5일 때, scores가 5개가 나오게 된다.
1.2 교차 검증 시 주의 사항
- 단순한 k겹 교차 검증은 데이터가 랜덤하지 않은 경우, 특히 분류 문제에서 클래스 별로 구성된 데이터일 때, 적용에 주의해야 함
-
위와 같은 데이터 형태일 때는 model_selection 모듈 내의 KFold()를 사용하여 기본형 k겹 교차검증을 보완할 수 있다.
* K-Fold : 검증을 하기 위해 데이터를 분리하는데 train, test로 분류하지 않고 train -> train + validation(검증) 으로 나누어서 검증을 할 수 있다. 그렇지만 데이터의 수가 작은 경우에 제대로 할 수 없기 때문에 사용하게 된다.
예를 들어 k=5를 선택한다면,
1) 데이터를 비슷한 크기의 부분집합 5개로 나눔
2) 첫번째 모델은 train : [ 1 2 3 4 ] test : [ 5 ], 두번째 모델은 train : [ 1 2 3 5 ] test : [ 4 ] ....
3) 이와 같이 5개의 정확도 값을 얻게됨
from sklearn.model_selection import KFold
# 1.1 KFold default parameter
kfold = KFold(n_splits=3)
# 1.1.1 socore
print("cross validation score : {}".format(cross_val_score(logreg, iris.data, iris.target, cv = kfold)))
# 결과: cross validation score : [0. 0. 0.]
# 1.2 KFold shuffle
kfold1 = KFold(n_splits=3, shuffle=True, random_state=0)
# 1.2.1 score
print("cross validation score : {}".format(cross_val_score(logreg, iris.data, iris.target, cv = kfold1)))
# 결과 : cross validation score : [0.9 0.96 0.96]
- 1.1 에서 iris 데이터는 품종별로 데이터가 정리되어 있다. 원하는 것이 품종(class) 인데 이것을 n_splits = 3이 되면 클래스가 분리되어 사라지게 되므로 1.1.1의 결과가 0 이 나온다
- 이런 점을 방지하기 위해 shuffle을 해준다.
1.3 임의분할 계층별 교차검증
- 매우 유연한 교차 검증 전략
- train_size / test_size로 데이터 임의 분할(중복 없음)
- 이 분할은 n_split 횟수만큼 반복됨
- 예를 들어, 샘플이 10개인 데이터에서 train_size=6, test_size=2로 설정하면, 2개의 샘플은 사용되지 않음
- 계층별 즉, 클래스의 존재 비율에 따라 추출하여 검증
from sklearn.model_selection import StratifiedShuffleSplit
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
# 1. StratifiedShuffleSplit 이용 (계층 이용)
stratified_shuffle_split = StratifiedShuffleSplit(train_size=0.7, test_size=0.3, n_splits=10, random_state=0)
# 2. 교차검증 점수
# 로지스틱 모델 사용하며, cv : 폴드 수( n_splits = 10 이여서 10이 들어가게 됨)
score = cross_val_score(logreg, iris.data, iris.target, cv=stratified_shuffle_split)
# 3. 점수 확인
print("score : {}".format(score))
# n_splits = 10개여서 10번의 횟수만큼 반복됨
# output : score : [0.97777778 0.91111111 0.95555556 0.91111111 0.95555556 0.93333333 0.97777778 0.95555556 0.97777778 1. ]
# 4. 데이터 확인 방법
X = iris.data
y = iris.target
for train_index, test_index in stratified_shuffle_split.split(X,y):
print("train:",train_index,"\n","test:",test_index)
X_train,X_test = X[train_index],X[test_index]
y_train,y_test = y[train_index],y[test_index]
# 결과는 train과 test가 10개씩 각각 안엔 위에서 정한 train 70%, test 30% 씩 무작위로 섞여있다.
# 5. 교차검증 확인
sss = cross_val_score(logreg, iris.data, iris.target, cv = stratified_shuffle_split)
sss.mean() # 0.9555555555555555
# y_train 데이터 확인
np.bincount(y_train) # 총 카운트 array([35, 35, 35], dtype=int64)
plt.hist(y_train) # 그래프 확인
- 그래프의 결과를 보면 35개씩 세개의 클래스가 동일한 값을 가진 것을 확인할 수 있다. 임의 계층으로 분류할 때 클래스의 비율로 하기 때문에 (iris의 품종 클래스 비율 1 : 1 : 1) 동일한 값이 나오게 된 것이다.
'머신러닝 in Python' 카테고리의 다른 글
[Python] Cross-validation + Grid Search (1) | 2019.08.30 |
---|---|
[Python] Grid Search (0) | 2019.08.30 |
[Python] 분류분석 - SVM(Support Vector Machine) (1) | 2019.08.29 |
[Python] 분류분석 - logistic regression (0) | 2019.08.28 |
[Python] LinearRegression(수치예측) - Lasso (0) | 2019.08.28 |