Cet article sur Adaboost donne quelques suggestions et code (page 17) pour étendre les modèles à 2 classes aux problèmes de classe K. Je voudrais généraliser ce code, de sorte que je puisse facilement brancher différents modèles à 2 classes et comparer les résultats. Étant donné que la plupart des modèles de classification ont une interface de formule et une predict
méthode, certains de ces éléments devraient être relativement faciles. Malheureusement, je n'ai pas trouvé de moyen standard d'extraire les probabilités de classe des modèles à 2 classes, donc chaque modèle nécessitera un code personnalisé.
Voici une fonction que j'ai écrite pour décomposer un problème de classe K en problèmes de 2 classes et renvoyer des modèles 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)
}
Voici une méthode de prédiction que j'ai écrite pour itérer sur chaque modèle et faire des prédictions:
predict.oneVsAll <- function(object, newX=object$info$X, ...) {
stopifnot(class(object)=='oneVsAll')
lapply(object$models, function(x) {
predict(x, newX, ...)
})
}
Et enfin, voici une fonction permettant de normaliser une data.frame
des probabilités prédites et de classer les cas. Notez qu'il vous appartient de construire la colonne K data.frame
des probabilités à partir de chaque modèle, car il n'existe pas de méthode unifiée pour extraire les probabilités de classe d'un modèle à 2 classes:
classify <- function(dat) {
out <- dat/rowSums(dat)
out$Class <- apply(dat, 1, function(x) names(dat)[which.max(x)])
out
}
Voici un exemple d'utilisation 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
Voici un exemple d'utilisation lda
(je sais que lda peut gérer plusieurs classes, mais ce n'est qu'un exemple):
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
Ces fonctions devraient fonctionner pour tout modèle à 2 classes avec une interface de formule et une predict
méthode. Notez que vous devez séparer manuellement les composants X et Y, ce qui est un peu moche, mais écrire une interface de formule me dépasse pour le moment.
Cette approche a-t-elle un sens pour tout le monde? Existe-t-il un moyen de l'améliorer ou existe-t-il un package existant pour résoudre ce problème?
predict
méthode.
car
, ou l'un des*lab
paquets) aurait fourni une fonction comme la vôtre. Désolé, je ne peux pas aider. J'ai lu un peu sur le fonctionnement de k-way SVM et il semble que c'était plus compliqué que je ne l'aurais pensé.