Использование CARET вместе с GAM (метод gamSpline) в регрессии Пуассона R

Я пытаюсь использовать пакет Caret для настройки параметра «df» игровой модели для моего когортного анализа.

Со следующими данными:

cohort = 1:60
age = 1:26
grid = data.frame(expand.grid(age = age, cohort = cohort))
size = data.frame(cohort = cohort, N = sample(100:150,length(cohort), replace = TRUE))
df = merge(grid, size, by = "cohort")

log_k = -3 + log(df$N) - 0.5*log(df$age) + df$cohort*(df$cohort-30)*(df$cohort-50)/20000 + runif(nrow(df),min = 0, max = 0.5)
df$conversion = rpois(nrow(df),exp(log_k))

Объяснение данных: номер когорты — это время прибытия потенциального клиента. N — количество потенциальных клиентов, пришедших в это время. Конверсия — это число тех потенциальных клиентов, которые «конвертировали» (купили что-то). Возраст — это возраст (время, прошедшее с момента прибытия) когорты, когда произошла конверсия. Для данной когорты с возрастом происходит меньше конверсий. Этот эффект подчиняется степенному закону. Но общий коэффициент конверсии каждой когорты также может медленно меняться во времени (номер когорты). Таким образом, мне нужен сглаживающий сплайн временной переменной в моей модели.

Могу подобрать игровую модель из пакета gam

library(gam)
fit = gam(conversion ~ log(N) + log(age) + s(cohort, df = 4), data = df, family = poisson)
fit
> Call:
> gam(formula = conversion ~ log(N) + log(age) + s(cohort, df = 4), 
> family = poisson, data = df)

> Degrees of Freedom: 1559 total; 1553 Residual
> Residual Deviance: 1869.943 

Но если я попытаюсь обучить модель с помощью пакета CARET

library(caret)
fitControl = trainControl(verboseIter = TRUE)
fit.crt = train(conversion ~ log(N) + log(age) + s(cohort,df),
            data = df, method = "gamSpline",
            trControl = fitControl, tune.length = 3, family = poisson)

Я получаю эту ошибку:

+ Resample01: df=1 
model fit failed for Resample01: df=1 Error in as.matrix(x) : object 'N' not found

- Resample01: df=1 
+ Resample01: df=2 
model fit failed for Resample01: df=2 Error in as.matrix(x) : object 'N' not found  .....

Пожалуйста, кто-нибудь знает, что я делаю неправильно здесь?

Спасибо


person Nick Mars    schedule 25.07.2016    source источник


Ответы (1)


В вашем коде две ошибки.

  1. Функция train может быть немного утомительной в зависимости от используемого вами метода (как вы заметили). В случае method = "gamSpline" функция train добавляет гладкое слагаемое к каждому независимому слагаемому в формуле. Таким образом, он преобразует ваши переменные в s(log(N), df), s(log(age) df) и в s(s(cohort, df), df). Ждать s(s(cohort, df), df) действительно не имеет смысла. Поэтому вы должны изменить s(cohort, df) на cohort.

  2. Не знаю почему, но train с method = "gamSpline" не любит, когда в формулу добавляются функции (например, log). Я думаю, это связано с тем, что этот метод уже применяет функции s() к вашим переменным. Эту проблему можно решить, применив лог ранее к вашим переменным. Например, df$N <- log(df$N) или logN <- log(df$N) и используйте logN в качестве переменной. И, конечно же, сделайте то же самое для age.

Я предполагаю, что вы не хотите, чтобы этот метод применял сглаживающий член ко всем вашим независимым переменным на основе предоставленного вами кода. Я не уверен, возможно ли это и как это сделать, если это возможно.

Надеюсь это поможет.

РЕДАКТИРОВАТЬ: Если вам нужно более элегантное решение, чем то, которое я предоставил в пункте 2, обязательно прочитайте комментарий @topepo. Это предложение также позволяет вам применять функцию s() к нужным вам переменным, если я правильно понимаю.

person StatMan    schedule 25.07.2016
comment
Проблема связана с тем, как формулы передаются из функции R в функцию R. MarcelG прав, и вам нужно будет использовать пользовательскую модель, чтобы делать то, что вы хочу. - person topepo; 25.07.2016
comment
Большое спасибо! Пункт 2 странный, но его можно легко исправить. Пункт 1, с другой стороны, я считаю хорошей идеей для улучшения метода! Спасибо еще раз! Мой комментарий был сделан до прочтения комментария Топепо. Спасибо за ваш комментарий - person Nick Mars; 25.07.2016
comment
@NickMars Нет проблем, приятель. Если на ваши вопросы дан полный ответ, не стесняйтесь принять ответ :) - person StatMan; 25.07.2016