ecsimsw
Cross validation / 교차 검증 / 모델 평가 본문
Cross validation
- 교차 검증. 머신러닝 모델의 타당성을 검증한다.
- 학습용 데이터는 복잡하나, 테스트용 데이터는 간단한 경우, 그 모델의 스코어는 사실보다 높게 평가되고, 반대 상황의 경우 사실보다 낮게 평가되는 문제가 발생한다. 이런 경우를 피하기 위해, 데이터를 k개로 분할하여 각각의 분류 정밀도를 구하고 이를 평균하는 것으로 모델을 평가할 수 있다.
- 예를들어 k=3일 경우, 전체 data set을 3등분하여 setA, setB, setC로 나누고,
score1 = predict(testSet : setA, trainSet : setB, setC)
score2 = predict(testSet : setB, trainSet : setC, setA)
score3 = predict(testSet : setC, trainSet : setA, setB)
으로 각 집단별 스코어를 구하고 이를 평균화하여 평가하는 것이다.
model_selection
- sklearn의 model_selection 라이브러리를 사용하면 cross_val_score() 메소드를 사용하는 것으로 쉽게 평가 가능하다.
import sys
from sklearn import svm, model_selection
clf = svm.SVC()
scoreSet = model_selection.cross_val_score(clf, trainAttribute, trainLabel, cv=k)
Example :: Iris classification / 붓꽃 분류기 / cross validation
: https://archive.ics.uci.edu/ml/datasets/iris의 붓꽃 데이터셋을 이용해 붓꽃 분류 학습을 진행하고 이 학습을 Cross validation으로 평가한다.
- Iris는 꽃받침 길이, 꽃받침 폭, 꽃잎의 길이, 꽃입의 너비에 따라 3가지 종류로 구분할 수 있다. 150개의 Iris 데이터를 받아 이를 학습하고, 그 결과를 직접 구현한 cross validation, sklearn의 cross validation과 비교한다.
- 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' 카테고리의 다른 글
딥러닝, 파이썬, Keras 공부에 참고한 자료 (0) | 2020.02.02 |
---|---|
아나콘다 / 텐서플로우 설치 (2) | 2020.02.01 |
Support Vector Machine / Random Forest / 언어 구분 학습 (0) | 2020.01.29 |
Scikit-learn / SVM (0) | 2020.01.24 |
Crawling / Scraping / 구글 이미지 크롤러 (0) | 2020.01.19 |