在R泊松回归中使用CARET和GAM(" gamSpline"方法)

时间:2016-07-25 08:30:50

标签: r regression r-caret poisson gam

我正在尝试使用插入包调整' df'我的队列分析的gam模型的参数。

使用以下数据:

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包中找到一个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  .....

请问有谁知道我在这里做错了吗?

由于

1 个答案:

答案 0 :(得分:3)

您的代码有两个问题。

  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作为变量。当然,为s()做同样的事情。

  3. 我的猜测是,您不希望此方法根据您提供的代码将平滑术语应用于所有自变量。如果可能的话,我不确定这是否可行以及如何做到这一点。

    希望这有帮助。

    编辑:如果你想要比我在第2点提供的解决方案更优雅的解决方案,请务必阅读@topepo的评论。如果我理解正确的话,此建议还允许您将{{1}}函数应用于您想要的变量。