Questo documento su Adaboost fornisce alcuni suggerimenti e codice (pagina 17) per estendere i modelli di classe 2 ai problemi di classe K. Vorrei generalizzare questo codice, in modo da poter collegare facilmente diversi modelli di 2 classi e confrontare i risultati. Poiché la maggior parte dei modelli di classificazione ha un'interfaccia formula e un predict
metodo, alcuni di questi dovrebbero essere relativamente facili. Sfortunatamente, non ho trovato un modo standard per estrarre le probabilità di classe da modelli di 2 classi, quindi ogni modello richiederà un codice personalizzato.
Ecco una funzione che ho scritto per suddividere un problema di classe K in problemi di classe 2 e restituire modelli K:
oneVsAll <- function(X,Y,FUN,...) {
models <- lapply(unique(Y), function(x) {
name <- as.character(x)
.Target <- factor(ifelse(Y==name,name,'other'), levels=c(name, 'other'))
dat <- data.frame(.Target, X)
model <- FUN(.Target~., data=dat, ...)
return(model)
})
names(models) <- unique(Y)
info <- list(X=X, Y=Y, classes=unique(Y))
out <- list(models=models, info=info)
class(out) <- 'oneVsAll'
return(out)
}
Ecco un metodo di previsione che ho scritto per scorrere su ogni modello e fare previsioni:
predict.oneVsAll <- function(object, newX=object$info$X, ...) {
stopifnot(class(object)=='oneVsAll')
lapply(object$models, function(x) {
predict(x, newX, ...)
})
}
E infine, ecco una funzione per trasformare una normalizzazione data.frame
delle probabilità previste e classificare i casi. Nota che spetta a te costruire la colonna K data.frame
di probabilità da ciascun modello, poiché non esiste un modo unificato per estrarre le probabilità di classe da un modello di 2 classi:
classify <- function(dat) {
out <- dat/rowSums(dat)
out$Class <- apply(dat, 1, function(x) names(dat)[which.max(x)])
out
}
Ecco un esempio usando adaboost
:
library(ada)
library(caret)
X <- iris[,-5]
Y <- iris[,5]
myModels <- oneVsAll(X, Y, ada)
preds <- predict(myModels, X, type='probs')
preds <- data.frame(lapply(preds, function(x) x[,2])) #Make a data.frame of probs
preds <- classify(preds)
>confusionMatrix(preds$Class, Y)
Confusion Matrix and Statistics
Reference
Prediction setosa versicolor virginica
setosa 50 0 0
versicolor 0 47 2
virginica 0 3 48
Ecco un esempio usando lda
(so che lda può gestire più classi, ma questo è solo un esempio):
library(MASS)
myModels <- oneVsAll(X, Y, lda)
preds <- predict(myModels, X)
preds <- data.frame(lapply(preds, function(x) x[[2]][,1])) #Make a data.frame of probs
preds <- classify(preds)
>confusionMatrix(preds$Class, Y)
Confusion Matrix and Statistics
Reference
Prediction setosa versicolor virginica
setosa 50 0 0
versicolor 0 39 5
virginica 0 11 45
Queste funzioni dovrebbero funzionare per qualsiasi modello di 2 classi con un'interfaccia formula e un predict
metodo. Nota che devi dividere manualmente i componenti X e Y, il che è un po 'brutto, ma la scrittura di un'interfaccia formula è al di là di me al momento.
Questo approccio ha senso per tutti? Esiste un modo per migliorarlo o esiste un pacchetto esistente per risolvere questo problema?
predict
metodo.
car
, o uno dei*lab
pacchetti) avrebbero fornito una funzione come la tua. Scusa, non posso aiutarti. Ho letto un po 'su come funziona SV-k-way e sembra che sia stato più complicato di quanto avrei pensato.