我想使用Poisson glmnet对保险索赔计数进行建模。我手头的数据包含每份保单的索赔数量(这是响应变量),关于策略的一些特性(性别、地区等)以及政策的持续时间(以年为单位)。我想把对数持续时间作为一个补偿项,就像我们在精算学中通常做的那样。使用glmnet
包中的cv.glmnet
函数,它是直截了当:
library(tidyverse)
library(glmnet)
n <- 100
dat <- tibble(
nb_claims = rpois(n, lambda = 0.5),
duration = runif(n),
x1 = runif(n),
x2 = runif(n),
x3 = runif(n)
)
fit <- cv.glmnet(
x = dat %>% dplyr::select(x1, x2, x3) %>% as.matrix(),
y = dat %>% pull(nb_claims),
family = "poisson",
offset = dat %>% pull(duration) %>% log()
)
fit
然而,我的目标是使用caret
包中的train
函数来训练这个模型,因为它提供了许多优点,实际上,使用这个包,验证、预处理以及特征选择都要好得多,使用caret
训练一个基本的glmnet(没有偏移项)非常简单:
library(caret)
fit <- caret::train(
x = dat %>% dplyr::select(x1, x2, x3) %>% as.matrix(),
y = dat %>% pull(nb_claims),
method = "glmnet",
family = "poisson"
)
fit
我们可以天真地尝试在train
函数中添加offset
参数:
fit <- caret::train(
x = dat %>% dplyr::select(x1, x2, x3) %>% as.matrix(),
y = dat %>% pull(nb_claims),
method = "glmnet",
family = "poisson",
offset = dat %>% pull(duration) %>% log()
)
fit
不幸的是,这段代码抛出了错误Error : No newoffset provided for prediction, yet offset used in fit of glmnet
,这是因为caret::train
函数没有注意为predict.glmnet
函数中的newoffset
参数给予。
在这本书中,他们展示了如何通过修改caret::train
函数的源代码来向GLM模型添加偏移项。它工作得很完美。然而,predict.glm
函数与predict.glmnet
函数有很大不同,因为它没有newoffset
参数。我尝试修改caret::train
函数的源代码。但是我遇到了一些麻烦,因为我不太清楚这个函数是如何工作的。
2条答案
按热度按时间0dxa2lsx1#
执行此操作的简单方法是将
offset
列作为x
的一部分传递,并在每个fit
和predict
调用中作为x
的x
列(不是offset
)传递,而作为offset
/newoffset
传递与offset
对应的x
列。在下面的示例中,x的offest列也需要命名为“offset”,这可以相对容易地更改
要创建函数,我们只需使用以下代码中的许多部分:https://github.com/topepo/caret/blob/master/models/files/glmnet.R
glmnet是特殊的,因为它需要一个
loop
,其余的只是冲洗和reapeat从https://topepo.github.io/caret/using-your-own-model-in-train.html#illustrative-example-1-svms-with-laplacian-kernels将在全文中指定
family = "poisson"
,以将此采用代码从https://github.com/topepo/caret/blob/master/models/files/glmnet.R更改为所以
x[,colnames(x) != "offset"]
是x
,而offset
是x[,colnames(x) == "offset"]
出于某种原因,我不明白,但它不工作,没有
prob
插槽这不适用于插入符号中的预处理,因为我们将偏移作为特性之一传递。但是它适用于recipes,因为您可以通过selections定义要执行预处理功能的列。https://tidymodels.github.io/recipes/articles/Selecting_Variables.html
我还没有时间检查我的代码错误。如果有任何问题发生或如果有一个错误的地方,请评论。谢谢。
您还可以在插入符号github中发布一个问题,要求将此特性(offset/newoffset)添加到模型中
nhjlsmyf2#
我尝试了很多方法来改变模型信息,但都失败得很惨。下面我可以提出一个解决方案,可能不是最好的,但如果你的数据是明智的,它会让你到达某个地方。
在Poisson / negative binom..回归中,因子中的偏移被引入回归,您可以阅读更多here和here:
其中tx是偏移量。在glmnet中,可以为每个项引入一个惩罚因子,如果某项的惩罚因子为0,基本上不会惩罚它,它总是包含在内。我们可以将其用于偏移量,只有在使用有意义的数据集时才能看到这种效果(注意,在示例数据集中,偏移量是没有意义的数字)。
下面我使用来自MASS的保险索赔数据集:
现在使用插入符号,我将在没有任何训练的情况下拟合它,并使用从cv. glmnet中的拟合获得的相同lambda。您还应该注意的一点是,cv.glmnet经常使用lambda.1se而不是lambda.min:
我们可以看到预测的差异有多大: