que he tenido problemas para entender todos los días la documentación sobre cómo se llaman métodos S3, y esta vez me está mordiendo.S3 y el orden de las clases
me disculparé por adelantado para pedir más de una pregunta, sino que están estrechamente relacionados. En el corazón de un complejo conjunto de funciones, creo muchos ajustes para glmnet
, en particular los logísticos. Ahora, la documentación glmnet
especifica su valor de retorno para tener ambas clases "glmnet" y (para la regresión logística) "lognet". De hecho, estos se especifican en este orden.
Sin embargo, mirando al final de la ejecución de glmnet
, más justo después de la llamada a (la función interna) lognet
, que establece la clase de fit
a "LogNet", veo esta línea de código justo antes del regreso (de la variable fit
):
class(fit) = c(class(fit), "glmnet")
partir de esto, llego a la conclusión de que el orden de las clases es de hecho "LogNet", "glmnet".
Por desgracia, el ajuste que tenía, tenía (al igual que el documento sugiere):
> class(myfit)
[1] "glmnet" "lognet"
El problema con esto es la forma en métodos S3 se envían para ello, en particular, predict
. Aquí está el código para 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)
}
He añadido un comentario para explicar mi razonamiento. Ahora cuando llamo predecir en este myfit
con un nuevo Datamatrix mydata
y type="response"
, así:
predict(myfit, newx=mydata, type="response")
, yo no, según la documentación, ver las probabilidades predichas, pero las combinaciones lineales, que es exactamente el resultado de llamar al predict.glmnet
inmediatamente.
he intentado invertir el orden de las clases, así:
orgclass<-class(myfit)
class(myfit)<-rev(orgclass)
y luego hacer el predecir llamar de nuevo: he aquí: funciona! I do obtener las probabilidades.
lo tanto, aquí vienen algunas preguntas:
- Estoy en lo cierto 'habiendo aprendido' que S3 métodos se envían con el fin de aparición de las clases?
- Estoy en lo cierto al suponer el código en
glmnet
causaría el orden equivocado para el correcto envío depredict
? - En mi código no hay nada que manipule las clases explícita/visiblemente que yo sepa. ¿Qué podría causar la orden de cambiar?
Para completarlo: aquí algunos ejemplos de código para jugar con (como estoy haciendo yo ahora):
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)
En función de los datos generados, la diferencia es más o menos evidente (en mi verdadero conjunto de datos noté valores negativos en las llamadas probabilidades, que es la forma en que recogí el problema), pero en realidad debería ver una diferencia.
Gracias por cualquier entrada.
Editar:
acabo de descubrir la horrible verdad: cualquier orden trabajó en glmnet 1.5.2 (que está presente en el servidor donde me encontré con el código real, lo que resulta en el ajuste con el fin de clases invertido), pero el código de 1.6 requiere que el orden sea "lognet", "glmnet". Todavía tengo que verificar lo que sucede en 1.7.
Gracias a @Aaron por recordarme los conceptos básicos de la informática (además de 'si todo lo demás falla, reinícielo': 'verifique sus versiones'). Había asumido erróneamente que un paquete de los dioses del aprendizaje estadístico estaría protegido contra este tipo de error), y a @Gavin para confirmar mi reconstrucción de cómo funciona S3.
Cuando ejecuto el código obtengo el orden '" lognet "" glmnet "' después de la primera llamada de 'clase', que está al revés de lo que dices que obtuviste. Tengo glmnet 1.7; ¿Qué versión tienes? – Aaron