S3 и порядок классов

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

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

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

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

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

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

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

Проблема в том, как для него отправляются методы S3, в частности предсказывают . Вот код для pred.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")

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

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

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

И затем снова выполняем предсказание: о чудо: это работает! Я получаю вероятности.

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

  1. Прав ли я, «узнав», что Методы S3 отправляются по порядку внешнего вида классов?
  2. Прав ли я, предполагая, что код в glmnet вызовет неправильный порядок для правильной отправки предсказать ?
  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.

8
задан Nick Sabbe 24 June 2011 в 06:56
поделиться