将2类模型扩展到多类问题


11

关于Adaboost的这篇论文提出了一些建议和代码(第17页),以将2类模型扩展到K类问题。我想对此代码进行概括,以便我可以轻松地插入不同的2类模型并比较结果。由于大多数分类模型都具有公式界面和predict方法,因此其中某些应该相对容易。不幸的是,我还没有找到从2类模型中提取类概率的标准方法,因此每个模型都需要一些自定义代码。

这是我编写的用于将K类问题分解为2类问题并返回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)
}

这是我编写的一种预测方法,用于遍历每个模型并进行预测:

predict.oneVsAll <- function(object, newX=object$info$X, ...) {
    stopifnot(class(object)=='oneVsAll')
    lapply(object$models, function(x) {
        predict(x, newX, ...)
    })
}

最后,这是一个将data.frame预测概率归一化并对案例进行分类的功能。请注意,由您决定data.frame从每个模型构造概率的K列,因为没有统一的方法从2类模型中提取类概率:

classify <- function(dat) {
    out <- dat/rowSums(dat)
    out$Class <- apply(dat, 1, function(x) names(dat)[which.max(x)])
    out
}

这是一个使用示例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

这是一个使用示例lda(我知道lda可以处理多个类,但这只是一个示例):

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

这些函数适用于具有公式接口和predict方法的任何2类模型。请注意,您必须手动拆分X和Y组件,这有点丑陋,但是编写公式界面此刻还超出了我的范围。

这种方法对每个人有意义吗?有什么办法可以改善它,还是有现有的软件包可以解决此问题?


2
哇,直到您问了我一眼,我已经确定某些软件包(如car,或其中一个*lab软件包)会提供与您一样的功能。对不起,我帮不上忙。我已经阅读了一些有关k-way SVM如何工作的信息,似乎它比我想象的要复杂。
韦恩

1
@韦恩:我也是!我敢肯定,只要模型有一个predict方法,就会有一些通用的功能可以做到这一点。
Zach 2012年

Answers:


1

一种改进的方法是使用“加权所有对”方法,该方法比“一对全”更好,同时仍可扩展。

对于现有软件包,glmnet支持(常规)多项式logit,可用作多分类器。


我知道R中有许多支持多类分类的软件包(例如glmnet,随机森林,kernlab,rpart,nnet等)。我对将二进制分类程序包(例如gbm)扩展到多类问题更加好奇。我将研究“加权所有对”。
Zach 2012年

另外,有趣的是它glmnet包含multinomial损失函数。我想知道是否可以在R中的其他算法中使用此损失函数,例如adaor gbm
Zach 2012年

是的,可以扩展某些方法以支持多项式损失函数。例如,内核逻辑回归在这里是这样扩展的:books.nips.cc/papers/files/nips14/AA13.pdf据了解ada,“保留”了特定的(指数)损失函数,但是可以扩展另一个支持多项式损失函数的基于方法-例如,有关多类GBM的详细信息,请参见《统计学习的元素》第360页-为每个增强迭代构建K个二叉树,其中K是类的数目(每个迭代仅一棵树)在二进制情况下是必需的)。
叶夫根尼2012年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.