1. ホーム
  2. r

[解決済み] rpart()でkフォールドクロスバリデーションをOFFにする方法

2022-02-12 09:31:42

質問

Bitcoinの時系列データで、11種類のテクニカル指標を特徴量として使用し、回帰木に当てはめたいと考えています。rpart()はk-foldクロスバリデーションで最適なコスト複雑性パラメータcpを検証していますが、tree()ではcpの値を指定することができません。

cv.tree() がクロスバリデーションで cp の最適値を探すことは知っていますが、やはり cv.tee() は k-fold cross validation を使っていますね。なぜなら、k-foldクロスバリデーションはデータをランダムにk-foldに分割し、k-1foldにモデルを当てはめ、残ったk-foldでMSEを計算するので、時系列の順序が明らかに崩れてしまうからです。

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-foldクロスバリデーションで検証した場合、やはり私の時系列のシーケンスは台無しになり、この結果は基本的に使えません。どなたか、rpart()のクロスバリデーションを効果的にオフにする方法や、tree()でcpの値を変化させる方法をご存じないでしょうか?

UPDATE: 同僚の一人の提案に従い、xval=1 としましたが、問題は解決しなかったようです。xval=1のときの関数の全出力を見ることができます。 こちら . ちなみに、parameters[j]はパラメータ・ベクトルのj番目の要素です。この関数を呼び出すと、parameters[j]=0.0009765625となります。

よろしくお願いします。

解決方法は?

ということを示すために rpart() の値の減少を繰り返し、ツリーノードを作成しています。 cp 対して、リサンプリングでは Ozone のデータを mlbench パッケージの結果を比較するために rpart()caret::train() をOPのコメントで説明したとおりです。の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

次に、同じ解析を caret::train() OPのコメントで提案されているように

# 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

のRMSEは caret::train() のRMSEと一致する。 rpart() .

> # 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() 日付属性がモデルの特徴として使用されない場合、これらのアルゴリズムは時間成分を直接的に考慮しないため、ラグ効果をモデルの特徴として含める必要があります。ラグ値の範囲を使用する回帰木のアンサンブルでこれを行う方法の一例は、次のとおりである。 時系列予測のためのアンサンブル回帰木 .