梯度提升模型的变量重要性(以 50 天为间隔滚动)
Posted
技术标签:
【中文标题】梯度提升模型的变量重要性(以 50 天为间隔滚动)【英文标题】:Variable Importance (rolling in 50days interval) for Gradient Boosting Model 【发布时间】:2021-06-15 20:57:04 【问题描述】:我有以下数据表dt.train
,days
的数量和函数varImportance
,来得到一个线性模型的变量重要性:
library(data.table)
library(caret)
library(xgboost)
library(zoo)
days <- 50
set.seed(123)
dt.train <- data.table(date = seq(as.Date('2020-01-01'), by = '1 day', length.out = 366),
'DE' = rnorm(366, 30, 1), 'windDE' = rnorm(366, 10, 1),
'consumptionDE' = rnorm(366, 35, 1), 'nuclearDE' = rnorm(366, 8, 1),
'solarDE' = rnorm(366, 1, 1), check.names = FALSE)
## Variable Importance Function: ##
## LINEAR MODEL: ##
varImportance <- function(data)
## Model fitting: ##
xgbModel <- stats::lm(DE ~ .-1, data = data.table(data))
varimp <- caret::varImp(xgbModel)
importance <- t(varimp)
## Iterative Variable Importance for Linear Model: ##
dt.importance <- as.data.frame(zoo::rollapply(dt.train[, !"date"],
FUN = varImportance,
width = days,
by.column = FALSE,
align = 'left')
)
## Adding date-column again: ##
dt.importance <- cbind(dt.train[1:nrow(dt.importance), .(date)], dt.importance)
这里一切正常,但我需要为梯度提升机器学习模型做同样的事情。我已经尝试过以相同的方式进行操作,其中模型拟合的准备工作在 varImportance
函数中:
## Variable Importance function: ##
## GRADIENT BOOSTING: ##
varImportance <- function(data)
## Create response vector and predictor matrix: ##
v.trainY <- data$DE
m.trainData <- as.matrix(data[, c("date", "DE") := list(NULL, NULL)])
## Hyper parameter tuning and grid search: ##
xgb_trcontrol <- caret::trainControl(method = "cv",
number = 3,
allowParallel = TRUE,
verboseIter = TRUE,
returnData = FALSE
)
xgbgrid <- base::expand.grid(nrounds = c(150), # 15000
max_depth = c(2),
eta = c(0.01),
gamma = c(1),
colsample_bytree = c(1),
min_child_weight = c(2),
subsample = c(0.6)
)
## Model fitting: ##
xgbModel <- caret::train(m.trainData,
v.trainY,
trControl = xgb_trcontrol,
tuneGrid = xgbgrid,
method = "xgbTree"
)
varimp <- caret::varImp(xgbModel, scale = FALSE)
importance <- t(varimp$importance)
## Iterative Variable Importance for Gradient Boosting: ##
dt.importance <- as.data.frame(zoo::rollapply(dt.train,
FUN = varImportance,
width = days,
by.column = FALSE,
align = 'left')
)
## Adding date-column again: ##
dt.importance <- cbind(dt.train[1:nrow(dt.importance), .(date)], dt.importance)
不幸的是,这不能每 50 天迭代一次(抛出错误:$ operator is invalid for atomic vectors
)。 varImportance
函数中的 varImp()
在运行一次时适用于梯度提升模型。
编辑 1:
您的回答使用 Gradient Boosting 引发以下错误:
编辑 2:
当我评论 trControl = xgb_trcontrol
时,我收到以下错误:
【问题讨论】:
如果我理解正确的话,第一个计算应该是varImportance(dt.train[1:days])
。但是,这会返回错误。我错过了什么吗?
第一个计算应该来自1: days
,第二个来自2: days
,第三个来自3: days
,以此类推。这已经适用于线性模型,您可以尝试一下,然后应该清楚它的含义。我想对梯度提升做同样的事情,并且我已经尝试过了(如您在上面看到的),但是使用我的版本会引发错误。也许有人知道另一个版本以便它可以工作或如何解决这个问题?
感谢您的反馈。 “不”迭代地工作“可能会令人困惑,因为第一次迭代根本不起作用。第一步是在尝试迭代之前让 xgbMpdel 与 varImp 一起工作。
如果我为整个数据集拟合 xgbModel,然后我用varimp <- caret::varImp(xgbModel, scale = FALSE)
计算拟合模型的变量重要性,这很好。所以,varImp
工作正常,当它不与函数 varImportance
迭代使用时。
在我的系统上,varImportance(dt.train)
返回Non-tree model detected! This function can only be used with tree models.
【参考方案1】:
在使用一些 data.table 函数时,您需要将输入转换回 data.table。 rollapply 将输入作为矩阵发送。您应该注意,您的第一列是日期,当 rollapply 将数据子集转换为矩阵时,所有内容都将转换为字符类。
由于您不在函数中使用日期,因此最好在 rollapply 函数中发送数据之前删除此列。但是,如果要发送完整数据,则需要将所有内容从字符转换回数字。在下面的代码中,我只是在输入中删除日期列。
这是工作代码 -
library(data.table)
library(caret)
library(xgboost)
library(zoo)
days <- 50
set.seed(123)
dt.train <- data.table(date = seq(as.Date('2020-01-01'), by = '1 day', length.out = 366),
'DE' = rnorm(366, 30, 1), 'windDE' = rnorm(366, 10, 1),
'consumptionDE' = rnorm(366, 35, 1), 'nuclearDE' = rnorm(366, 8, 1),
'solarDE' = rnorm(366, 1, 1), check.names = FALSE)
## GRADIENT BOOSTING: ##
varImportance <- function(data)
data = data.table(data.frame(data))
## Create response vector and predictor matrix: ##
v.trainY <- data$DE
m.trainData <- as.matrix(data[, c("DE") := list(NULL)])
## Hyper parameter tuning and grid search: ##
xgb_trcontrol <- caret::trainControl(method = "cv",
number = 3,
allowParallel = TRUE,
verboseIter = TRUE,
returnData = FALSE
)
xgbgrid <- base::expand.grid(nrounds = c(150), # 15000
max_depth = c(2),
eta = c(0.3),
gamma = c(1),
colsample_bytree = c(1),
min_child_weight = c(2),
subsample = c(0.6)
)
## Model fitting: ##
xgbModel <- caret::train(m.trainData,
v.trainY,
trControl = xgb_trcontrol,
tuneGrid = xgbgrid,
method = "xgbTree" )
varimp <- caret::varImp(xgbModel, scale = FALSE)
importance <- t(varimp$importance)
## Iterative Variable Importance for Gradient Boosting: ##
dt.importance1 <- as.data.frame(zoo::rollapply(dt.train[,-1],
FUN = varImportance,
width = days,
by.column = FALSE,
align = 'left')
)
## Adding date-column again: ##
dt.importance <- cbind(dt.train[1:nrow(dt.importance1), .(date)], dt.importance1)
【讨论】:
感谢您的回答。我稍后会尝试一下。这是否也适用于多元自适应回归样条(= MARS),我在以下问题中提到过:link 并且具有与梯度提升相同的模型拟合约定。 使用答案中的代码会引发错误(请参阅上面的问题)。为什么它对你有效,但对我无效?错误信息是什么意思? 您收到“$ operator is invalid for atomic vectors”错误,因为 rollapply 无法正常工作。 第二个错误提示你不能对交叉验证的结果使用predict。在您的代码中注释 trControl = xgb_trcontrol 并重试。请参阅有关此主题的另一篇文章 - ***.com/questions/52007875/… 当我评论trControl = xgb_trcontrol
时,会产生以下警告/错误(请参阅我在问题中的第二次编辑)。以上是关于梯度提升模型的变量重要性(以 50 天为间隔滚动)的主要内容,如果未能解决你的问题,请参考以下文章
2万字阐述-Python 用 XGBoost 进行梯度提升的数据准备(收藏)