ecsimsw

붓꽃 분류 학습 / cross validation / 교차 검증 / 학습 모델 평가 본문

붓꽃 분류 학습 / cross validation / 교차 검증 / 학습 모델 평가

JinHwan Kim 2020. 1. 30. 10:31

Cross validation

 

https://ecsimsw.tistory.com/entry/Cross-validation

 

Cross validation

Cross validation - 교차 검증. 머신러닝 모델의 타당성을 검증한다. - 학습용 데이터는 복잡하나, 테스트용 데이터는 간단한 경우, 그 모델의 스코어는 사실보다 높게 평가되고, 반대 상황의 경우 사실보다 낮게..

ecsimsw.tistory.com

Iris classification / 붓꽃 분류기 / cross validation

 

   : Iris는 꽃받침 길이, 꽃받침 폭, 꽃잎의 길이, 꽃입의 너비에 따라 3가지 종류로 구분할 수 있다. 150개의 Iris 데이터를 받아 이를 학습하고, 그 학습 결과를 검증한다.

   

   - https://archive.ics.uci.edu/ml/datasets/iris의 붓꽃 데이터셋을 이용해 붓꽃 분류 학습을 진행하고 이 학습을 Cross validation으로 평가한다.

 

   - 3가지 타입의 모델 평가 정의

 

     actualScore : 전체 데이터 중 1/3 이하의 수를 랜덤하게 뽑아 그 수 만큼의 데이터를 추출하여 test 데이터로, 나머지를 학습 데이터로 하여 학습 후 평가한다. 

 

     cvScore : 전체 데이터를 3등분하여 setA, setB, setC로 분할 후, 한 집단이 테스트 데이터, 나머지 집단이 학습 데이터가 되어 학습 후 평가를 반복한다. 이렇게 나온 3개의 집단별 score을 평균한다.

 

     ms_cvScore : sklearn의 model_selection 라이브러리를 사용하여 전체를 3등분하여 cross validation 한다.

 

Code

 

1. 붓꽃 데이터 로드

import sys
from sklearn import svm, metrics, model_selection
import random

dataSource = "./data_iris/iris.data"

trainData = [] 
trainLabel =[]
trainAttribute =[]

## Move some of data from trainData, and remove them in trainData 

testData = [] 
testLabel =[]
testAttribute =[]

with open(dataSource,mode="r") as f:
    for line in f:
        if line == '\n':
            break
        trainData.append(line.replace('\n','')) 

2. Train set, Test set 분리

# Decide number of test data / move test data from chosen index of trainData

numberOfData = len(trainData)
numberOfTest = random.randint(0,numberOfData/3)

chosenIndex =[]

for i in range(numberOfTest):
    chosenIndex.append(random.randint(0,numberOfData-1))

chosenIndex = list(set(chosenIndex)) # to remove duplicate / The order of items changes
chosenIndex.sort(reverse=True)

for index in chosenIndex:
    testData.append(trainData[index])
    trainData.remove(trainData[index])

   - 전체 데이터안에서 랜덤하게 test set이 결정된다. 단 test set의 크기는 전체의 1/3을 넘지 않도록 한다.

 

   *** list(set(chosenIndex)) : 현재 리스트에서 중복된 인덱스를 제가한다. 순서가 변경된다.

 

3. 로드한 데이터 가공 

# Split attributes and label by ','

def splitDataLabel(dataList, attributeList, labelList):
    for dL in dataList :
        splitedData = dL.split(',')
        attributeList.append(splitedData[0:4])
        labelList.append(splitedData[4])

splitDataLabel(trainData,trainAttribute,trainLabel)
splitDataLabel(testData,testAttribute,testLabel)

4. 학습 및 단순 평가

# Trainning & Report

clf = svm.SVC()
clf.fit(trainAttribute,trainLabel)

pre = clf.predict(testAttribute)
actualScore = metrics.accuracy_score(testLabel,pre)

print("\rActual validation    ")
print("train data : {0}".format(len(trainData)))
print("test data : {0}".format(len(testData)))
print("Actual score : {0}%".format(int(actualScore*100)))

   - 학습 후 미리 지정해둔 test set으로 학습 결과를 평가한다. 이렇게 데이터에서 랜덤하게 뽑은 test set은 문제가 적지만, 현실에서는 상황이 좀 다르다. 갖고 있는 데이터를 train set으로 하여 열심히 학습한 후, 쉽게 레이블을 낼 수 있는 test set으로 검정하는 상황이 많고, 그럼 비교적 쉬운 test로 모델의 성능을 과대 평가할 가능성이 크다.

 

