ecsimsw
붓꽃 분류 학습 / cross validation / 교차 검증 / 학습 모델 평가 본문
붓꽃 분류 학습 / cross validation / 교차 검증 / 학습 모델 평가
JinHwan Kim 2020. 1. 30. 10:31Cross validation
https://ecsimsw.tistory.com/entry/Cross-validation
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%
'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 |