Zawsze miałem problemy ze zrozumieniem dokumentacji dotyczącej sposobu wywoływania metod S3, i tym razem mnie gryzą.S3 i kolejność klas
Przepraszam z góry za zadawanie więcej niż jednego pytania, ale wszystkie są ze sobą ściśle powiązane. Głęboko w sercu złożonego zestawu funkcji, tworzę wiele pasowań glmnet
, w szczególności logistycznych. Teraz, dokumentacja glmnet
określa jego wartość zwracaną, aby obie klasy "glmnet" i (dla regresji logistycznej) "lognet". W rzeczywistości są one określone w tej kolejności.
Jednak patrząc na koniec realizacji glmnet
, Righter po wywołaniu (funkcja wewnętrzna) lognet
, że ustawia klasę fit
do „lognet”, widzę tę linię kodu tuż przed powrotem (zmiennej fit
):
class(fit) = c(class(fit), "glmnet")
od tego, chciałbym stwierdzić, że kolejność klas jest w istocie „lognet”, „glmnet”.
Niestety pasowanie miałem, miał (jak sugeruje doc):
> class(myfit)
[1] "glmnet" "lognet"
Problemem jest to sposób metody S3 są wysyłane do niego, w szczególności predict
. Oto kod dla 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)
}
Dodałem komentarz wyjaśnić moje rozumowanie. Teraz, gdy zgłoszę przewidzieć na tej myfit
z nowym DataMatrix mydata
i type="response"
, tak:
predict(myfit, newx=mydata, type="response")
, nie wiem, jak na dokumentację, uzyskać przewidywanych prawdopodobieństw, ale kombinacje liniowe, która jest dokładnie natychmiastowego wywołania predict.glmnet
.
Próbowałem odwrócić kolejność klas, tak jak poniżej:
orgclass<-class(myfit)
class(myfit)<-rev(orgclass)
A potem robi przewidzieć zadzwonić ponownie: lo i oto: to działa! I do uzyskać prawdopodobieństwa.
Więc tutaj przyjść jakieś pytania:
- mam rację „dowiedziawszy” że S3 metody są wywoływane w kolejności wyglądu klas?
- mam rację zakładając kod w
glmnet
mogłoby spowodować niewłaściwe zamówienie dla prawidłowego wysyłekpredict
? - W moim kodzie nie ma nic, co manipuluje klasami jawnie/widocznie według mojej wiedzy. Co może spowodować zmianę zamówienia na ?
kompletności boską: oto przykładowy kod, aby bawić się z (jak robię sobie teraz):
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)
zależności od danych generowanych, różnica jest bardziej lub mniej oczywiste (w moim prawdziwym zestawie danych zauważyłem ujemne wartości w tak zwanych prawdopodobieństwach, w ten sposób podjąłem problem), ale naprawdę powinniście zobaczyć różnicę.
Dzięki za wszelkie dane wejściowe.
Edit:
Właśnie okazało się straszną prawdę: albo kolejność pracował w glmnet 1.5.2 (który jest obecny na serwerze, gdzie wpadłem rzeczywisty kod, w wyniku ataku z zamówieniem klasy odwrócony), ale kod z wersji 1.6 wymaga, aby kolejność brzmiała "lognet", "glmnet". Muszę jeszcze sprawdzić, co dzieje się w 1.7.
Podziękowania dla @Aarona za przypomnienie podstaw informatyki (oprócz "jeśli wszystko inne zawiedzie, uruchom ponownie": "sprawdź wersje"). Błędnie założyłem, że pakiet bogów statystycznego uczenia się będzie chroniony przed tego rodzaju błędem), a także @Gavinowi za potwierdzenie mojej rekonstrukcji sposobu działania S3.
Po uruchomieniu kodu otrzymuję polecenie '" lognet "" glmnet "' po pierwszym wywołaniu 'class', które jest odwrotne od tego, co mówisz. Mam glmnet 1.7; jaka masz wersję? – Aaron