도찐개찐

[머신러닝] 03. 훈련과 테스트 데이터 본문

PYTHON/데이터분석

[머신러닝] 03. 훈련과 테스트 데이터

도개진 2023. 1. 3. 09:31

훈련과 테스트 데이터

  • 머신러닝 모델을 만들기 위해서 데이터집합이 필요
  • 과적합을 방지하기 위해 데이터를 훈련/테스트 데이터로 나누고
  • 교차검증 방식으로 모델을 만들어 성능을 평가함
  • 훈련데이터 : 모델 추정및 학습이 목적
  • 테스트데이터 : 모델 성능 평가가 목적
  • 분할 비율은 7:3 또는 8:2로 설정
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import sklearn

train/test 분할 없이 분석하는 경우

from sklearn.datasets import load_iris
from sklearn.tree import DecisionTreeClassifier
from sklearn.metrics import accuracy_score
# 데이터 불러오기
iris = load_iris()
data = iris.data
target = iris.target
# 의사결정 나무로 모델 학습
dtclf = DecisionTreeClassifier()

# 분류모델 학습 시킴
# fit(독립변수, 종속변수)
dtclf.fit(data, target)
DecisionTreeClassifier()
In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
# 학습된 모델의 성능을 알아보기 (평가)
# predict(독립변수)
pred = dtclf.predict(data)

# 학습 된 모델로 예측한 결과를 실제값과 비교해 봄
# accuracy_score(실제값, 예측값)
accuracy_score(target, pred)

# 학습에 사용된 데이터 와 평가에 사용 된 데이터를 동일한 데이터로 사용한 경우 제대로 된 평가가 어려움
1.0

과적합overfit 발생

  • 훈련데이터가 가지고 있는 특성을 너무 많이 반영해서
    훈련데이터의 패턴을 너무 잘 인식하게 되는 문제
  • 이런 경우 새로운 데이터가 주어지면 정확하게 예측하는 능력은 떨어짐
    • 비유) A문제집으로 시험공부했는데,
    • 시험문제가 A문제집에서 거의 다나옴 => 100점 맞음!
  • 이런문제를 피할려면 데이터셋을
    훈련/테스트로 나눠 학습과 평가를 수행해야 함

데이터를 학습/평가용으로 분할 1

  • 학습/평가용 데이터 비율은 7:3으로 설정
  • iris 데이터의 총 갯수는 150개이므로
  • 105:45로 분할하면 됨
splitCnt = int(len(iris.data) * 0.7)
train_data = iris.data[:splitCnt,]
test_data = iris.data[splitCnt:,]
train_target = iris.target[:splitCnt,]
test_target = iris.target[splitCnt:,]
train_target.shape, test_target.shape
((105,), (45,))
# 모델 학습 후 평가
dtcf = DecisionTreeClassifier(random_state=2211161135)
dtclf.fit(train_data, train_target)
pred = dtclf.predict(test_data)

accuracy_score(test_target, pred)
0.7777777777777778

데이터 분할 분포 확인

# 0단원 에서 50개 학습
# 1단원 에서 50개 학습
# 2단원 에서 5개만 학습
pd.Series(train_target).value_counts()
0    50
1    50
2     5
dtype: int64
# 2단원에서만 45개 문제가 나옴
pd.Series(test_target).value_counts()

# 데이터를 앞에서 순서대로 나눴기 때문에
# 데이터 분포가 일정하지 않음

# 즉, setosa, verginica, versicolor의 비율이
# 같아야 하는데, train에는 setosa, verginica위주로
# test에는 versicolor위주로 데이터가 분할됨

# 따라서, setosa, verginica들은 잘 구분하지만
# versicolor는 잘 예측하지 못하는 경우 발생함
2    45
dtype: int64

데이터를 학습용/평가용 데이터로 분할 2

  • 독립변수의 속성들의 분포를 고려한 표본추출 필요
    • => sklearn의 train_test_split 함수를 사용
  • train_test_split(독립변수, 종속변수, 훈련데이터크기,
          평가데이터크기, 계층추출여부(분류용), 난수시드값)
from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = train_test_split(iris.data, iris.target, train_size = 0.7,
                stratify=iris.target, random_state=2211161135)
pd.Series(y_test).value_counts()
0    15
2    15
1    15
dtype: int64
# 모델 학습 후 평가
dtcf = DecisionTreeClassifier(random_state=2211161135)
dtclf.fit(X_train, y_train)
pred = dtclf.predict(X_test)

accuracy_score(y_test, pred)

# dtclf.fit(train_data, train_target)
# pred = dtclf.predict(test_data)

# accuracy_score(test_target, pred)
0.9777777777777777

데이터를 학습용/평가용 데이터로 분할 3

  • 데이터수가 작은 경우 데이터의 일부인 평가 데이터도 작음
    • => 성능 평가의 신뢰도 의심
  • 데이터를 동일한 크기로 k개 나누고 이들 중 훈련/평가데이터를 구분지어
  • 순환적으로 훈련 및 평가를 k번 실시함
  • K fold 교차검증이라 함
  • cross_val_score(분류기, feature, target, 평가지표, 검증횟수)
from sklearn.model_selection import cross_val_score
dtclf = DecisionTreeClassifier(random_state=2211161155)
scores = cross_val_score(dtclf, iris.data, iris.target, scoring='accuracy', cv = 10)
scores
array([1.        , 0.93333333, 1.        , 0.93333333, 0.93333333,
       0.86666667, 0.93333333, 1.        , 1.        , 1.        ])
np.mean(scores)
0.96
print(iris.data[:5])
# print(iris.target[:5])
[[5.1 3.5 1.4 0.2]
 [4.9 3.  1.4 0.2]
 [4.7 3.2 1.3 0.2]
 [4.6 3.1 1.5 0.2]
 [5.  3.6 1.4 0.2]]
[0 0 0 0 0]
728x90
Comments