#!/usr/bin/env python3


다양한 교차 검증 방법


1. LOOCVLeave-one-out cross-validation

LOOCV 교차 검증폴드 하나샘플 하나만 들어 있는 k-겹 교차 검증

각 반복에서 하나의 데이터 포인트를 선택해 테스트 세트로 사용

특히 데이터셋이 클 때는 시간이 매우 오래 걸리지만, 작은 데이터셋에서는 좋은 결과를 만들어냄


# library load

from sklearn.datasets import load_iris

from sklearn.linear_model import LogisticRegression

from sklearn.model_selection import LeaveOneOut, cross_val_score, KFold


# dataset

iris = load_iris()


# create object

logreg = LogisticRegression() # model

loo = LeaveOneOut() # LeaveOneOut model


# test validation

# LOOCV

scores_loo = cross_val_score(logreg, iris.data, iris.target, cv=loo) 


# K-fold(5)

kfold = KFold(n_splits=5, random_state=0, shuffle=True)

scores_fold = cross_val_score(logreg, iris.data, iris.target, cv=kfold) # model, train, target, cross validation


# cv result

print('iris.data.shape \n{}'.format(iris.data.shape))

print('cv number of partition \n{}'.format(len(scores_loo)))

print('mean score_loocv \n{:.3f}'.format(scores_loo.mean()))

print('mean score_kfold \n{:.3f}'.format(scores_fold.mean()))


cv result


>> LOOCV가 K-fold보다 성능이 더 좋음을 알 수가 있음



2. shuffle-split cross-validation임의 분할 교차 검증

shuffle-split cross-validation에서는 

train_size만큼의 포인트로 train set를 만들고, test_size만큼(train set와 중첩되지 않는) 포인트로 test set를 만들도록 분할함

이 분할은 n_splits 횟수만큼 반복됨


# load library

import mglearn

import matplotlib.pyplot as plt

import matplotlib


# matplotlib 설정

matplotlib.rc('font', family='AppleGothic') # 한글출력

plt.rcParams['axes.unicode_minus'] = False # 축 -


mglearn.plots.plot_shuffle_split()

plt.show()


10개의 데이터 포인트에 train_size=5, test_size=2와 n_splits=4를 적용한 ShuffleSplit


>> train_size와 test_size에 정수를 입력하면 데이터포인트의 절대 갯수를

실수를 입력하면 전체 데이터에서의 비율을 의미


# iris데이터를 이용하여 shuffle-split cross-validation

# load library

from sklearn.model_selection import ShuffleSplit


# create object

shuffle_split = ShuffleSplit(test_size=0.5, train_size=0.5, n_splits=10) # ShuffleSplit 객체 생성


# cv test

scores = cross_val_score(logreg, iris.data, iris.target, cv=shuffle_split)


# cv test result

print('cv test score \n{}'.format(scores))

cv test score

>> 임의 분할 교차 검증은 반복 횟수를 훈련 세트나 테스트 세트의 크기와 독립적으로 조절해야 할때 유용함

또한 train_size와 test_size의 합을 전체와 다르게 함으로써 전체 데이터의 일부만 사용할 수 있음

이렇게 데이터를 subsampling부분 샘플링방식은 대규모 데이터셋으로 작업할 때 유용함



3. 그룹별 교차 검증

# load library

mglearn.plots.plot_group_kfold()

plt.show()

레이블에 기반한 GroupKFold분할


>> 이 그림에서 볼 수 있듯이 각 분할에서 한 그룹 전체가 훈련 세트 아니면 테스트 세트에 있음

그룹별 교차 검증의 자세한 정보는 아래 링크 참조

http://scikit-learn.org/stable/modules/cross_validation.html


데이터 안에 매우 연관된 그룹이 있을 때도 교차 검증을 널리 사용함

<<얼굴 사진에서 표정을 인식하는 시스템을 만들기 위해 100명의 사진을 모았다고 가정>>

한 사람을 찍은 여러 장의 사진이 각기 다른 표정을 담고 있음 ==>

이 데이터셋에 없는 사람의 표정을 정확히 구분할 수 있는 분류기를 만드는 것이 목표


같은 사람의 사진훈련 세트와 테스트 세트에 모두 나타날 수 있으므로 그룹별 교차겸증을 하는것이 타당


새 얼굴에 대한 일반화 성능을 더 정확하게 평가하려면

훈련 세트와 테스트 세트에 서로 다른 사람의 사진이 들어가도록 해야함


이를 위해 사진의 사람이 누구인지 기록한 배열을 

groups 매개변수로 전달 받을 수 있는 GroupKFold를 사용할 수 있음

groups 배열은 훈련 세트와 테스트 세트를 만들 때 분리되지 않아야 할 그룹을 지정하는 것이라 클래스 레이블과는 다름


데이터에 그룹에 있는 예로는 의료분야가 일반적

여기서는 같은 환자로부터 얻은 여러 샘플을 가지고 새로운 환자에게 일반화하는 것이 목적


비슷하게 음성 인식에서도 데이터셋에 같은 사람의 목소리가 여러 개 녹음되어 있을 수 있으며, 

관심사항은 새로운 사람의 대화를 인식하는 것


# load library

from sklearn.model_selection import GroupKFold

from sklearn.datasets import make_blobs


# datasets

x, y = make_blobs(n_samples=12, random_state=0)

plt.scatter(x[:, 0], x[:, 1], c=y)

plt.xlabel('feature 0')

plt.ylabel('feature 1')

plt.show()


make_blobs로 만든 인위적 데이터

>> 인위적으로 만든 데이터셋에 group 배열로 그룹을 지정하는 방법

데이터셋은 12개의 포인트로 이뤄져 있고 groups는 각 데이터 포인트에 대해 각 포인트가 어떤그룹(ex. 환자)에

속하는지를 나타냄

4개의 그룹을 나타내고 있으며 처음 3개의 샘플을 첫번째 그룹, 다음 4개는 두번째 그룹을 나타내는 식

샘플 데이터를 그룹으로 정렬할 필요는 없음


# create object

gkfold = GroupKFold(n_splits=3) # GroupKFold

groups = [0, 0, 0, 1, 1, 1, 1, 2, 2, 3, 3, 3] # group class


# cv test

scores = cross_val_score(logreg, x, y, groups, cv=gkfold)


# cv test result

print('cv test score \n{}'.format(scores))

cv test score


+ Recent posts