교차검증 Cross Validation
데이터를 분할하여 모델 생성 및 적용에 번갈아 가면서 일반화하는 모델검증 평가방법(모든 데이터셋을 검증에 1번씩 사용한다.)
1. K-Fold cross validation
자료를 k 개로 분류하고 k-1개를 훈련데이터, 1개를 평가데이터로 구분하여 모델생성과정을 k번 검증한다.
K-Fold() 는 데이터셋을 순서대로 일정한 간격으로 분할하기 때문에 분류 분석일 경우 종속변수의 데이터 분포가 치우칠 수 있다 (위에서 부터 순차적으로 끊기 때문이다) -> shuffle = True 로 지정하여 임의 추출로 해결할 수 있지만, 한쪽의 비율이 더 많을수도 있다는 단점 존재.
주로 회귀분석에서 사용한다.
2. Stratified K-Fold cross validation
원본데이터의 전체 종속 변수 분포 비율을 학습 및 검증 데이터셋에 반영하여 분할한다. 즉 각각의 분포 비율이 1:1 이라면 학습데이터와 검증데이터의 종속변수 분포도 각 1:1 을 따르게 된다. (균등하게 분할해준다.)
주로 분류분석에서 사용한다.
3. cross_val_score(), cross_val_validate()
클래스를 쓰지 않고 모형에따라 알아서 검증을 수행한다.
회귀분석 = KFold, 분류분석 = Stratified K-Fold
[실습]
패키지 로딩
import numpy as np
import pandas as pd
from sklearn.datasets import load_iris
from sklearn.model_selection import KFold, StratifiedKFold, train_test_split, cross_val_score, cross_validate
from sklearn.tree import DecisionTreeClassifier # 분류모형
from sklearn.metrics import accuracy_score # 평가지표
>> None Cross Validation
# 데이터의 한 부분을 가지고 교차검증
iris = load_iris()
x_train,x_test,y_train, y_test = train_test_split(iris.data, iris.target, # 독립변수(data), 종속변수(target)
test_size= 0.3, random_state= 10)
model = DecisionTreeClassifier(random_state = 1) # 의사결정나무 = 데이터를 하나 가져와서 분리함 'random_state' : seed값 고정
model.fit(x_train,y_train) # 학습
y_hat = model.predict(x_test) # 예측
# 정확도 (평가지표)
print(f'정확도: {accuracy_score(y_test, y_hat):.2f}') # 100개 중 98개를 정확히 분류시킨다.
정확도: 0.98
>> K-Fold Cross Validation
데이터 형태 확인하기
print(iris.data.shape)
print(iris.target) # 종속변수의 값만
# 0 품종 50개, 1품종 50개, .. 1:1:1
(150, 4)
[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 2
2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
2 2]
k_fold = KFold(n_splits= 5) # 교차검증을 위해 데이터를 분할해주는 클래스
# k_fold = KFold(n_splits= 5, shuffle= True) # 임의로 섞어서 가져옴, 데이터셋이 같은 분포로 들어갔을지는 알 수 없다.
# n_splits: 분할 개수
# 전체 5개 중 학습:4, 평가:1
x = iris.data
y = iris.target
k = 0 # 교차검증의 횟수를 저장할 변수 (반복문통해 어떻게 분할해서 가져오는지 체크)
cv_acc = [] # 교차검증마다 정확도를 저장할 변수
model = DecisionTreeClassifier(random_state= 1)
for train_idx, test_idx in k_fold.split(x): # split 으로 데이터를 5등분, 분할된 데이터의 인덱스값만 반환함
k += 1
print(f'{k}번째 검증 데이터 셋')
print('Train:', train_idx) # 학습데이터에 인덱스 값
print('Test:', test_idx)
x_train, x_test = x[train_idx], x[test_idx] # 값만 인덱싱해오는 것을 x_train / x_test 에 넣음
y_train, y_test = y[train_idx], y[test_idx]
model.fit(x_train,y_train)
y_hat = model.predict(x_test)
acc = accuracy_score(y_test,y_hat) # 리스트에 저장시키기 위함
print(f'{k}번째 교차검증 정확도: {acc:.2f}')
cv_acc.append(acc) # 평균정확도 구하기 위함
print()
print(f'평균정확도: {np.mean(cv_acc):.2f}')
1번째 검증 데이터 셋
Train: [ 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119
120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
138 139 140 141 142 143 144 145 146 147 148 149]
Test: [ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
24 25 26 27 28 29]
1번째 교차검증 정확도: 1.00
앞에서부터 교차 검증을 진행한다. 평균정확도가 꽤 떨어진 것을 확인할 수 있다.
평균정확도: 0.91
K-fold Cross Validation = 과적합 (편향된 데이터를 가지고 결과를 도출했을 것이다.)
-> 위에서 부터 순차적으로 끊었기 때문이다.
>> Stratified K-Fold Cross Validation
stf_kfold = StratifiedKFold(n_splits= 5) # 교차검증을 위해 데이터를 분할해주는 클래스
# n_splits: 분할 개수
# 전체 5개 중 학습:4, 평가:1
x = iris.data
y = iris.target
k = 0 # 교차검증의 횟수를 저장할 변수 (반복문통해 어떻게 분할해서 가져오는지 체크)
cv_acc = [] # 교차검증마다 정확도를 저장할 변수
model = DecisionTreeClassifier(random_state= 1)
for train_idx, test_idx in stf_kfold.split(x,y): # 종속변수가 들어가야함, 비율을 알아야 하기때문
k += 1
print(f'{k}번째 검증 데이터 셋')
print('Train:', train_idx) # 학습데이터에 인덱스 값
print('Test:', test_idx)
x_train, x_test = x[train_idx], x[test_idx] # 값만 인덱싱해오는 것을 x_train / x_test 에 넣음
y_train, y_test = y[train_idx], y[test_idx]
model.fit(x_train,y_train)
y_hat = model.predict(x_test)
acc = accuracy_score(y_test,y_hat) # 리스트에 저장시키기 위함
print(f'{k}번째 교차검증 정확도: {acc:.2f}')
cv_acc.append(acc) # 평균정확도 구하기 위함
print()
print(f'평균정확도: {np.mean(cv_acc):.2f}')
# 0,1,2 해당하는 값들을 1: 1: 1 로 균등하게 가져옴
# 별도의 과적합이 없다고 봐도 됨 (일반모델 대신? 사용해도 된다.)
1번째 검증 데이터 셋
Train: [ 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
46 47 48 49 60 61 62 63 64 65 66 67 68 69 70 71 72 73
74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
92 93 94 95 96 97 98 99 110 111 112 113 114 115 116 117 118 119
120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
138 139 140 141 142 143 144 145 146 147 148 149]
Test: [ 0 1 2 3 4 5 6 7 8 9 50 51 52 53 54 55 56 57
58 59 100 101 102 103 104 105 106 107 108 109]
1번째 교차검증 정확도: 0.97
평균정확도: 0.97
평균정확도가 유사한 것을 볼 수 있다.
>> cross_val_score()
estimator : 학습할 모델 객체(회귀모형: KFold, 분류모형: StratifiedKFold 자동적으로 선택)
x : 독립변수 데이터 셋
y : 종속변수 데이터 셋
cv : 교차검증 k 값(default:5), 또는 교차검증 객체
score = cross_val_score(model, x, y)
# 주어진 k 값에 따른 매 교차마다의 정확도 값을 리스트로 반환
# model = DecisionTreeClassifier(random_state= 1) -> 계층화된 교차검증을 알아서 실행해줌
print('score:', score)
print(f'평균 정확도: {np.mean(score):.2f}')
score: [0.96666667 0.96666667 0.9 1. 1. ]
평균 정확도: 0.97
>> cross_validate()
매 검증마다 소요된 학습 시간과 검증 시간을 딕셔너리로 반환(위와 유사하지만 차이는 좀 더 부가적인 정보를 제공)
여러가지 평가지표를 리스트 형태로 전달이 가능하다.
result = cross_validate(model, x, y, cv =5, scoring= ['accuracy', 'precision_macro','roc_auc_ovr']) # scoring : 평가지표값을 문자열로
for key, val in result.items():
print('평가지표:', key)
print(f'평균값: {np.mean(val):.2f}')
print('-' * 30)
평가지표: fit_time
평균값: 0.00
------------------------------
평가지표: score_time
평균값: 0.01
------------------------------
평가지표: test_accuracy
평균값: 0.97
------------------------------
평가지표: test_precision_macro
평균값: 0.97
------------------------------
평가지표: test_roc_auc_ovr
평균값: 0.97
------------------------------
참고용 평가지표
# 참고용
import sklearn
sklearn.metrics.SCORERS.keys() # 평가지표
'국비 교육 > 머신러닝, 딥러닝' 카테고리의 다른 글
[머신러닝] 분류분석 : [이지분류] 로지스틱 회귀분석 - (실습) 유방암 확률 예측, 개인 신용도 기반 대출 가능 여부 예측 (0) | 2023.11.21 |
---|---|
[머신러닝] 지도학습 알고리즘 - 분류분석 : 로지스틱 회귀분석 (0) | 2023.11.20 |
[머신러닝] 회귀분석 - L1, L2규제 ((문제) 보스톤 집값 예측, 대한민국 육군 몸무게 예측) (0) | 2023.11.20 |
[머신러닝] 회귀분석 - 다중공선성, L1 규제 ,L2규제 (0) | 2023.11.20 |