머신러닝

교차검증

2020. 7. 28. 11:11

데이터를 검증하는 방법

  • 모델의 타당성을 검증하는 크로스 밸리데이션

교차 검증 - Cross-validation

  • 모델의 타당성을 검증하는 방법 중 하나

  • 특정 데이터를 훈련 전용데이터와 테스트 전용 데이터로 분할

  • 훈련데이터로 학습하고 테스트 데이터로 학습의 타당성 검증하는 방법

K 분할 교차 검증 : K-fold cross validation

3-fold cross validation

  • 집합 X 를 3개로 분할 : A, B, C

  • A:테스트, (B,C):훈련 => 정밀도 s1

  • B:테스트, (A,C):훈련 => 정밀도 s2

  • C:테스트, (A,B):훈련 => 정밀도 s3

  • s1, s2, s3의 평균을 구해 최종적인 분류 정밀도 구하기

붓꽃 데이터 데이터 검증해보기

scikit-learn 이용

  • model_selection.cross_val_score() 사용

import pandas as pd
from sklearn import svm, metrics, model_selection
import random, re
# 붓꽃의 CSV 데이터 읽어 들이기 --- (1)
csv = pd.read_csv('pyml_rev_examples/ch4/iris.csv')
csv.head()
  SepalLength SepalWidth PetalLength PetalWidth Name
0 5.1 3.5 1.4 0.2 Iris-setosa
1 4.9 3.0 1.4 0.2 Iris-setosa
2 4.7 3.2 1.3 0.2 Iris-setosa
3 4.6 3.1 1.5 0.2 Iris-setosa
4 5.0 3.6 1.4 0.2 Iris-setosa
# 리스트를 훈련 전용 데이터와 테스트 전용 데이터로 분할하기 --- (2)
data = csv[["SepalLength","SepalWidth","PetalLength","PetalWidth"]]
label = csv["Name"]
# 크로스 밸리데이션 하기 --- (3)
clf = svm.SVC()

# cv : 몇개로 분할 할지
scores = model_selection.cross_val_score(clf, data, label, cv=5)
# cv번의 정답률 평균이므로 더욱 신뢰성 있는 값 도출 가능
print("각각의 정답률 =", scores)
print("평균 정답률 =", scores.mean())
각각의 정답률 = [0.96666667 0.96666667 0.96666667 0.93333333 1.        ]
평균 정답률 = 0.9666666666666666
type(scores)
numpy.ndarray

참고 - 파이썬으로 구현

from sklearn import svm, metrics
import random, re
# 붓꽃의 CSV 파일 읽어 들이기 --- (※1)
lines = open('iris.csv', 'r', encoding='utf-8').read().split("\n")
f_tonum = lambda n : float(n) if re.match(r'^[0-9\.]+$', n) else n
f_cols  = lambda li: list(map(f_tonum,li.strip().split(',')))
csv = list(map(f_cols, lines))
del csv[0] # 헤더 제거하기
random.shuffle(csv) # 데이터 섞기
# 데이터를 K개로 분할하기 --- (※2)
K = 5 
csvk = [ [] for i in range(K) ]
for i in range(len(csv)):
    csvk[i % K].append(csv[i])
# 리스트를 훈련 전용 데이터와 테스트 전용 데이터로 분할하는 함수
def split_data_label(rows):
    data = []; label = []
    for row in rows:
        data.append(row[0:4])
        label.append(row[4])
    return (data, label)
# 정답률 구하기 --- (※3)
def calc_score(test, train):
    test_f, test_l = split_data_label(test)
    train_f, train_l = split_data_label(train)
    # 학습시키고 정답률 구하기
    clf = svm.SVC()
    clf.fit(train_f, train_l)
    pre = clf.predict(test_f)
    return metrics.accuracy_score(test_l, pre)
# K개로 분할해서 정답률 구하기 --- (※4)
score_list = []
for testc in csvk:
    # testc 이외의 데이터를 훈련 전용 데이터로 사용하기
    trainc = []
    for i in csvk:
        if i != testc: trainc += i
    sc = calc_score(testc, trainc)
    score_list.append(sc)
print("각각의 정답률 =", score_list)
print("평균 정답률 =", sum(score_list) / len(score_list))

그리드 서치

  • scikit-learn의 학습기 알고리즘은 여러 가지 선택 가능

  • 각 알고리즘은 여러 개의 매개변수를 지정 가능

  • 적절한 매개변수를 지정하면 정밀도가 높아짐

  • 매개변수 튜닝이 굉장히 중요한 작업

  • 매개변수 자동으로 조사 -> 그리드 서치

  • GridSerachCV() 제공

import pandas as pd
from sklearn import model_selection, svm, metrics
#from sklearn.grid_search import GridSearchCV => error
from sklearn.model_selection import GridSearchCV
# MNIST 학습 데이터 읽어 들이기 --- (1)
train_csv = pd.read_csv('./mnist/train.csv')
test_csv = pd.read_csv('./mnist/t10k.csv')
# 필요한 열 추출하기 --- (2)
train_label = train_csv.iloc[:, 0]
train_data = train_csv.iloc[:, 1:577]
test_label = test_csv.iloc[:, 0]
test_data = test_csv.iloc[:, 1:577]
print("학습 데이터의 수 =", len(train_label))
학습 데이터의 수 = 1000
# 그리드 서치 매개변수 후보 설정 --- (3)
# 매개변수 참고 : https://wikidocs.net/26271
params = [
    {"C": [1,10,100,1000], "kernel":["linear"]},
    {"C": [1,10,100,1000], "kernel":["rbf"], "gamma":[0.001, 0.0001]}
]
# # 그리드 서치 수행 --- (※4)
# n_jobs=-1 병렬 계산할 프로세스 수 지정, -1 자동으로 코어수에 맞게 처리
# 시간이 꽤 걸림
clf = GridSearchCV(svm.SVC(), params, n_jobs=-1)
clf.fit(train_data, train_label)
print("학습기 =", clf.best_estimator_)
학습기 = SVC(C=1, kernel='linear')
# 테스트 데이터 확인하기 --- (5)
pre = clf.predict(test_data)
ac_score = metrics.accuracy_score(pre, test_label)
print("정답률 =",ac_score)
정답률 = 0.866

매개변수 참고 : https://wikidocs.net/26271