我想计算使用tidymodels工作流程创建的模型的FIRM重要性得分。对于示例,我将使用iris数据集,并尝试预测一个观测值是否为setosa。
library(tidymodels)library(readr)library(vip)#清理数据iris <- iris %>% mutate(class = case_when(Species == 'setosa' ~ 'setosa', TRUE ~ 'other'))iris$class = as.factor(iris$class)iris <- subset(iris, select = -c(Species))#将数据分割成训练集和测试集iris_split = initial_split(iris, prop = 0.8)cv_splits = vfold_cv(training(iris_split), v = 5)#预处理iris_recipe = recipe(class ~., data = iris) %>% step_center(Sepal.Length) %>% prep()#指定MARS模型model = rand_forest( mode = "classification", mtry = tune(), trees = 50) %>% set_engine("ranger", importance = "impurity")#调参tuning_grid = grid_regular(mtry(range=c(1,4)), levels = 4)iris_wkfl = workflow() %>% add_recipe(iris_recipe) %>% add_model(model) iris_tune = tune_grid(iris_wkfl, resamples = cv_splits, grid = tuning_grid, metrics = metric_set(accuracy))best_params = iris_tune %>% select_best(metric = "accuracy")best_model = finalize_workflow(iris_wkfl, best_params) %>% parsnip::fit(data = training(iris_split)) %>% pull_workflow_fit()vip(best_model, method = "firm")
最后一行产生了来自pdp包的错误。
在get_training_data.default(object)中出现错误:无法从对象中提取训练数据。请使用partial
调用中的train
参数提供原始训练数据。
以下这行代码是否正确?或者我是否需要先提供使用我的配方转换过的训练数据?我想确保vip在计算重要性得分时应用了我的配方。我知道错误信息中提到“原始训练数据”,但我不确定pdp是否了解我的工作流程。
vip(best_model, method = "firm", train = training(iris_split))
回答:
你应该采用我在这个回答中概述的方法。
首先调整然后在训练数据上训练你的模型:
library(tidymodels)#清理数据iris = iris %>% mutate(class = case_when(Species == 'setosa' ~ 'setosa', TRUE ~ 'other'), class = factor(class)) %>% select(-Species)#将数据分割成训练集和测试集iris_split = initial_split(iris, prop = 0.8)iris_train = training(iris_split)iris_test = testing(iris_split)cv_splits = vfold_cv(iris_train, v = 5)#预处理iris_recipe = recipe(class ~., data = iris_train) %>% step_center(Sepal.Length)#指定ranger模型rf_spec = rand_forest( mode = "classification", mtry = tune(), trees = 50) %>% set_engine("ranger", importance = "impurity") ## 如果你将以另一种方式进行重要性计算,这里不需要任何重要性;可能需要移除#调参tuning_grid = grid_regular(mtry(range=c(1,4)), levels = 4)iris_wkfl = workflow() %>% add_recipe(iris_recipe) %>% add_model(rf_spec) iris_tune = tune_grid(iris_wkfl, resamples = cv_splits, grid = tuning_grid, metrics = metric_set(accuracy))#> #> 正在附加包: 'rlang'#> 下列对象从 'package:purrr' 中被屏蔽:#> #> %@%, as_function, flatten, flatten_chr, flatten_dbl, flatten_int,#> flatten_lgl, flatten_raw, invoke, list_along, modify, prepend,#> splice#> #> 正在附加包: 'vctrs'#> 下列对象从 'package:tibble' 中被屏蔽:#> #> data_frame#> 下列对象从 'package:dplyr' 中被屏蔽:#> #> data_framebest_params = iris_tune %>% select_best(metric = "accuracy")rf_fit = finalize_workflow(iris_wkfl, best_params) %>% fit(data = iris_train)
现在你的模型已经训练好了,你可以计算像FIRM这样的模型无关的变量重要性得分。需要执行几个步骤:
- 你需要从工作流程中
pull()
出拟合的模型。 - 你必须指定目标/结果变量,
class
。 - 在这种情况下,我们需要传递原始训练数据(你必须在这里使用预处理过的训练数据,你可以从配方中获取)和ranger用于预测的正确底层函数(对于大多数模型这是
predict()
,但不幸的是对于ranger它是predictions()
)。
library(vip)#> #> 正在附加包: 'vip'#> 下列对象从 'package:utils' 中被屏蔽:#> #> virf_fit %>% pull_workflow_fit() %>% vip(method = "firm", target = "class", metric = "accuracy", pred_wrapper = ranger::predictions, train = bake(prep(iris_recipe), new_data = NULL))
由reprex包(v0.3.0.9001)于2020-12-10创建