본문 바로가기
DNN with Keras/Regularization and Dropout

K-Fold Cross-validation

by goatlab 2023. 7. 24.
728x90
반응형
SMALL

K-Fold Cross-validation

 

 

예측 모델링에서 다양한 목적으로 교차 검증을 사용할 수 있다.

 

• 신경망에서 표본 외 예측 생성

• 조기 중단 (early stopping)을 위해 신경망을 훈련시키기 위한 충분한 수의 에포크 추정

• 활성화 함수, 뉴런 수 및 계층 수와 같은 특정 하이퍼 파라미터의 효과 평가

 

교차 검증은 여러 접힘 및 여러 모델을 사용하여 각 데이터 세그먼트가 유효성 검사 및 훈련 세트 역할을 모두 할 수 있는 기회를 제공한다. 새 데이터에 대한 예측을 생성하기 위해 (훈련 세트에 없는) 폴드 모델의 예측은 여러 가지 방법으로 처리할 수 있다.

 

• 검증 점수가 가장 높은 모델을 최종 모델로 선택한다.

• 새 데이터를 5개의 모델 (폴드마다 하나씩)에 미리 설정하고 결과를 평균을 낸다 (이것이 앙상블).

• 전체 데이터 세트에서 교차 검증과 동일한 설정을 사용하여 새 모델을 재훈련한다. 동일한 숨겨진 레이어 구조를 사용하여 최대한 많은 에포크를 훈련한다.

 

일반적으로 마지막 접근 방식을 선호하며 하이퍼 파라미터를 선택하면 전체 데이터 세트에 대한 모델을 재훈련한다.

 

K-Fold Cross-validation : 회귀 vs 분류

 

회귀 분석과 분류는 교차 검증과 관련하여 다소 다르게 처리된다. 회귀 분석은 각 항목의 위치를 거의 고려하지 않고 데이터 집합을 K개의 폴드로 분할할 수 있는 간단한 경우이다. 회귀 분석의 경우 데이터 항목이 가능한 한 랜덤하게 접혀 있어야 한다. 또한 모든 폴더가 동일한 수의 데이터 항목을 가질 필요는 없다. 데이터 세트가 항상 K개의 폴드로 균등하게 분할될 수 있는 것은 아니다. 회귀 교차 검증의 경우 Scikit-Learn 클래스 KFold를 사용한다.

 

분류를 위한 교차 검증은 KFold 개체를 사용할 수도 있지만, 이 기법은 클래스 균형이 원래와 동일하게 각 폴더에서 유지되도록 보장하지는 않는다. 모델이 훈련된 클래스의 균형은 훈련 세트와 동일하거나 유사해야 한다. 이 분포의 드리프트는 훈련된 모델이 실제 사용된 후 모니터링해야 하는 가장 중요한 사항 중 하나이다. 따라서, 교차 검증을 통해 의도하지 않은 이동이 발생하지 않도록 해야 한다. 이 기술은 계층화 샘플링이라고 하며 Scikit-Learn 객체 계층화를 사용하여 수행된다. 분류를 사용할 때마다 KFold 대신 StratifiedKFold를 사용한다. 요약하면 Scikit-Learn에서 다음 두 개체를 사용해야 한다.

 

• KFold는 회귀 문제를 처리할 때 사용한다.

• 계층화된 KFold는 분류 문제를 처리할 때 사용한다.

 

Out-of-Sample Regression Predictions with K-Fold Cross-Validation

 

5배 교차 검증을 수행하여 표본 외 예측을 생성할 수 있다.

 

import pandas as pd
import os
import numpy as np
from sklearn import metrics
from scipy.stats import zscore
from sklearn.model_selection import KFold
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, Activation

EPOCHS = 500
kf = KFold(5 , shuffle = True , random_state = 42)
oos_y = [ ]
oos_pred = [ ]

fold = 0
for train, test in kf.split(x):
  fold += 1
  print(f"Fold #{fold}")

  x_train = x[train]
  y_train = y[train]
  x_test = x[test]
  y_test = y[test]

  model = Sequential()
  model.add(Dense(20, input_dim = x.shape[1], activation = 'relu'))
  model.add(Dense(10, activation = 'relu'))
  model.add(Dense(1))
  model.compile(loss = 'mean_squared_error', optimizer = 'adam')
  model.fit(x_train, y_train, validation_data = (x_test, y_test), verbose= 0, epochs= EPOCHS)
  pred = model.predict(x_test)
  
  oos_y.append(y_test)
  oos_pred.append(pred)
  
  score = np.sqrt(metrics.mean_squared_error(pred, y_test))
  print(f"Fold score (RMSE) : {score}")

oos_y = np.concatenate(oos_y)
oos_pred = np.concatenate(oos_pred)
score = np.sqrt(metrics.mean_squared_error(oos_pred, oos_y))
print(f"Final, out of sample score (RMSE) : {score}")

oos_y = pd.DataFrame(oos_y)
oos_pred = pd.DataFrame(oos_pred)
oosDF = pd.concat([df, oos_y, oos_pred], axis = 1)

oosDF.to_csv(filename_write, index = False)

 

보시다시피, 위의 코드는 또한 필요한 평균 에포크 수를 보고한다. 일반적인 기술은 전체 데이터 세트에서 필요한 평균 에포크 수를 훈련하는 것이다.

728x90
반응형
LIST