在 R 泊松回归中将 CARET 与 GAM("gamSpline" 方法)一起使用

Using CARET together with GAM ("gamSpline" method) in R Poisson Regression

我正在尝试使用 caret 包来调整 gam 模型的 '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))

Explanation of the data : Cohort number is the time of arrival of the potential customer. N is the number of potential customer that arrived at that time. Conversion is the number out of those potential customer that 'converted' (bought something). Age is the age (time spent from arrival) of the cohort when conversion took place. For a given cohort there are fewer conversions as age grows. This effect follows a power law. But the total conversion rate of each cohort can also change slowly in time (cohort number). Thus I want a smoothing spline of the time variable in my model.

我可以拟合 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. 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. 我不确定为什么,但是 trainmethod = "gamSpline" 不喜欢在公式中放入函数(例如 log)。我认为这是因为此方法已经将 s() 函数应用于您的变量。这个问题可以通过更早地将日志应用于您的变量来解决。例如 df$N <- log(df$N)logN <- log(df$N) 并使用 logN 作为变量。当然,对 age 执行相同的操作。

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

希望这对您有所帮助。

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