如何在r

时间:2018-07-28 16:58:21

标签: r tree cross-validation rpart

我有比特币时间序列,我使用11个技术指标作为特征,并且我想对数据拟合回归树。据我所知,r中有2个可以创建回归树的函数,即rpart()和tree(),但是这两个函数似乎不合适。 rpart()使用k倍交叉验证来验证最佳成本复杂度参数cp,在tree()中,无法指定cp的值。

我知道cv.tree()通过交叉验证来寻找cp的最佳值,但是cv.tee()同样使用k倍交叉验证。由于我具有时间序列,因此具有时间依赖性,因此我不想使用k折交叉验证,因为k折交叉验证会将数据随机分为k折,使模型适合k-1折并进行计算MSE排在第k位,那么我的时间序列的序列显然被破坏了。

我找到了rpart()函数的一个参数,即xval,应该让我指定交叉验证的次数,但是当我查看xval = 0时rpart()函数调用的输出时,它似乎交叉验证未关闭。在下面,您可以看到我的函数调用和输出:

tree.model= rpart(Close_5~ M+ DSMA+ DWMA+ DEMA+ CCI+ RSI+ DKD+ R+ FI+ DVI+ 
OBV, data= train.subset, method= "anova", control= 
rpart.control(cp=0.01,xval= 0, minbucket = 5))

> summary(tree.model)
Call:
rpart(formula = Close_5 ~ M + DSMA + DWMA + DEMA + CCI + RSI + 
DKD + R + FI + DVI + OBV, data = train.subset, method = "anova", 
control = rpart.control(cp = 0.01, xval = 0, minbucket = 5))
n= 590 

           CP nsplit rel error
1  0.35433076      0 1.0000000
2  0.10981049      1 0.6456692
3  0.06070669      2 0.5358587
4  0.04154720      3 0.4751521
5  0.02415633      5 0.3920576
6  0.02265346      6 0.3679013
7  0.02139752      8 0.3225944
8  0.02096500      9 0.3011969
9  0.02086543     10 0.2802319
10 0.01675277     11 0.2593665
11 0.01551861     13 0.2258609
12 0.01388126     14 0.2103423
13 0.01161287     15 0.1964610
14 0.01127722     16 0.1848482
15 0.01000000     18 0.1622937

似乎rpart()交叉验证了15个不同的cp值。如果通过k倍交叉验证对这些值进行了测试,那么我的时间序列的序列将再次被破坏,我基本上无法使用这些结果。有谁知道我如何才能有效地关闭rpart()中的交叉验证,或者如何更改tree()中cp的值?

更新:我遵循了一位同事的建议,并设置xval = 1,但这似乎并不能解决问题。当xval = 1 here时,您可以看到完整功能的输出。顺便说一句,parameters [j]是参数向量的第j个元素。当我调用此函数时,参数[j] = 0.0009765625

非常感谢

2 个答案:

答案 0 :(得分:1)

为了证明rpart()通过遍历cp的下降值而不是重采样来创建树节点,我们将使用Ozone包中的mlbench数据进行比较{OP的注释中讨论的rpart()caret::train()的结果。我们将按照Support Vector Machines的CRAN文档中的说明设置臭氧数据,该数据支持非线性回归并且可以与rpart()进行比较。

library(rpart)
library(caret)
data(Ozone, package = "mlbench")
# split into test and training
index <- 1:nrow(Ozone)
set.seed(01381708)
testIndex <- sample(index, trunc(length(index) / 3))
testset <- na.omit(Ozone[testIndex,-3])
trainset <- na.omit(Ozone[-testIndex,-3])


# rpart version
set.seed(95014) #reset seed to ensure sample is same as caret version
rpart.model <- rpart(V4 ~ .,data = trainset,xval=0)
# summary(rpart.model)
# calculate RMSE
rpart.pred <- predict(rpart.model, testset[,-3])
crossprod(rpart.pred - testset[,3]) / length(testIndex)

...以及RMSE计算的输出:

> crossprod(rpart.pred - testset[,3]) / length(testIndex)
         [,1]
[1,] 18.25507

接下来,我们将根据对OP的评论中的建议,对caret::train()进行相同的分析。

# caret version
set.seed(95014)
rpart.model <- caret::train(x = trainset[,-3],
                            y = trainset[,3],method = "rpart", trControl = trainControl(method = "none"), 
                            metric = "RMSE", tuneGrid = data.frame(cp=0.01), 
                            preProcess = c("center", "scale"), xval = 0, minbucket = 5)
# summary(rpart.model)
# demonstrate caret version did not do resampling
rpart.model
# calculate RMSE, which matches RMSE from rpart() 
rpart.pred <- predict(rpart.model, testset[,-3])
crossprod(rpart.pred - testset[,3]) / length(testIndex)

当我们打印来自caret::train()的模型输出时,它清楚地指出没有重新采样。

> rpart.model
CART 

135 samples
 11 predictor

Pre-processing: centered (9), scaled (9), ignore (2) 
Resampling: None

caret::train()版本的RMSE与rpart()中的RMSE相匹配。

> # calculate RMSE, which matches RMSE from rpart() 
> rpart.pred <- predict(rpart.model, testset[,-3])
> crossprod(rpart.pred - testset[,3]) / length(testIndex)
         [,1]
[1,] 18.25507
> 

结论

首先,如上所述,caret::train()rpart()都没有重新采样。但是,如果有人打印模型输出,则会通过两种技术使用cp的多个值来生成47个节点的最终树。

插入符号summary(rpart.model)的输出

          CP nsplit rel error
1 0.58951537      0 1.0000000
2 0.08544094      1 0.4104846
3 0.05237152      2 0.3250437
4 0.04686890      3 0.2726722
5 0.03603843      4 0.2258033
6 0.02651451      5 0.1897648
7 0.02194866      6 0.1632503
8 0.01000000      7 0.1413017

rpart summary(rpart.model)的输出

          CP nsplit rel error
1 0.58951537      0 1.0000000
2 0.08544094      1 0.4104846
3 0.05237152      2 0.3250437
4 0.04686890      3 0.2726722
5 0.03603843      4 0.2258033
6 0.02651451      5 0.1897648
7 0.02194866      6 0.1632503
8 0.01000000      7 0.1413017

第二,两个模型都通过包含monthday变量作为自变量来考虑时间值。在Ozone数据集中,V1是月份变量,V2是日期变量。所有数据都是在1976年收集的,因此数据集中没有年份变量,在svm小插图中的原始分析中,在分析之前删除了星期几。

第三,要在日期属性未用作模型特征时使用rpart()svm()之类的算法来考虑其他基于时间的效应,则必须将滞后效应作为模型中的特征包括在内,因为这些算法不直接考虑时间成分。 Ensemble Regression Trees for Time Series Predictions是一个使用一系列滞后值的回归树集成方法的示例。

答案 1 :(得分:0)

在模型中,只需xval=0,即可关闭交叉验证。

在输出中,您只有CP NSPLIT REL ERROR,使用交叉定值时,您应该有CP NSPLIT REL ERROR XERROR XSTD

cp只是您的“复杂度参数”(默认为cp = 0.01),范围是1至0.01。

rel error是您的数据集训练中的预测错误/根节点的预期损失。

nsplit根据cp在树的大小上相对的节点数。

外观:https://cran.r-project.org/web/packages/rpart/vignettes/longintro.pdf