{{indexmenu_n>6}}
Obsah této stránky bude přístupný od 2. 11. 2017.
====== Cvičení 6 - Výběr a hodnocení modelu ======
Test: https://goo.gl/forms/wqaWAoDsnZsnIXK32
===== Opakování =====
=== Míry pro hodnocení modelů ===
* klasifikační přesnost a realtivní chyba
* specifita a senzitivita
* precision a recall
* F1 score
=== Standardní postup pro validaci modelů ===
* trénovací množina - učení klasifikátoru
* validační množina - optimalizace parametrů klasifikátoru
* testovací množina - konečný výpočet hodnotícího kritéria
* **přeučení (overfitting) vs nedoučení (underfitting)**
=== k-NN klasifikátor ===
* klasifikace podle minima vzdálenosti
* výsledná třída se určuje hlasováním (z toho důvodu je vhodné volit k liché)
* je možné použít různé typy metrik
===== Testování - klasifikátor k-NN =====
Instalace balíčku s funkcí knn()
install.packages("class")
library(class)
Načtení iris dat.
# načtení iris dat
data(iris)
# rychlá explorace dat
dim(iris)
summary(iris)
Rozdělte instance náhodně na trénovací (50%), validační testovací (30%) a testovací (20%) množinu.
# zamíchání dat před rozdělením do množin
set.seed(13579)
shuffle <- sample(nrow(iris), nrow(iris), replace=F)
iris <- iris[shuffle,]
# vytvoření trénovací (50%), validační (30%) and testovací (20%) množiny
trainIris <- iris[1:(0.5*nrow(iris)),]
validIris <- iris[(0.5*nrow(iris) + 1):(0.8*nrow(iris)),]
testIris <- iris[(0.8*nrow(iris) + 1):(nrow(iris)),]
# ověření velikosti množin
dim(trainIris)
dim(validIris)
dim(testIris)
Trénovací, validační a testovací množinu můžeme získat alternativním postupem. Všimněte si, že velikost jednotlivých množin neodpovídá přesně tomu, co jsme požadovali.
# alternativní způsob rozdělení dat
ind = sample(3,nrow(iris),replace=T,prob=c(0.5,0.3,0.2))
# vytvoření trénovací (50%), validační (30%) a testovací (20%) množiny
trainIris <- iris[ind == 1,]
validIris <- iris[ind == 2,]
testIris <- iris[ind == 3,]
# ověření velikosti množin
dim(trainIris)
dim(validIris)
dim(testIris)
Na trénovací množině budeme postupně učit klasifikátor k-NN s //k// = 1,3,5 ... 11,13,15. Budeme si zaznamenávat klasifikační přesnost na validační množině. Následně najdeme největší hodnotu klasifikační úspěšnosti a k ní příslušnou hodnotu parametru //k// a prohlásíme jí za optimální.
# příprava hodnot parametru k
parameter <- seq(from = 1, to = 15, by = 2);
# příprava vektoru pro zaznamenávání hodnot klasifikační úspěšnosti
acc <- vector(length = length(parameter))
for (i in 1:length(parameter)) {
prediction <- knn(trainIris[,-5],validIris[,-5],cl = trainIris[,5],k = parameter[i])
acc[i] <- sum(prediction == validIris[,5])/nrow(validIris)
}
# nalezení nejlepší hodnoty k podle validační množiny
kValidated <- parameter[which.max(acc)]
Jaká hodnota parametru k je optimální pro k-NN klasifikátor na iris datech?
Nakonec vypočteme úspěšnost klasifikátoru na testovacích datech:
# odhad úspěšnosti klasifikace na testovací množině
trainFull <- rbind(trainIris, validIris)
prediction <- knn(trainFull[,-5],testIris[,-5],cl = trainFull[,5],k = kValidated)
testAcc <- sum(prediction == testIris[,5])/nrow(testIris)
Při definici přeučení se obvykle porovnává chyba na trénovací a validační množině. Určete klasifikační přesnost na trénovací množině a porovnejte jí s přesností na validační množině. Jakým způsobem se mění klasifikační přesnost s rostoucím k? Jaká je příčina tohoto chování. Co lze soudit o našem výsledném klasifikátoru? Je klasifikátor přeučený, tak akorát, nebo nedoučený?
===== Testování - 10-ti složková křížová validace - rozhodovací stromy =====
Podobným způsobem jako v předchozím úkolu můžeme využít křížovou validaci. Vyzkoušíme si odhad optimální hodnoty maximální hloubky rozhodovacího stromu. Postup je velmi podobný, pouze v každé iteraci parametru provedeme místo jednoho učení a jednoho výpočtu hodnotícího kritéria celou křížovou validaci, to znamená 10x budeme učit klasifikátor a desetkrát určovat hodnotící kritérium, ukládat ale budeme pouze průměrnou hodnotu ze všech iterací křížové validace.
Křížovou validaci vyzkoušíme na krabích datech, která jsou v R (package MASS)
Potřebné knihovny pro tento příklad
install.packages("MASS")
library(MASS)
library(rpart)
library(rpart.plot)
**10-složková křížová validace**
# načtení krabích dat
library(MASS)
library(rpart)
library(rpart.plot)
data(crabs)
# nastavit generátor náhodných čísel
set.seed(12345)
# vytvoření trénovací množiny (80%), která bude rozdělena na 10 složek, a testovací množiny (20%)
ind <- sample(1:nrow(crabs),0.8*nrow(crabs))
trainCrabs <- crabs[ind,]
testCrabs <- crabs[-ind,]
folds <- rep_len(1:10,nrow(trainCrabs))
# ověření velikostí množin
# training set
dim(trainCrabs)
# folds in training set
table(folds)
# testing set
dim(testCrabs)
# hodnoty parametru maxdepth, které budeme optimalizovat
parameter <- seq(from = 1, to = 10, by = 1);
# inicializace vektorů pro klasifikační přesnosti
accValid <- matrix(NA,nrow=length(parameter),ncol=10)
accTrain <- matrix(NA,nrow=length(parameter),ncol=10)
for (i in 1:length(parameter)){
for(j in 1:10){
train <- trainCrabs[folds!=j,]
valid <- trainCrabs[folds==j,]
tree <- rpart(sp ~ .,data=train,control = rpart.control(minsplit=10,maxdepth=parameter[i]))
accTrain[i,j] <- sum(predict(tree,type='class') == train$sp)/nrow(train)
accValid[i,j] <- sum(predict(tree,newdata=valid,type='class') == valid$sp)/nrow(valid)
}
}
avgAccTrain <- apply(accTrain,1,mean)
avgAccValid <- apply(accValid,1,mean)
# závislost trénovací (zelená) a validační (červená) úspěšnosti
plot(parameter,avgAccValid,type="b",col=2,xlab='Maximal tree depth',ylab='Accuracy',ylim=c(0.5,1))
lines(parameter,avgAccTrain,type="b",col=3)
legend('bottomright',c('Validation set','Training set'),col=c(2,3),pch='---')
# nalezení optimální hodnoty parametru z hlediska úspěšnosti klasifikace
maxdepthValidated = parameter[which.max(avgAccValid)]
# odhad úspěšnosti klasifikace na nezávislých datech
finalTree <- rpart(sp ~ .,data=trainCrabs,control = rpart.control(minsplit=10,maxdepth=maxdepthValidated))
testAcc <- sum(predict(finalTree,newdata=testCrabs,type='class') == testCrabs$sp)/nrow(testCrabs)
# výsledný rozhodovací strom
rpart.plot(finalTree)
== Úkol - hodhocení modelu pomocí bootstrapu ==
Vyzkoušejte odhad úspěšnosti klasifikace pomocí bootstrapu. Upravte odhadování vhodné hodnoty parametru **maxdepth** na krabích datech. Poměr trénovací a validační množiny ve vnitřní smyčce zvolte 60% a 40%. Pro každou hodnotu opakujte trénování a validování klasifikátoru 32 krát. Výsledky porovnejte s 10-složkouvou křížovou validací.
===== Křivka učení =====
* je ukazatelem vhodnosti zvoleného modelu pro daná data.
* generujeme ji tak, že data rozdělíme na konstantní množinu testovacích dat a trénovací množinu dat, kde postupně zvyšujeme počet příkladů, na kterých se model může učit, a zjišťujeme chybu na datech testovacích.
* v případě, že model je schopen dostatečně dobře generalizovat zpracovávaná data, pak chyba s počtem příkladů stále klesá a blíží se v ideálním případě nule.
Nakreslete křivku učení pro učení rozhodovacího stromu na testovacích datech v R - např. //Iris// a dále pak na datech //parita.csv// - uložena v //{{courses:a6m33dvz:cviceni:parita.zip|parita.zip}}// (pro bližší popis parity např. [[http://cs.wikipedia.org/wiki/Paritn%C3%AD_bit|Paritní bit - Wikipedie]]).
- data vždy nejprve prozkoumejte
- na základě křivky učení rozhodněte, zda je rozhodovací strom pro daná data vhodný
drawLearningCurve <- function(x, y, xtest, ytest, nfolds=10) {
folds <- rep_len(1:nfolds,nrow(x))
acc <- vector(length=nfolds)
for(j in 1:nfolds){
train <- cbind(y[folds <= j],x[folds <= j,])
names(train)[1] <- 'class'
tree <- rpart(class ~ .,data=train,control = rpart.control(minsplit = 3))
acc[j] = sum(predict(tree,newdata=xtest,type='class') == ytest)/length(ytest)
}
plot((1:nfolds)/nfolds,acc,type="b",col=2,xlab='Mohutnost mnoziny',ylab='Uspesnost',ylim=c(0,1))
abline(h=0.5, col="black")
}
# an example of use
drawLearningCurve(trainCrabs[,-1],trainCrabs[,1],testCrabs[,-1],testCrabs[,1],20)