S3 and class order

I always had problems understanding the documentation of how the S3 method is called, and this time it bit me off.

I apologize for asking more than one question, but they are all closely related. Deep in the middle of a complex set of functions, I create many glmnet , particularly logistic ones. Now the glmnet documentation indicates its return value to have both the "glmnet" and (for logistic regression) "lognet" classes. In fact, they are listed in that order.

However, looking at the end of the glmnet implementation, coarser after calling (the internal function) lognet , which sets the fit class to "lognet", I see this line of code just before the return (of the fit variable):

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

From this I would conclude that the class order is actually "lognet", "glmnet".

Unfortunately, I had what was (for example, a document):

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

The problem with this is how S3 methods are sent for it, in particular predict . Here is the code for 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) } 

I added a comment to explain my reasoning. Now, when I call the forecast on this myfit with the new datamatrix mydata and type="response" , like this:

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

I do not, according to the documentation, do predictable probabilities, but linear combinations that are the result of a direct call to predict.glmnet .

I tried to reorder the classes, for example:

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

And then repeat the predictive call: thatโ€™s it: it works! I get the probabilities.

So here are some questions:

  • Am I right to โ€œlearnโ€ that S3 Methods are sent in the order that classes appear?
  • Do I correctly assume that the code in glmnet will lead to the wrong order for dispatching predict correctly?
  • There is nothing in my code that manipulates classes explicitly, as far as I know. What could lead to change?

For completeness: here is an example of code to play with (as I am doing now):

 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) 

Depending on the data generated, the difference is more or less obvious (in my true data set, I noticed negative values โ€‹โ€‹in the so-called probabilities, this is how I took the problem), but you really should see the difference.

Thanks for any input.

Edit

I just found out the terrible truth: either the order worked in glmnet 1.5.2 (which is present on the server, where I ran the actual code, which led to the correction with the cancellation of the order), but the code from 1.6 requires the order to be "lognet", "glmnet" . I have yet to check what happens in 1.7.

Thanks to @Aaron for reminding me of the basics of computer science (besides, "if all else fails, restart": "check your versions"). I mistakenly assumed that the statistical training gods package would be protected from this type of error) and @Gavin to confirm my reconstruction of S3.

+8
r glmnet
source share
1 answer

Yes, the submission order is in the order in which the classes are specified in the class attribute. In a simple, everyday case, yes, the first class declared is the one that was selected by the first dispatch method, and only if it cannot find the method for this class (or NextMethod is NextMethod ), it will go to the second class or the default method cannot be found.

No, I do not think that you are right that the order of the classes is incorrect in the code. The documentation does not look right. The goal is, first, to call predict.lognet() , use the predict.glmnet() to perform basic calculations for all types of lasso / elastic network models installed by glmnet , and finally do some post- processing these general forecasts. This predict.glmnet() not exported from glmnet NAMESPACE, while other methods may also say.

I'm not sure why you are thinking of getting out of this:

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

wrong? I get a matrix of 10 rows and 21 columns with columns related to prediction only for interception plus predictions at 20 lambda values โ€‹โ€‹for which the model coefficients along the lasso / elastic network path were calculated. They do not seem linear combinations and are one response scale for your request.

The order of the classes does not change. I think you misunderstand how the code should work. There is an error in the documentation, because it indicates an incorrect indication. But the code works as it seems to me.

+6
source share

All Articles