我们在之前的推文中已经给大家介绍了tidymodels
中的一些内容,包括:
工作流是tidymodels
中非常重要的概念,它可以把模型设定和预处理步骤(在tidymodels中称为配方)连接起来,成为一个整体的对象。
tidymodels
框架认为预处理和模型应该放在一起评估,不应该单独执行。放在一起有诸多好处,关于这里的细节,大家可以参考《Tidymodeling with R》。
我们在之前已经给大家介绍过了工作流的用法了,今天再介绍一下parsnip
,这也是tidymodels
的核心包之一,主要用来选择(创建)模型的。
parsnip
本身并不提供任何算法(模型),比如随机森林、逻辑回归、支持向量机等,而是为R语言中不同的机器学习R包(比如randomforest,glmnet,xgboost等)提供一个统一的接口,基于统一的使用语法进行建模。
大家都知道在R中做一件事可以有多种方法,比如要使用随机森林模型,我们可以选择randomforest
或者ranger
等R包。不同R包的参数名字、使用方法、需要的数据格式等等都是不一样的。这种R包之间的异质性严重影响大家的使用体验。
所以tidymodels
出手了,推出了parsnip
包,专门用来解决这些问题。它是基于tidy
理念开发,给出统一的参数名和使用方法,统一数据类型,并且建模结果和预测结果也是统一的格式和列名。
下面我们来演示。
2选1即可:
# The easiest way to get parsnip is to install all of tidymodels:
install.packages("tidymodels")
# Alternatively, install just parsnip:
install.packages("parsnip")
R语言基础语法中,不同的R包有不同的语法,比如以下是3种可以实现随机森林模型的R包的使用语法:
# From randomForest
rf_1 <- randomForest(
y ~ .,
data = dat,
mtry = 10,
ntree = 2000,
importance = TRUE
)
# From ranger
rf_2 <- ranger(
y ~ .,
data = dat,
mtry = 10,
num.trees = 2000,
importance = "impurity"
)
# From sparklyr
rf_3 <- ml_random_forest(
dat,
intercept = FALSE,
response = "y",
features = names(dat)[names(dat) != "y"],
col.sample.rate = 10,
num.trees = 2000
)
除此之外,还有其他不方便的地方,比如说:
在parsnip
中,这些问题统统得到解决。首先是不同的R包选择问题,上面也说过了,parsnip
本身不能实现任何算法,但是能够使用可以实现这些算法的R包,作为引擎。
在parsnip
中,你只要选择好模型的类型,比如你要用随机森林,还是SVM,还是神经网络,还是正则化模型;然后选择模型的模式,比如回归还是分类?即可!
比如,假如我们要用随机森林做回归模型,我们想用ranger
包做,在parsnip
中的语法如下:
suppressMessages(library(tidymodels))
rf_spec <- rand_forest(mtry = 10, trees = 1000) %>%
set_engine("ranger") %>% # 选择引擎
set_mode("regression") # 选择模式
rf_spec
## Random Forest Model Specification (regression)
##
## Main Arguments:
## mtry = 10
## trees = 1000
##
## Computational engine: ranger
如果我不想使用ranger
,而是想用randomForest
呢?很简单,只要换引擎即可:
rf_spec <- rand_forest(mtry = 10, trees = 1000) %>%
set_engine("randomForest") %>% # 选择引擎
set_mode("regression") # 选择模式
rf_spec
## Random Forest Model Specification (regression)
##
## Main Arguments:
## mtry = 10
## trees = 1000
##
## Computational engine: randomForest
选择模型的过程与数据无关,而且在选择模型时需要做一些设置,比如使用哪个引擎?使用什么模式?哪些超参数需要调优?
所以在tidymodels
中,像rf_spec
这个对象就被称为模型设定。
除此之外,parsnip
把不同的超参数名称也统一了,比如上面的trees
就表示树的数量,在不同的R包中,这个参数的拼写可能不一样,但是在parsnip
中都是trees
。
R语言中绝大多数建模函数都是支持公式的,但也有一些例外(说的就是glmnet
),parsnip
也把这些全都统一了,不管底层的引擎用的是什么接口,在parsnip
中既可以用公式,也可以用x/y
的形式。
以下是使用parsnip
拟合模型的示例:
rf_fit <- rf_spec %>%
fit(mpg ~ ., data = mtcars)
rf_fit
## parsnip model object
##
##
## Call:
## randomForest(x = maybe_data_frame(x), y = y, ntree = ~1000, mtry = min_cols(~10, x))
## Type of random forest: regression
## Number of trees: 1000
## No. of variables tried at each split: 10
##
## Mean of squared residuals: 5.789713
## % Var explained: 83.55
试试glmnet
:
lasso_spec <- linear_reg(penalty = 0.1) %>%
set_engine("glmnet") %>%
set_mode("regression")
lasso_fit <- lasso_spec %>%
fit(mpg ~ ., data = mtcars)
lasso_fit
## parsnip model object
##
##
## Call: glmnet::glmnet(x = maybe_matrix(x), y = y, family = "gaussian")
##
## Df %Dev Lambda
## 1 0 0.00 5.1470
## 2 2 12.90 4.6900
## 3 2 24.81 4.2730
## 4 2 34.69 3.8940
## 5 2 42.90 3.5480
## 6 2 49.71 3.2320
## 7 2 55.37 2.9450
## 8 2 60.06 2.6840
## 9 2 63.96 2.4450
## 略
## 76 10 86.89 0.0048
## 77 10 86.89 0.0044
## 78 10 86.90 0.0040
## 79 10 86.90 0.0036
R语言里不同R包的预测结果五花八门,而且有些R包的predict()
函数有各种自己的选项,根本记不住。
parsnip
把这些也统一了。预测出来的格式都是一模一样的,列名也是一模一样的(非常有规律),完全不用担心不知道预测结果怎么用。
以下是一个示例:
test <- mtcars[1:10,]
rf_fit %>% predict(new_data = test)
## # A tibble: 10 × 1
## .pred
## <dbl>
## 1 20.9
## 2 20.9
## 3 24.2
## 4 20.2
## 5 17.8
## 6 18.8
## 7 14.7
## 8 23.7
## 9 22.8
## 10 18.7
预测结果中都有一个.pred
列,这一列是预测结果,对于分类模型还会有预测类别列和预测概率列,而且这个结果的行的顺序和原始数据的行的顺序也是完全一致的!
所以我们可以直接进行列连接:
test_pred <- test %>%
select(mpg) %>%
bind_cols(rf_fit %>% predict(new_data = test))
test_pred
## mpg .pred
## Mazda RX4 21.0 20.94531
## Mazda RX4 Wag 21.0 20.93802
## Datsun 710 22.8 24.17076
## Hornet 4 Drive 21.4 20.21766
## Hornet Sportabout 18.7 17.84907
## Valiant 18.1 18.76401
## Duster 360 14.3 14.74038
## Merc 240D 24.4 23.66752
## Merc 230 22.8 22.75649
## Merc 280 19.2 18.71179
对于另一个模型也是一模一样的用法和结果:
test_pred <- test %>%
select(mpg) %>%
bind_cols(lasso_fit %>% predict(new_data = test))
test_pred
## mpg .pred
## Mazda RX4 21.0 22.52575
## Mazda RX4 Wag 21.0 22.11111
## Datsun 710 22.8 26.44102
## Hornet 4 Drive 21.4 20.78967
## Hornet Sportabout 18.7 17.26803
## Valiant 18.1 20.32089
## Duster 360 14.3 14.58826
## Merc 240D 24.4 22.48821
## Merc 230 22.8 23.67817
## Merc 280 19.2 19.06079
这个结果一目了然,大家都知道是什么意思!你可以试试看默认的glmnet
的预测结果是啥,对比一下就知道parsnip
的便利之处了。
有了这样的结果,画图也是很简单:
ggplot(test_pred, aes(mpg, .pred))+
geom_point()+
geom_smooth(method = "lm")+
#coord_fixed()+
theme_bw()
## `geom_smooth()` using formula = 'y ~ x'
以上是parsnip
的简单介绍,更多内容我们以后慢慢介绍。
🔖精选合集