У меня всегда были проблемы с пониманием документации о том, как вызываются методы 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)
И затем сделал прогнозЗвоните еще раз: вот, это работает!Я делаю получить вероятности.
Итак, вот несколько вопросов:
- Прав ли я, узнав, что методы S3 отправляются в порядкепоявление классов?
- Прав ли я, предполагая, что код в
glmnet
приведет к неправильному порядку правильной отправки predict
? - В моем коде нет ничего, что манипулирует классамиявно / заметно, насколько мне известно.Что может привести к изменению порядка?
Для полноты картины: вот пример кода, с которым можно поиграться (как я делаю сейчас):
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.