5. train set 분할, 분할 검증 처리

# Cross validation // k-fold cross validation

k=3

selectedIndex =[False for _ in trainData]

setA =[]
setB =[]
setC =[]

def devideSet(set):
    for i in range(int(len(trainData)/k)):
        index = random.randint(0,len(trainData)-1)
        while selectedIndex[index] is True:
            index = random.randint(0,len(trainData)-1)

        selectedIndex[index] = True
        set.append(index)

devideSet(setA)
devideSet(setB)

for i in range(len(selectedIndex)):
    if selectedIndex[i] is True:
        continue
    else:
        setC.append(i)

def crossValidation(test,train1,train2):
    cvTrainAttribute =[]
    cvTrainLabel=[]

    for index in train1:
        cvTrainAttribute.append(trainAttribute[index])
        cvTrainLabel.append(trainLabel[index])

    for index in train2:
        cvTrainAttribute.append(trainAttribute[index])
        cvTrainLabel.append(trainLabel[index])

    clf = svm.SVC()
    clf.fit(cvTrainAttribute,cvTrainLabel)

    cvTestAttribute = []
    cvTestLabel =[]

    for index in test:
        cvTestAttribute.append(trainAttribute[index])
        cvTestLabel.append(trainLabel[index])

    pre = clf.predict(cvTestAttribute)
    score = metrics.accuracy_score(cvTestLabel,pre)
    return score

scoreA = crossValidation(setA,setB,setC)
scoreB = crossValidation(setB,setC,setA)
scoreC = crossValidation(setC,setA,setB)

print("\n\rk-fold cross validation")
print("scoreA : {0}%, train data {1}, test data {2}".format(int(scoreA*100), len(setB)+len(setC), len(setA)))
print("scoreB : {0}%, train data {1}, test data {2}".format(int(scoreB*100), len(setA)+len(setC), len(setB)))
print("scoreC : {0}%, train data {1}, test data {2}".format(int(scoreC*100), len(setB)+len(setA), len(setC)))
print("cvSocre : {0}%".format(int((scoreA+scoreB+scoreC)/k*100)))

   - train set을 3등분하여 각각 test set이 됐을 때의 성능을 찾아 평균낸 값을 cvScore로 한다.

 

   - devideSet()에서는 dataSet을 랜덤하게 각각 n/3개, n/3개, (n/3+n%3)개로 나눈다. 미리 선택된 인덱스를 리스트(selectedIndex)에 넣어 해당 인덱스가 선택되었는지 확인한다.

 

6. scikit-learn의 model_selection 라이브러리 사용으로 교차 검증

# Using scikit-learn model_selection library

clf = svm.SVC()
scoreSet = model_selection.cross_val_score(clf, trainAttribute, trainLabel, cv=3)
print("\n\rUsing model_selection library    ")
print("score set : ",end="")
print(scoreSet)
print("ms_cvScore : {0}%".format(int(sum(scoreSet)/k*100)))

   - 해당 라이브러리를 사용하면, 교차 검증을 쉽게 할 수 있다.

 

   - 총 3개의 모델 평가를 출력하여 비교한다.

 

Result

Actual validation
train data : 110
test data : 40
Actual score : 95%

k-fold cross validation
scoreA : 97%, train data 74, test data 36
scoreB : 97%, train data 74, test data 36
scoreC : 94%, train data 72, test data 38
cvSocre : 96%

Using model_selection library
score set : [0.94594595 0.97297297 0.97222222]
ms_cvScore : 96%

cross validation.txt
0.00MB

'Machine Learning > Tensorflow' 카테고리의 다른 글

BMI 분류 학습 / Keras 연습  (0) 2020.02.06
언어 구분 학습 / Scikit-learn 연습 /SVM  (0) 2020.01.24
Processing devices  (0) 2019.03.19
Tensorflow architecture  (0) 2019.03.18
Placeholder / Variable  (0) 2019.03.17
Comments