2015-07-05 25 views
5

Questa è una domanda relativa a https://stats.stackexchange.com/questions/21572/how-to-plot-decision-boundary-of-a-k-nearest-neighbor-classifier-from-elements-oVariazione su "Come tracciare il confine decisionale di un classificatore vicino al k più vicino da Elementi di Apprendimento Statistico?"

Per completezza, ecco l'esempio originale da questo link:

library(ElemStatLearn) 
require(class) 
x <- mixture.example$x 
g <- mixture.example$y 
xnew <- mixture.example$xnew 
mod15 <- knn(x, xnew, g, k=15, prob=TRUE) 
prob <- attr(mod15, "prob") 
prob <- ifelse(mod15=="1", prob, 1-prob) 
px1 <- mixture.example$px1 
px2 <- mixture.example$px2 
prob15 <- matrix(prob, length(px1), length(px2)) 
par(mar=rep(2,4)) 
contour(px1, px2, prob15, levels=0.5, labels="", xlab="", ylab="", main= 
     "15-nearest neighbour", axes=FALSE) 
points(x, col=ifelse(g==1, "coral", "cornflowerblue")) 
gd <- expand.grid(x=px1, y=px2) 
points(gd, pch=".", cex=1.2, col=ifelse(prob15>0.5, "coral", "cornflowerblue")) 
box() 

Ho giocato con quell'esempio, e vorrei cercare di farlo funzionare con tre classi. Posso modificare alcuni valori di g con qualcosa come

g[8:16] <- 2 

solo per far finta che ci siano alcuni campioni che provengono da una terza classe. Non posso far funzionare la trama, però. Credo che ho bisogno di cambiare le linee che si occupano con la percentuale di voti per classe vincitrice:

prob <- attr(mod15, "prob") 
prob <- ifelse(mod15=="1", prob, 1-prob) 

e anche i livelli sul contorno:

contour(px1, px2, prob15, levels=0.5, labels="", xlab="", ylab="", main= 
"15-nearest neighbour", axes=FALSE) 

Sono, inoltre, non sicuro di contorno è il diritto strumento per questo. Un'alternativa che funziona è creare una matrice di dati che copra la regione che mi interessa, classificare ogni punto di questa matrice e tracciare quelli con un marcatore grande e colori diversi, in modo simile a quello che viene fatto con i punti (gd .. .) po.

Lo scopo finale è quello di essere in grado di mostrare diversi limiti di decisione generati da diversi classificatori. Qualcuno può indicarmi la giusta direzione?

grazie Rafael

risposta

11

Separando le parti principali del codice aiuterà illustra come raggiungere questo obiettivo:

dati dei test con 3 classi

train <- rbind(iris3[1:25,1:2,1], 
       iris3[1:25,1:2,2], 
       iris3[1:25,1:2,3]) 
cl <- factor(c(rep("s",25), rep("c",25), rep("v",25))) 

dati di test che coprono una griglia

require(MASS) 

test <- expand.grid(x=seq(min(train[,1]-1), max(train[,1]+1), 
          by=0.1), 
        y=seq(min(train[,2]-1), max(train[,2]+1), 
          by=0.1)) 

Classificazione per quella griglia

3 classi, ovviamente,

require(class) 
classif <- knn(train, test, cl, k = 3, prob=TRUE) 
prob <- attr(classif, "prob") 

struttura di dati per tracciare

require(dplyr) 

dataf <- bind_rows(mutate(test, 
          prob=prob, 
          cls="c", 
          prob_cls=ifelse(classif==cls, 
              1, 0)), 
        mutate(test, 
          prob=prob, 
          cls="v", 
          prob_cls=ifelse(classif==cls, 
              1, 0)), 
        mutate(test, 
          prob=prob, 
          cls="s", 
          prob_cls=ifelse(classif==cls, 
              1, 0))) 

Trama

require(ggplot2) 
ggplot(dataf) + 
    geom_point(aes(x=x, y=y, col=cls), 
       data = mutate(test, cls=classif), 
       size=1.2) + 
    geom_contour(aes(x=x, y=y, z=prob_cls, group=cls, color=cls), 
       bins=2, 
       data=dataf) + 
    geom_point(aes(x=x, y=y, col=cls), 
       size=3, 
       data=data.frame(x=train[,1], y=train[,2], cls=cl)) 

plot

Ci può anche essere un po 'più elaborato e tracciare la probabilità di appartenenza di classe come indicazione della "fiducia".

ggplot(dataf) + 
    geom_point(aes(x=x, y=y, col=cls, size=prob), 
       data = mutate(test, cls=classif)) + 
    scale_size(range=c(0.8, 2)) + 
    geom_contour(aes(x=x, y=y, z=prob_cls, group=cls, color=cls), 
       bins=2, 
       data=dataf) + 
    geom_point(aes(x=x, y=y, col=cls), 
       size=3, 
       data=data.frame(x=train[,1], y=train[,2], cls=cl)) + 
    geom_point(aes(x=x, y=y), 
       size=3, shape=1, 
       data=data.frame(x=train[,1], y=train[,2], cls=cl)) 

enter image description here

+0

Fantastico, l'ultima trama è un enorme anticipo su quello che volevo fare! –