Warning
This page is located in archive.

TEST 05

  1. (0.5 b) Popište (k-násobnou) křížovou validaci. Jak probíhá tvorba trénovací a testovací množiny při použití této metody? Jak se spočítá výsledný odhad chyby zvoleného modelu?
  2. (0.5 b) Jsou-li k dispozici rozsáhlá data, jak a proč je dělíme na data trénovací, testovací a validační?
  3. (0.5 b) Uvažujte záznamy (řádky) v následující tabulce. Příznaky ve sloucích Deadline, IsThereAParty a Lazy jsou vstupní parametry. Příznak Activity je parametr výstupní - třída. Spočítejte hodnotu entropie atributu IsThereAParty vzhledem k výstupnímu parametru Activity. Nápověda: $\log_2 0.2 = -2.32$, $\log_2 0.6 = -0.74$, $0 . \log_2 0 \equiv 0$.

<latex> \begin{table}[] \begin{tabular}{lll|l} \textbf{Deadline} & \textbf{IsThereAParty} & \textbf{Lazy} & \textbf{Activity}
\hline Urgent & Yes & Yes & Party
Urgent & No & Yes & Study
Near & Yes & Yes & Party
None & Yes & No & Party
None & No & Yes & Pub
None & Yes & No & Party
Near & No & No & Study
Near & No & Yes & TV
Near & Yes & Yes & Party
Urgent & No & No & Study
\hline \end{tabular} \end{table} </latex>

Cvičení 6 - Výběr a hodnocení modelu

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 parita.zip (pro bližší popis parity např. Paritní bit - Wikipedie).

  1. data vždy nejprve prozkoumejte
  2. 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)

courses/a6m33dvz/cviceni/06-testovani.txt · Last modified: 2018/11/07 14:54 by nemymila