728x90
교차 검증 이란?
- 과적합 : 모델이 학습 데이터에마 과도하게 최적화된 현상. 그로인해 일반화된 데이터에서는 예측 성능이 과하게 떨어지는 현상
- 지난번 와인 맛 평가에서 훈련용 데이터의 Acc는 72.94, 테스트용 데이터는 Acc가 71.61%였는데, 누가 이결과가 정말 괜찮은 것인지 묻는다면?
- 나에게 주어진 데이터에 적용한 모델의 성능을 정확히 표현하기 위해서도 유용하다
- train 데이터를 다시 나누어 validation 데이터로 사용함으로써 과적합을 막는 방법
- 검증이 끝나면 다시 train데이터로 학습 한 뒤 test로 마지막 결과를 확인한다
교차 검증 구현하기
Simple Example
import numpy as np
from sklearn.model_selection import KFold
X = np.array([[1, 2], [3, 4], [1, 2], [3, 4]])
y = np.array([1, 2, 3, 4])
kf = KFold(n_splits=2)
print(kf.get_n_splits(X))
print(kf)
for train_idx, test_idx in kf.split(X):
print('-----idx')
print(train_idx, test_idx)
print('-----train data')
print(X[train_idx])
print('-----test data')
print(X[test_idx])
2
KFold(n_splits=2, random_state=None, shuffle=False)
-----idx
[2 3] [0 1]
-----train data
[[1 2]
[3 4]]
-----test data
[[1 2]
[3 4]]
-----idx
[0 1] [2 3]
-----train data
[[1 2]
[3 4]]
-----test data
[[1 2]
[3 4]]
- Kfold는 sklearn에 포함되어 있음.
와인 데이터
와인맛 분류
import pandas as pd
red_wine = pd.read_csv(red_url, sep = ';')
white_wine = pd.read_csv(white_url, sep = ';')
red_wine['color'] = 1
white_wine['color'] = 0
wine = pd.concat([red_wine, white_wine])
데이터 정리
wine['taste'] = [1. if grade > 5 else 0. for grade in wine['quality']]
X = wine.drop(['taste', 'quality'], axis = 1)
y = wine['taste']
의사결정 나무
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier
from sklearn.metrics import accuracy_score
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=13)
wine_tree = DecisionTreeClassifier(max_depth=2, random_state=13)
wine_tree.fit(X_train, y_train)
y_pred_tr = wine_tree.predict(X_train)
y_pred_test = wine_tree.predict(X_test)
print('Train Acc : ', accuracy_score(y_train, y_pred_tr))
print('Test Acc : ', accuracy_score(y_test, y_pred_test))
Train Acc : 0.7294593034442948
Test Acc : 0.7161538461538461
- Kfold를 진행하지 않고 바로 train으로 데이터를 학습 한뒤 결과를 도출해냄
- 데이터를 train_test_split으로 랜덤하게 분리하는게 맞는것인지? 혹은 이것이 최선인건가?
- 또한, 저 acc는 신뢰할수 있는지에 대한 검증이 필요함
KFold
from sklearn.model_selection import KFold
kfold = KFold(n_splits=5)
wine_tree_cv = DecisionTreeClassifier(max_depth=2, random_state=13)
- Kfold를 만들고, 분류기도 다시 생성
- cv = cross validation의 약자
Index 반환
for train_idx, test_idx in kfold.split(X):
print(len(train_idx), len(test_idx))
5197 1300
5197 1300
5198 1299
5198 1299
5198 1299
Fold Acc
cv_accuracy = []
for train_idx, test_idx in kfold.split(X):
X_train, X_test = X.iloc[train_idx], X.iloc[test_idx]
y_train, y_test = y.iloc[train_idx], y.iloc[test_idx]
wine_tree_cv.fit(X_train, y_train)
pred = wine_tree_cv.predict(X_test)
cv_accuracy.append(accuracy_score(y_test, pred))
cv_accuracy
[0.6007692307692307,
0.6884615384615385,
0.7090069284064665,
0.7628945342571208,
0.7867590454195535]
np.mean(cv_accuracy)
0.709578255462782
StratifiedKFold
from sklearn.model_selection import StratifiedKFold
skfold = StratifiedKFold(n_splits= 5)
wine_tree_cv = DecisionTreeClassifier(max_depth=2, random_state=13)
cv_accuracy = []
for train_idx, test_idx in skfold.split(X, y):
X_train, X_test = X.iloc[train_idx], X.iloc[test_idx]
y_train, y_test = y.iloc[train_idx], y.iloc[test_idx]
wine_tree_cv.fit(X_train, y_train)
pred = wine_tree_cv.predict(X_test)
cv_accuracy.append(accuracy_score(y_test, pred))
cv_accuracy
[0.5523076923076923,
0.6884615384615385,
0.7143956889915319,
0.7321016166281755,
0.7567359507313318]
Acc 평균이 안좋음
np.mean(cv_accuracy)
0.6888004974240539
- 인덱스를 반환하기 때문에 for문으로 각각 데이터를 validation하였다.
- 하지만 이렇게 불편하게 코드를 하나하나 짜가면서 해야하는것일까?
2.11 cross validation을 보다 더 간편하게
Cross Validation을 더 간편하게(w. Scikit Learn)
from sklearn.model_selection import cross_val_score
skfold = StratifiedKFold(n_splits=5)
wine_tree_cv = DecisionTreeClassifier(max_depth=2, random_state=13)
cross_val_score(wine_tree_cv, X, y , scoring=None, cv=skfold)
array([0.55230769, 0.68846154, 0.71439569, 0.73210162, 0.75673595])
- 위의 예제처럼 for문 코드를 짜서 돌리는것이 아닌 이미 Sklean에 cross_val_score로 한다
- sklearn에 cross_val_score에 분류기, X, y, Fold객체를 넣어주면된다
- skfold의 n_splits = 5는 데이터를 5개로 나누어 validation한다는 뜻
Depth가 높다고 정확도가 높지 않음
from sklearn.model_selection import cross_val_score
skfold = StratifiedKFold(n_splits=5)
wine_tree_cv = DecisionTreeClassifier(max_depth=5, random_state=13)
cross_val_score(wine_tree_cv, X, y, scoring=None, cv=skfold)
array([0.50076923, 0.62615385, 0.69745958, 0.7582756 , 0.74903772])
- 의사결정 나무의 max_depth를 늘려서 accuracy를 보았으나, 무조건 높아지는것도 아님을 확인
Train Score
from sklearn.model_selection import cross_validate
cross_validate(wine_tree_cv, X, y, scoring=None, cv=skfold, return_train_score= True)
{'fit_time': array([0.01485896, 0.01390481, 0.01378489, 0.01321983, 0.0129869 ]),
'score_time': array([0.00206208, 0.00191903, 0.00187325, 0.00179911, 0.00170922]),
'test_score': array([0.50076923, 0.62615385, 0.69745958, 0.7582756 , 0.74903772]),
'train_score': array([0.78795459, 0.78045026, 0.77568295, 0.76356291, 0.76279338])}
- cross_validate의 return_train_score를 쓰면됨
- train과 test의 격차를 보니 과적합이 있는듯 하다.
728x90
'AI > Machine Learing' 카테고리의 다른 글
PCA, t-SNE, LDA으로 알아보는 차원 축소 (0) | 2024.11.17 |
---|