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() 사용
In [1]:
import pandas as pd
from sklearn import svm, metrics, model_selection
import random, re
C:\Users\205\.conda\envs\pydata\lib\importlib\_bootstrap.py:219: RuntimeWarning: numpy.ufunc size changed, may indicate binary incompatibility. Expected 192 from C header, got 216 from PyObject
  return f(*args, **kwds)
C:\Users\205\.conda\envs\pydata\lib\importlib\_bootstrap.py:219: RuntimeWarning: numpy.ufunc size changed, may indicate binary incompatibility. Expected 192 from C header, got 216 from PyObject
  return f(*args, **kwds)
In [2]:
# 1. 붓꽃의 CSV 데이터 읽어들이기
csv = pd.read_csv('pyml_rev_examples_20191204/ch4/iris.csv')
csv.head()
Out[2]:
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
In [3]:
# 2. 리스트를 훈련 전용 데이터와 테스트 전용 데이터로 분할
data = csv[["SepalLength","SepalWidth","PetalLength","PetalWidth"]]
label = csv["Name"]
In [4]:
# 3. Cross Validiation
clf = svm.SVC()

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

참고) 파이썬으로 구현

In [ ]:
from sklearn import svm, metrics
import random, re

# 1. 붓꽃의 CSV 파일 읽어들이기
lines = open('pyml_rev_examples_20191204/ch4/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)

# 2. 데이터를 K개로 분할
K = 5
csvk = [ [] for i in range(K) ]

for i in range(len(csv)):
    csvk[i % K].append(csv[i])
    
# 3. 리스트를 훈련 전용 데이터와 테스트 전용 데이터로 분할하는 함수 생성
def split_data_label(rows):
    data = []
    label = []
    
    for row in rows:
        data.append(row[0:4])
        label.append(row[4])
    
    return (data, label)

# 4. 정답률 구하는 함수 생성
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, test_l)
    pre = clf.predict(test_f)
    
    return metrics.accuracy_score(test_l, pre)

# 5. K개로 분할해서 정답률 구하기
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() 제공
In [17]:
import pandas as pd
from sklearn import model_selection, svm, metrics
#from sklearn.grid_search import GridSearchCV => error
from sklearn.model_selection import GridSearchCV
In [18]:
# 1.MNIST 학습 데이터 읽어들이기
train_csv = pd.read_csv('MNIST/train.csv')
test_csv = pd.read_csv('MNIST/t10k.csv')
In [19]:
# 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
In [20]:
# 3. 그리드 서치 매개변수 후보 설정
params = [
    {'C': [1,10,100,1000], 'kernel':['linear']},
    {'C': [1,10,100,1000], 'kernel':['rbf'], 'gamma':[0.001, 0.0001]}
]
In [21]:
# 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')
In [22]:
# 5. 테스트 데이터 확인하기
pre = clf.predict(test_data)
ac_score = metrics.accuracy_score(pre, test_label)
print('정답률 = ', ac_score)
정답률 =  0.866