Спецификатор пространства имен в пакете gam не работает

Я не понимаю, почему две нижеследующие модели гаммы дают разные результаты. Единственная разница в том, что в одной из моделей я добавил спецификатор пространства имен gam:: перед функциями gam и s.

Я хочу сделать это, потому что изучаю различия между запуском функции gam в пакете gam и в пакете mgcv.

library(ISLR)  
library(gam) 
gam.m3 <- gam::gam(wage ~ gam::s(year,4) + gam::s(age,5) + education,data=Wage) 
gam.m3.orig <- gam(wage ~ s(year,4) + s(age,5) + education, data=Wage)

#Coefficients are different
coef(gam.m3)[1]; coef(gam.m3.orig)[1] 

#Models are different
gam.m3$df.residual; gam.m3.orig$df.residual

Вот результат. Вроде бы коэффициенты и степени свободы не должны отличаться; на самом деле две модели должны быть абсолютно одинаковыми. Но они разные, и я не понимаю, почему. Любые предложения приветствуются, я сейчас в растерянности.

> library(ISLR)  
> library(gam) 
Loading required package: splines
Loading required package: foreach
Loaded gam 1.16

> gam.m3 <- gam::gam(wage ~ gam::s(year,4) + gam::s(age,5) + education,        data=Wage) 
Warning message:
In model.matrix.default(mt, mf, contrasts) :
  non-list contrasts argument ignored
> gam.m3.orig <- gam(wage ~ s(year,4) + s(age,5) + education, data=Wage)
Warning message:
In model.matrix.default(mt, mf, contrasts) :
  non-list contrasts argument ignored
> 
> #Coefficients are different
> coef(gam.m3)[1]; coef(gam.m3.orig)[1] 
(Intercept) 
  -2058.077 
(Intercept) 
  -2339.364 
> 
> #Models are different
> gam.m3$df.residual; gam.m3.orig$df.residual
[1] 2993
[1] 2986

person TimW    schedule 04.06.2019    source источник


Ответы (1)


gam вызывает gam.fit и gam.fit имеет специальный код для обработки сглаживания. Этот код работает правильно только в том случае, если в атрибуте "terms" атрибута model.frame они правильно указаны в его атрибуте "specials". В остальном сглаживания обрабатываются так же, как и с любой другой функцией, что, по-видимому, дает другой результат. Если вы хотите узнать, как именно обрабатываются сглаживания по-разному, вам необходимо подробно изучить исходный код gam.fit.

По сути, это показывает решающую разницу между вашими двумя вызовами gam:

gam.smoothers()$slist
#[1] "s"      "lo"     "random"

attr(terms(wage ~ s(year,4) + s(age,5) + education, 
           specials = gam.smoothers()$slist), "specials")
#$s
#[1] 2 3
#
#$lo
#NULL
#
#$random
#NULL

attr(terms(wage ~  gam::s(year,4) + gam::s(age,5) + education, 
           specials = gam.smoothers()$slist), "specials")
#$s
#NULL
#
#$lo
#NULL
#
#$random
#NULL

Зачем нужно использовать gam::s? Вызов gam::gam должен быть достаточным, чтобы гарантировать, что вызывается правильная функция сглаживания (через поиск в пространстве имен):

gam::gam(wage ~ s(year,4) + s(age,5) + education,data=Wage)  

Изменить:

Хорошо, mgcv::s фактически маскирует gam::s на пути поиска. Один из подходов к решению этой проблемы можно найти здесь.

person Roland    schedule 07.06.2019
comment
Как оказалось, поскольку mgcv также имеет mgcv::s(), отсутствие указания gam::s() также вызывает проблемы, как описано в этот вопрос. (+1) хотя для указания, какая проблема вызвана использованием спецификатора пространства имен для s. - person duckmayr; 07.06.2019
comment
@duckmayr Я добавил туда ответ. - person Roland; 07.06.2019
comment
Отличный подход! Я скоро назначу награду, а по другому вопросу я связался с OP, чтобы указать им на ваше превосходное решение. - person duckmayr; 07.06.2019
comment
@Roland Это здорово, как и ваш ответ на мой другой вопрос. Я многому научился из этого. Когда-нибудь я могу попытаться отследить в коде, как работает glm.fit и почему он не читает gam::s так, как я хотел, но это дает мне больше, чем то, что мне нужно, чтобы продолжать двигаться. Спасибо, duckmayr, за то, что объявили о награде! - person TimW; 07.06.2019