데이터셋 나누기와 모델검증

김혜인·2023년 5월 14일

머신러닝

목록 보기
3/11

모델 성능 평가를 위한 데이터셋 분리

데이터셋(Dataset)

  • Train 데이터셋 : 훈련/학습
  • Validation 데이터셋 : 검증
  • Test 데이터셋 : 평가

머신러닝 모델 파라미터 : 성능에 영향을 주는 값, 최적 성능 값 찾아내야함

  • 하이퍼파라미터(Hyper Parameter) : 사람이 직접 설정하는 파라미터 값
  • 파라미터(Parameter) : 학습을 통해 찾는 파라미터 값

Hold Out

  • 데이터 셋을 Train, Validation, Test set으로 나눔
from sklearn.datasets import load_iris   #데이터준비
from sklearn.model_selection import train_test_split  # 데이터셋을 분리 함수
from sklearn.tree import DecisionTreeClassifier  # 모델
from sklearn.metrics import accuracy_score # 평가함수-정확도
  1. 데이터 불러오기
X, y = load_iris(return_X_y=True)
  1. Train/Test set 분리
  • tmp, test분리
X_tmp, X_test, y_tmp, y_test = train_test_split(X, # input
                                                y, # output
                                                test_size = 0.2, #test set의 크기 설정, 0~1 실수: 비율, 정수: 개수, 기본값:0.25
                                                stratify=y, #분류문제일 경우 필수. 원본의 class별 비율을 유지하면서 나눠지도록 처리
                                                random_state = 0 #random seed값 설정
                                               )
  1. Train/Validation/Test set 분리
  • tmp를 train/validation으로 분리
X_train, X_val, y_train, y_val = train_test_split(X_tmp, y_tmp, test_size=0.2, stratify=y_tmp, random_state=0)
  1. 모델학습
# max_depth > Decision Tree의 하이퍼파라미터
max_depth = 2

# 1. 모델 생성
tree = DecisionTreeClassifier(max_depth=max_depth, random_state=0) 

# 2. train set으로 모델 학습 -> 파라미터 찾는 작업
tree.fit(X_train, y_train) 

#3. 검증 -> 추론, 평가. 검증: ,trainset, validation set 두 개를 가지고 한다.
pred_train = tree.predict(X_train)
pred_val = tree.predict(X_val)

train_acc = accuracy_score(y_train, pred_train)
val_acc = accuracy_score(y_val, pred_val)
  1. Testset으로 최종검증
ed_test = tree.predict(X_test)
test_acc = accuracy_score(y_test, pred_test)

Hold out 방식 단점 : 데이터가 적으면 문제 생길 수 있음

K-겹 교차검증(K-Fold Cross Validation)

  • 데이터 셋을 K개로 나눔
  • K개 중 하나로 훈련, 검증 > 모델 학습, 평가 : K번 반복 >> 성능평가
  • 데이터 양이 불충분할 때 사용
  • 종류
    - KFold > 회귀문제의 Dataset을 분리할 때 사용
    - StratifiedKFold > 분류문제의 Dataset을 분리할 때 사용

예제 -Boston housing

불러오기

import pandas as pd
boston = pd.read_csv('data/boston_hosing.csv')

# feature(X), label(y)를 분리
X = boston.drop(columns = 'MEDV').values
y = boston['MEDV'].values

KFold

  • K개로 분할
  • 회귀
  • KFold(n_splits=K) >몇개의 Fold로 나눌지 지정
  • KFold객체.split(데이터셋) > 데이터셋을 지정한 K개 나눴을때 train/test set에 포함될 데이터의 index들을 반환하는 generator 생성
from sklearn.model_selection import KFold

kf = KFold(n_splits=3)  > 데이터 3개로 
gen = kf.split(X)

v1 = next(gen) 
v2 = next(gen) 

#두번째 iteration의 train/validation set 조회
X_train, y_train = X[v2[0]],y[v2[0]]
X_val, y_val = X[v2[1]],y[v2[1]]
################### KFold를 이용해 Boston housing dataset 교차검증
from sklearn.model_selection import KFold > 데이터셋분리
from sklearn.tree import DecisionTreeRegressor > 모델
from sklearn.metrics import mean_squared_error > 평가 : #평균제곱오차
import numpy as np


#각 iteration별 검증 결과를 담을 리스트 - mean_squared_error
mse_list = []

#1. KFold 객체 생성 - 폴드개수(K)를 설정
kfold = KFold(n_splits=5)

