Memperluas model 2 kelas ke masalah multi-kelas

11

Makalah ini pada Adaboost memberikan beberapa saran dan kode (halaman 17) untuk memperluas model 2-kelas ke masalah kelas-K. Saya ingin menggeneralisasi kode ini, sehingga saya dapat dengan mudah memasang model 2-kelas yang berbeda dan membandingkan hasilnya. Karena sebagian besar model klasifikasi memiliki antarmuka rumus dan predictmetode, beberapa di antaranya seharusnya relatif mudah. Sayangnya, saya belum menemukan cara standar untuk mengekstraksi probabilitas kelas dari model 2-kelas, sehingga setiap model akan memerlukan beberapa kode khusus.

Berikut adalah fungsi yang saya tulis untuk memecah masalah K-class menjadi masalah 2-kelas, dan mengembalikan model 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)
}

Berikut adalah metode prediksi yang saya tulis untuk mengulang setiap model dan membuat prediksi:

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

Dan akhirnya, inilah fungsi untuk mengubah normalisasi data.frameprobabilitas yang diprediksi dan mengklasifikasikan kasus. Perhatikan bahwa terserah Anda untuk membuat kolom K- data.frameprobabilitas dari masing-masing model, karena tidak ada cara terpadu untuk mengekstrak probabilitas kelas dari model 2-kelas:

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

Berikut ini contoh menggunakan 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

Berikut ini adalah contoh menggunakan lda(Saya tahu lda dapat menangani beberapa kelas, tetapi ini hanya sebuah contoh):

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

Fungsi-fungsi ini harus bekerja untuk setiap model 2-kelas dengan antarmuka rumus dan predictmetode. Perhatikan bahwa Anda harus secara manual membagi komponen X dan Y, yang agak jelek, tetapi menulis antarmuka rumus di luar saya saat ini.

Apakah pendekatan ini masuk akal bagi semua orang? Apakah ada cara saya bisa memperbaikinya, atau apakah ada paket yang ada untuk menyelesaikan masalah ini?

Zach
sumber
2
Wow, sampai Anda bertanya dan saya melihat, saya akan yakin bahwa beberapa paket (seperti car, atau salah satu *labpaket) akan menyediakan fungsi seperti milik Anda. Maaf saya tidak bisa membantu. Saya telah membaca sedikit tentang cara kerja k-way SVM dan sepertinya itu lebih rumit dari yang saya kira.
Wayne
1
@Wayne: Aku juga! Saya yakin akan ada beberapa fungsi umum yang akan melakukan ini, asalkan model memiliki predictmetode.
Zach

Jawaban:

1

Salah satu cara untuk meningkatkan adalah dengan menggunakan pendekatan "tertimbang semua pasangan" yang seharusnya lebih baik daripada "satu terhadap semua" sementara masih dapat diukur.

Adapun paket yang ada, glmnetmendukung (diatur) multinomial logit yang dapat digunakan sebagai multi-class classifier.

Yevgeny
sumber
Saya mengetahui banyak paket dalam R yang mendukung klasifikasi multi-kelas (seperti glmnet, forest acak, kernlab, rpart, nnet, dll.). Saya lebih ingin tahu tentang memperluas paket klasifikasi biner (misalnya gbm) ke masalah multiclass. Saya akan melihat ke "semua pasangan tertimbang."
Zach
Juga, itu menarik yang glmnetmencakup multinomialfungsi kerugian. Saya ingin tahu apakah fungsi kerugian ini dapat digunakan dalam algoritme lain dalam R, seperti adaatau gbm?
Zach
Ya, beberapa metode dapat diperluas untuk mendukung fungsi kehilangan multinomial. Sebagai contoh, regresi logistik kernel diperpanjang seperti itu di sini: books.nips.cc/papers/files/nips14/AA13.pdf Sejauh yang diketahui ada"dicadangkan" untuk fungsi kerugian spesifik (eksponensial), tetapi seseorang dapat memperpanjang peningkatan lainnya metode berbasis untuk mendukung fungsi kehilangan multinomial - mis. lihat halaman 360 dari Elemen Pembelajaran Statistik untuk detail tentang multi-kelas GBM - Pohon biner K dibangun untuk setiap peningkatan iterasi di mana K adalah jumlah kelas (hanya satu pohon per iterasi diperlukan dalam kasus biner).
Yevgeny