Розширення 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передбачувані ймовірності та класифікувати випадки. Зауважте, що вам належить побудувати K-стовпчик data.frameймовірностей з кожної моделі, оскільки не існує єдиного способу вилучення ймовірностей класу з 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

Ці функції повинні працювати для будь-якої моделі 2 класу з інтерфейсом формули та predictметодом. Зауважте, що вам потрібно вручну розділити компоненти X і Y, що трохи негарно, але написання інтерфейсу формули наразі поза мною.

Чи має сенс цей підхід для всіх? Чи я можу це покращити, чи існує існуючий пакет для вирішення цього питання?


2
Нічого собі, поки ви не поцікавились, і я подивився, я був би впевнений, що якийсь пакет (наприклад car, чи один із *labпакунків) забезпечив би функцію, як ваш. Вибачте, я не можу допомогти. Я трохи прочитав про те, як працює SV-спосіб, і здається, що це було складніше, ніж я міг подумати.
Уейн

1
@Wayne: Я теж! Я був певен, що буде якась загальна функція, яка б це зробила, за умови, що модель має predictметод.
Зак

Відповіді:


1

Один із способів поліпшити - це використовувати підхід "зважених всіх пар", який нібито є кращим, ніж "один проти всіх", але все ще масштабується.

Що стосується існуючих пакетів, glmnetпідтримується (регульований) багаточленний logit, який може використовуватися як багатокласний класифікатор.


Мені відомо про безліч пакетів в R, які підтримують багатокласну класифікацію (такі як glmnet, випадкові ліси, kernlab, rpart, nnet тощо). Мені цікавіше розширювати пакети бінарної класифікації (наприклад, gbm) на багатокласові проблеми. Я перегляну "зважені всі пари".
Зак

Також цікаво, що glmnetвключає функцію multinomialвтрат. Цікаво, чи можна цю функцію втрати використовувати в інших алгоритмах R, наприклад, adaабо gbm?
Зак

Так, деякі методи можна розширити, щоб підтримати функцію мультиноміальних втрат. Наприклад, логістична регресія ядра розширена саме тут: books.nips.cc/papers/files/nips14/AA13.pdf Наскільки відомо ada, "зарезервовано" для конкретної (експоненціальної) функції втрат, але можна розширити іншу прискорення метод, заснований на підтримці функції мультиноміальних втрат - наприклад, див. сторінку 360 Елементів статистичного навчання для детальної інформації про багатокласний GBM - K бінарні дерева будуються для кожної інтенсивної ітерації, де K - кількість класів (лише одне дерево за ітерацію потрібен у двійковому випадку).
Євген
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.