S3 и порядок занятий - PullRequest
8 голосов
/ 24 июня 2011

У меня всегда были проблемы с пониманием документации о том, как вызываются методы S3, и на этот раз меня укусило.

Я заранее извинюсь за то, что задал более одного вопроса, но онивсе тесно связано.В глубине сложного набора функций я создаю множество «1003» подгонок, в частности логистических.Теперь в документации glmnet указано возвращаемое значение для обоих классов: "glmnet" и (для логистической регрессии) "lognet".Фактически, они указываются в следующем порядке.

Однако, глядя на конец реализации glmnet, правее после вызова (внутренней функции) lognet, которая устанавливает класс fit в "lognet", я вижу эту строку кода непосредственно перед возвратом (переменной fit):

class(fit) = c(class(fit), "glmnet")

Из этого я бы заключил, что порядок классов на самом деле"lognet", "glmnet".

К сожалению, подгонка, которую я имел, имела (как предполагает документ):

> class(myfit)
[1] "glmnet" "lognet"

Проблема заключается в том, как методы S3 отправляются дляэто, в частности predict.Вот код для predict.lognet:

function (object, newx, s = NULL, type = c("link", "response", 
    "coefficients", "class", "nonzero"), exact = FALSE, offset, 
    ...) 
{
    type = match.arg(type)
    nfit = NextMethod("predict") #<- supposed to call predict.glmnet, I think
    switch(type, response = {
        pp = exp(-nfit)
        1/(1 + pp)
    }, class = ifelse(nfit > 0, 2, 1), nfit)
}

Я добавил комментарий, чтобы объяснить мои рассуждения.Теперь, когда я вызываю прогнозирование для этого myfit с новыми матрицами данных mydata и type="response", например:

predict(myfit, newx=mydata, type="response")

, я, согласно документации, не получаю предсказанные вероятности, нолинейные комбинации, которые являются точным результатом немедленного вызова predict.glmnet.

Я попытался изменить порядок классов, например:

orgclass<-class(myfit)
class(myfit)<-rev(orgclass)

И затем сделал прогнозЗвоните еще раз: вот, это работает!Я делаю получить вероятности.

Итак, вот несколько вопросов:

  1. Прав ли я, узнав, что методы S3 отправляются в порядкепоявление классов?
  2. Прав ли я, предполагая, что код в glmnet приведет к неправильному порядку правильной отправки predict?
  3. В моем коде нет ничего, что манипулирует классамиявно / заметно, насколько мне известно.Что может привести к изменению порядка?

Для полноты картины: вот пример кода, с которым можно поиграться (как я делаю сейчас):

library(glmnet)
y<-factor(sample(2, 100, replace=TRUE))
xs<-matrix(runif(100), ncol=1)
colnames(xs)<-"x"
myfit<-glmnet(xs, y, family="binomial")
mydata<-matrix(runif(10), ncol=1)
colnames(mydata)<-"x"
class(myfit)
predict(myfit, newx=mydata, type="response")
class(myfit)<-rev(class(myfit))
class(myfit)
predict(myfit, newx=mydata, type="response")
class(myfit)<-rev(class(myfit))#set it back
class(myfit)

В зависимостина сгенерированных данных разница более или менее очевидна (в моем истинном наборе данных я заметил отрицательные значения в так называемых вероятностях, как я и решил проблему), но вы действительно должны увидеть разницу.

Спасибо за любой ввод.

Редактировать :

Я только что узнал ужасную правду: любой порядок работал в glmnet 1.5.2 (который присутствует на сервере, гдеЯ запустил реальный код, что привело к соответствию с обратным порядком классов), но код из 1.6 требует, чтобы порядок был «lognet», «glmnet».Мне еще предстоит проверить, что происходит в 1.7.

Спасибо @Aaron за напоминание об основах информатики (кроме «если ничего не помогает, перезапустите»: «проверьте свои версии»).Я ошибочно предположил, что пакет от богов статистического обучения будет защищен от ошибок этого типа), и @Gavin за подтверждение моей реконструкции работы S3.

1 Ответ

6 голосов
/ 24 июня 2011

Да, порядок отправки находится в том порядке, в котором классы перечислены в атрибуте класса. В простом повседневном случае да, первый указанный класс - это класс, выбранный первым методом диспетчеризации, и только если ему не удается найти метод для этого класса (или вызывается NextMethod), он перейдет к второй класс или не удалось найти метод default.

Нет, я не думаю, что вы правы, что в коде неправильный порядок классов. Документация выглядит неправильно. Намерение явно состоит в том, чтобы сначала вызвать predict.lognet(), использовать рабочую лошадку predict.glmnet(), чтобы выполнить базовые вычисления для всех типов моделей лассо / эластичной сетки, установленных в glmnet , и, наконец, выполнить некоторую постобработку этих общих прогнозы. То, что predict.glmnet() является , а не экспортируется из glmnet NAMESPACE, в то время как другие методы, возможно, тоже говорят.

Я не уверен, почему вы думаете, вывод из этого:

predict(myfit, newx=mydata, type="response")

не так? Я получаю матрицу из 10 строк и 21 столбца, причем столбцы относятся к прогнозированию модели только для перехвата плюс прогнозам для 20 значений лямбды, при которых были рассчитаны коэффициенты модели вдоль пути лассо / эластичной сетки. Они не являются линейными комбинациями и являются одной из шкал ответов, как вы просили.

Порядок занятий не меняется. Я думаю, вы неправильно понимаете, как должен работать код. В документации есть ошибка, так как там указано неправильное расположение. Но код работает так, как я думаю.

...