본문 바로가기
Machine Learning

모형 평가 (교차 검증)

by Nowkeeh Ahc

 모형에 따라 적합한 평가 지표를 사용한다고 해도 어떠한 평가 데이터를 사용하느냐에 따라 모형 평가의 객관성이 달라질 수 있다. 모형의 성능을 더 엄격하고, 객관적으로 평가하기 위해 단일 평가 데이터가 아닌 서로 다른 복수 개의 평가 데이터를 사용하여 테스트하는 방법을 교차검증 (Cross Validation)이라고 한다. 

 교차검증은 전체 데이터를 평가용 데이터 세트에 사용할 수 있기 때문에 단일 평가 데이터 분할을 통해 나타날 수 있는 우연한 성능 수준을 회피할 수 있다. 교차검증에는 다양한 방법이 존재하지만, 일반적으로 수치 예측 모형에는 기본 K-겹 교차검증을, 분류 모형에는 층화 K-겹 교차검증을 주로 사용한다. 

 

1) K-겹 교차검증

 K-겹 교차검증 (K-Fold Cross Validation)은 가장 널리 사용되는 교차검증 방법으로서 전체 데이터를 폴드 (Fold)라고 하는 동일한 크기의 부분집합들로 k등분하여 k 모델링을 통해 모형을 평가하는 방법이다. 만약, k를 3으로 한다면 전체 데이터를 3등분하는데, 첫 번째 모형은 ‘폴드 1’을 평가용 데이터 세트로 사용하고 나머지 폴드를 학습용 데이터 세트로 사용한다. 그다음 두 번째 모형은 ‘폴드 2’를 평가용 데이터 세트로 사용하고 나머지 ‘폴드1’과 ‘폴드2’를 학습용 데이터로 사용한다. 이와 같이 k개의 폴드 중 k-1개의 데이터 세트는 학습용 데이터로 사용하고, 나머지 1개의 데이터 세트는 평가용 데이터로 사용하여 모델링을 k번 반복한다. 교차검증 결과, k개의 모형의 성능을 비교하여 가장 우수한 모형을 사용하기도 하고, 전체 성능을 평균하여 사용하기도 한다.

[그림 1] 3-겹 교차검증에서의 데이터 분할

 

 간단한 예제를 통해 K-겹 교차검증을 수행해보자. 교차검증을 수행할 대상 모형은 추후 살펴볼 K-최근접 이웃 모형(K-Nearest Neighbor, K-NN)이며, K-최근접 이웃 모형에 대한 자세한 설명은 추후에 진행하고, 여기에서는 단순히 모델링 결과를 활용하여 교차검증만 수행해보고자 한다. 

K겹 교차검증의 기능은 Scikit-Learn 라이브러리 내 model_selection 모듈의 cross_val_score( )라는 함수에 잘 구현되어 있다. cross_val_score( ) 함수의 인자는 평가하려는 모형, 학습용 데이터, 그리고 폴드의 수이며, 폴드의 수는 cv 인자를 통해 지정한다. cross_val_score( ) 함수가 출력하는 평가지표는 수치 예측 모형일 경우 결정계수를, 분류 모형일 경우 정확도를 출력한다. 만약 다른 지표가 필요하다면 scoring 인자를 이용하여 다른 지표로 바꿀 수 있다.

 내가 분석에 사용할 데이터는 모 커머스 회사의 샘플 데이터로 변수들의 이름은 딱히 신경 안쓰고 메커니즘을 주로 보면 될듯 하다. 

K-최근접 이웃 모형을 만들고, 이를 교차검증으로 평가해보는 코드이다. 

#1. 모듈과 함수 불러오기
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.neighbors import KNeighborsRegressor 
from sklearn.model_selection import cross_val_score

#2. 데이터 불러오기
df = pd.read_csv('data.csv', encoding = 'cp949')

#3. 변수 지정(독립변수/종속변수)
X = df[['a', 'b', 'c']]
Y = df['d']

#4. 데이터 분할(학습용/평가용 데이터 세트)
X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size=0.3, random_state=0)

#5. 모형 생성
model = KNeighborsRegressor()

#6. 5-겹 교차검증 수행
scores = cross_val_score(model, X_train, Y_train, cv=5)
print(‘교차검증 점수:’, scores)

예제의 실행결과 출력은 다음과 같다.

교차검증 점수: [0.65777511 0.71775927 0.61704877 0.64648606 0.77413476]

☞ 본 예제는 수치 예측을 위한 수치 예측 모형이므로 5-겹 교차검증은 5개의 결정계수 값을 출력한다. 5번의 반복 모델링과 테스트 결과 결정계수가 약 0.61~0.77 수준의 성능을 보이는 것으로 나타났다.  

 

2) 층화 K-겹 교차검증

 K-겹 교차검증을 수치 예측 문제에 적용하는 것은 별 문제가 없지만, 만약 분류 문제에 적용할 때에는 문제가 발생할 수 있다. 특정 폴드 내에서는 분류할 클래스(또는 범주)의 비율이 전체 데이터에서의 클래스 비율과 다르게 샘플링될 위험이 크기 때문이다. 이 경우 해당 폴드에서 학습된 모형의 성능은 다른 폴드의 모형과 매우 상이한 성능을 보일 수 있다. 

 분류 문제에서의 이러한 문제를 해결하기 위해 층화 K-겹 교차검증 (Stratified K-Fold Cross Validation)을 사용할 수 있다. 층화 K-겹 교차검증은 앞서 살펴본 K-겹 교차검증 기능에 층화 표본추출 개념을 추가한 방법이라고 할 수 있다. 즉, 각 폴드 내에서의 클래스 비율이 전체 데이터 세트의 클래스 비율과 같도록 데이터를 나누어서 K-겹 교차검증을 실행하는 것이다. 

[그림 2] 층화 3-겹 교차검증에서의 데이터 분할 개념

 Scikit-Learn 라이브러리에서 층화 교차검증은 model_selection 모듈의 StratifiedKFold( ) 함수로 구현되어 있다. 동일한 데이터 세트에서 고객의 이탈여부를 예측하는 분류예측 모형에 대한 층화 K-겹 교차검증을 수행해보자.

#1. 모듈과 함수 불러오기
from sklearn.neighbors import KNeighborsClassifier
from sklearn.model_selection import StratifiedKFold

#2. 변수 지정(독립변수/종속변수) 
X = df[['A', 'B', 'C']]
Y = df['D']

#3. 데이터 분할(학습용/평가용 데이터 세트)
X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size=0.3, random_state=0)

#4. 모형 생성
model= KNeighborsClassifier()

#5. 층화 5-겹 교차검증 수행
skf = StratifiedKFold(n_splits=5, shuffle=True, random_state=0)
scores = cross_val_score(model, X_train, Y_train, cv=skf)
print(‘층화 교차검증 점수:’, scores)

 출력된 결과는 다음과 같다.

층화 교차검증 점수: [0.64285714 0.7 0.67857143 0.67142857 0.70714286]

☞ 출력값이 앞서 진행한 일반 교차검증에서 출력된 값과 유사해 보이지만, 여기에서 나타난 층화 교차검증 결과값은 분류 문제에 적용된 모형의 성능 평가이므로 결정계수가 아니라 모형의 정확도라고 이해하는 것이 바람직하다.


This post was written based on what I read and studied the book below.

http://www.kyobobook.co.kr/product/detailViewKor.laf?mallGb=KOR&ejkGb=KOR&barcode=9791195511747

 

댓글