#2. split을 이용해서 generator 생성
index_gen = kfold.split(X)

#3. 반복문 -> 각 folder 별 iteration을 처리
tree = DecisionTreeRegressor(random_state = 0)

for train_index, val_index in index_gen:
    #train/val dataset을 생성
    X_train, y_train = X[train_index], y[train_index]
    X_val, y_val = X[val_index], y[val_index]
    
    #모델 학습
    tree.fit(X_train, y_train)
    
    #검증
    ## 추론
    pred_val = tree.predict(X_val)

    ## 검증
    mse = mean_squared_error(y_val, pred_val) #평가함수 매개변수 (정답, 모델의 추정값)
    mse_list.append(mse)

np.mean(mse_list), np.sqrt(np.mean(mse_list))

StratifiedKFold

  • 분류
  • class별 개수 비율과 동일한 비율로 fold 나눔
  • 종류
    - StratifiedKFold(n_splits=K) > 몇개의 Fold로 나눌지 지정
    - StratifiedKFold객체.split(X, y) > 데이터셋을 지정한 K개 나눴을때 train/test set에 포함될 데이터의 index들을 반환하는 generator 생성 / input(X)와 output(y) dataset을 전달한다.

불러오기

from sklearn.datasets import load_iris
from sklearn.model_selection import StratifiedKFold
from sklearn.tree import DecisionTreeClassifier
from sklearn.metrics import accuracy_score

X,y = load_iris(return_X_y = True)
################ iris dataset 교차 검증
# 폴더 개수 지정
s_kfold =StratifiedKFold(n_splits=4)
#index 제공 generator 생성
index_gen_iris = s_kfold.split(X,y)

#iteration 별 정확도를 저장할 리스트
acc_list = []

tree_clf = DecisionTreeClassifier(random_state=0)

for train_idx, val_idx in index_gen_iris:
    X_train, y_train = X[train_idx], y[train_idx]
    X_val, y_val = X[val_idx], y[val_idx]
    
    tree_clf.fit(X_train, y_train)
    
    pred = tree_clf.predict(X_val)

    acc = accuracy_score(y_val, pred)
    acc_list.append(acc)

np.mean(acc_list)       

Cross Validation Utility 함수

cross_val_score()

  • 데이터셋 K개 나눔 > 반복 > 평가
  • cross_val_score()은 한개의 평가지표
  • estimator: 모델객체
  • X: feature
  • y: label
  • scoring: 평가지표
  • cv: 나눌 개수 (K)
    - 정수: 개수
    - KFold 타입 객체
  • 반환값: array - 각 반복마다의 평가점수
#보스톤데이터셋 - 회귀
df = pd.read_csv('data/boston_hosing.csv')
X_boston = df.drop(columns = 'MEDV')
y_boston = df['MEDV'].values

from sklearn.model_selection import cross_val_score

result_boston = cross_val_score(DecisionTreeRegressor(random_state=0, max_depth=3), # 대상 모델
                                X= X_boston,
                                y=y_boston,
                                scoring='neg_mean_squared_error', #평가 지표
                                cv=4, #폴더 개수 cv=KFold(4)  >> regressor는 kfold
                                n_jobs=-1 #학습+검증 ==> 병렬처리 사용할 cpu 프로세서의 개수 -1: 다사용
                               )
print(result_boston)
print(-result_boston) > 등수세려고 -붙임
#iris-분류
X_iris, y_iris = load_iris(return_X_y=True)

result_iris = cross_val_score(DecisionTreeClassifier(max_depth=3, random_state=0),
                              X=X_iris,
                              y=y_iris,
                              scoring='accuracy',
                              cv=4,  #cv=StratifiedKFold(4) >> clssifier는 strarifiedKFold
                              n_jobs=-1
                             )
result_iris

mse를 제외하고 모든 평가지표는 클수록 좋음

cross_validate()

  • cross_validate()는 여러개 평가지표
  • estimator: 모델객체
  • X: feature
  • y: label
  • scoring: 평가지표 > 여러개는 list나 tuple로 묶어 전달
  • cv: 나눌 개수 (K)
    - 정수: 개수
    - KFold 타입 객체
  • 반환값: dictionary
from sklearn.model_selection import cross_validate()

#여러 평가지표를 확인
result= cross_validate(DecisionTreeRegressor(random_state=0, max_depth=3),
                       X=X_boston,
                       y=y_boston, 
                       scoring=['r2', 'neg_mean_squared_error'],
                       cv = 4,
                       n_jobs = -1)
result['test_score']

0개의 댓글