Wie zeichnet man die Entscheidungsgrenze eines k-Nächsten-Nachbarn-Klassifikators aus Elementen des statistischen Lernens?

31

Ich möchte die Handlung erzeugen, die im Buch ElemStatLearn "Die Elemente des statistischen Lernens: Data Mining, Inferenz und Vorhersage. Zweite Ausgabe" von Trevor Hastie & Robert Tibshirani & Jerome Friedman beschrieben ist. Die Handlung ist:

Bildbeschreibung hier eingeben

Ich frage mich, wie ich dieses genaue Diagramm in erzeugen kann. RBeachten Sie insbesondere die Gittergrafiken und die Berechnung, um die Grenze anzuzeigen.

littleEinstein
quelle
1
@StasK: Ja, das ist es. Wie wird der Plot erstellt? Würden Sie bitte helfen? Danke vielmals!
LittleEinstein

Antworten:

35

Um diese Abbildung zu reproduzieren, muss das ElemStatLearn- Paket auf Ihrem System installiert sein. Der künstliche Datensatz wurde mit mixture.example()@StasK erzeugt.

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()

Alle bis auf die letzten drei Befehle stammen aus der Online-Hilfe für mixture.example. Beachten Sie, dass wir die Tatsache verwendet haben, dass expand.griddie Ausgabe durch Variieren xzuerst angeordnet wird, wodurch es weiterhin möglich ist, Farben (nach Spalten) in der prob15Matrix (der Dimension 69x99) zu indizieren, die den Anteil der Stimmen für die Gewinnerklasse für die einzelnen Gitterkoordinaten enthält ( px1, px2).

Bildbeschreibung hier eingeben

chl
quelle
+1. Vielen Dank! Ich frage mich auch, wie ich die Daten wie im Text "Expose the oracle" beschrieben generieren soll. Könnten Sie das bitte auch hinzufügen, anstatt die Daten von der Website zu verwenden?
LittleEinstein
@littleEinstein Meinen Sie, was in der Online-Hilfe für gegeben ist mixture.example? Schauen Sie sich das Simulationssetup an, beginnend mit # Reproducing figure 2.4, page 17 of the book:im Beispielabschnitt.
chl
Kannst du mir bitte den Link mitteilen? Ich kann es nicht finden.
LittleEinstein
Sorry @littleEinstein, aber es gibt etwas, was ich wahrscheinlich vermisse. Es ist nur eine Frage der Eingabe help(mixture.example)oder example(mixture.example)der R-Eingabeaufforderung (nachdem Sie das erforderliche Paket mit geladen haben library(ElemStatLearn)). Der Code zum Generieren des künstlichen Datensatzes (nicht zum Generieren von Abb. 2.4) ist im Abschnitt „Beispiel“ in R geschrieben.
chl
1
Übrigens, ich bin gerade auf @ Shane's Weblog gestoßen, wo er es ggplotfür ähnliche Zwecke benutzt hat. Überprüfen Sie dies: ESL 2.1: Lineare Regression vs. KNN .
Chl
7

Ich lerne ESL selbst und versuche, alle im Buch enthaltenen Beispiele durchzuarbeiten. Ich habe dies gerade getan und Sie können den R-Code unten überprüfen:

library(MASS)
# set the seed to reproduce data generation in the future
seed <- 123456
set.seed(seed)

# generate two classes means
Sigma <- matrix(c(1,0,0,1),nrow = 2, ncol = 2)
means_1 <- mvrnorm(n = 10, mu = c(1,0), Sigma)
means_2 <- mvrnorm(n = 10, mu = c(0,1), Sigma)

# pick an m_k at random with probability 1/10
# function to generate observations
genObs <- function(classMean, classSigma, size, ...)
{
  # check input
  if(!is.matrix(classMean)) stop("classMean should be a matrix")
  nc <- ncol(classMean)
  nr <- nrow(classMean)
  if(nc != 2) stop("classMean should be a matrix with 2 columns")
  if(ncol(classSigma) != 2) stop("the dimension of classSigma is wrong")

  # mean for each obs
    # pick an m_k at random
  meanObs <- classMean[sample(1:nr, size = size, replace = TRUE),]
  obs <- t(apply(meanObs, 1, function(x) mvrnorm(n = 1, mu = x, Sigma = classSigma )) )
  colnames(obs) <- c('x1','x2')
  return(obs)
}


obs100_1 <- genObs(classMean = means_1, classSigma = Sigma/5, size = 100)
obs100_2 <- genObs(classMean = means_2, classSigma = Sigma/5, size = 100)

# generate label
y <- rep(c(0,1), each = 100)

# training data matrix
trainMat <- as.data.frame(cbind(y, rbind(obs100_1, obs100_2)))

# plot them
library(lattice)
with(trainMat, xyplot(x2 ~ x1,groups = y, col=c('blue', 'orange')))

# now fit two models

# model 1: linear regression
lmfits <- lm(y ~ x1 + x2 , data = trainMat)

# get the slope and intercept for the decision boundary
intercept <- -(lmfits$coef[1] - 0.5) / lmfits$coef[3]
slope <- - lmfits$coef[2] / lmfits$coef[3]

# Figure 2.1
xyplot(x2 ~ x1, groups = y, col = c('blue', 'orange'), data = trainMat,
       panel = function(...)
       {
        panel.xyplot(...)
        panel.abline(intercept, slope)
        },
       main = 'Linear Regression of 0/1 Response')    

# model2: k nearest-neighbor methods
library(class)
# get the range of x1 and x2
rx1 <- range(trainMat$x1)
rx2 <- range(trainMat$x2)
# get lattice points in predictor space
px1 <- seq(from = rx1[1], to = rx1[2], by = 0.1 )
px2 <- seq(from = rx2[1], to = rx2[2], by = 0.1 )
xnew <- expand.grid(x1 = px1, x2 = px2)

# get the contour map
knn15 <- knn(train = trainMat[,2:3], test = xnew, cl = trainMat[,1], k = 15, prob = TRUE)
prob <- attr(knn15, "prob")
prob <- ifelse(knn15=="1", prob, 1-prob)
prob15 <- matrix(prob, nrow = length(px1), ncol = length(px2))

# Figure 2.2
par(mar = rep(2,4))
contour(px1, px2, prob15, levels=0.5, labels="", xlab="", ylab="", main=
    "15-nearest neighbour", axes=FALSE)
points(trainMat[,2:3], col=ifelse(trainMat[,1]==1, "coral", "cornflowerblue"))
points(xnew, pch=".", cex=1.2, col=ifelse(prob15>0.5, "coral", "cornflowerblue"))
box()
Daoying Lin
quelle
1
Um hier Code einzugeben, ohne dies zu tun, können Sie den Code markieren und dann auf die Schaltfläche "Code" oben auf der Seite klicken. Es befindet sich in einer Reihe von Symbolen / Schaltflächen. Der Code sieht aus wie geschweifte Klammern.
Peter Flom - Wiedereinsetzung von Monica
Betreff: "Einfügen eines R-Code-Blocks". Sie haben Zugriff auf eine kleine Menüleiste, wenn Sie Ihren Beitrag bearbeiten.
chl
Wenn Sie keinen Editor verwenden, der Codeblöcke problemlos einrücken kann, werden Sie wahrscheinlich gerne zu einem wechseln. ZB in Rstudio Auswahl des Code und drücken Registerkarte Einzüge es, in vim können Sie 5>>etc.
Mark