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