LoginSignup
2

More than 5 years have passed since last update.

The caret Package:4 Data Splittingの和訳

Last updated at Posted at 2016-03-20

訳注
http://topepo.github.io/caret/splitting.html の和訳です
図は訳者がRで再現を試みたものです。
日本語がおかしいところを改訳しました。また、4.4 Simple Splitting with Important Groupsが追加されたので訳も追加しました。


4.1 目的変数に基づく簡単な分割

createDataPartition 関数でバランスの取れたデータ分割が出来ます。もし属性yがファクター型ならば、ランダムサンプリングにおいてもデータ内のクラスの分布が保存される必要があります。例えば、 iris データを簡単に 80%と20%(訳注:トレーニングデータ80%、テストデータ20%)と分割する場合は:

library(caret)
set.seed(3456)
trainIndex <- createDataPartition(iris$Species, p = .8,
                                  list = FALSE,
                                  times = 1)
head(trainIndex)

     Resample1
[1,]         1
[2,]         2
[3,]         4
[4,]         5
[5,]         6
[6,]         8
irisTrain <- iris[ trainIndex,]
irisTest  <- iris[-trainIndex,]

list = FALSE はデータをリスト型で返されるのを避けるためです。この関数は属性として、times があり、1回に複数の分割をすることが出来ます; この場合は整数ベクトルのリストとして返されます。同様に、 createResample ではブートストラップサンプルを、 createFoleds ではクロスバリデーションによる分割が可能です。

4.2 説明変数に基づく分割

maxDissim 関数でも maximum dissimilarity approach (Willet, 1990) にてサブサンプルを作成可能です。サンプルセット A に m 個のサンプルがあり、より大きいサンプルセット B に n 個のサンプルがあるとします。B からサブサンプルを作るとき A より分散しているものとします。この場合、B のサンプルのそれぞれについて A における各点からの dissimilarities 行列を計算します。B の中で最も類似性の低い点を A に追加し、これを繰り返します。R では非類似性を計算する方法がたくさんあります。caret では proxy パッケージを用います。proxy パッケージのマニュアルを見てください、そこには多くの計測法があります。“most dissimilar” となるサンプルを計算する手法もたくさんあります。属性オブジェクトで、どの計測法の結果を返り値とするかを指定出来ます。caret には minDiss と sumDiss という2つの関数があり、それぞれ最小値の最大化と非類似性の合計を行います。

例として、Cox2 データに関する2つの化学記述子スキャッタープロットを見てみましょう。初期値として5つの化合物を用いてランダムサンプリングを行い、データセットから20以上の化合物を得ており、初期値としての5つの化合物よりも非類似性の高い新たな化合物となっています。図中の表には、距離と得点関数のいくつかの組み合わせから得られる結果を示しています。このデータに関しては、得点の手法よりも距離の計測法のほうが結果へのインパクトが小さくなっています。どの化合物が最も非類似度が高いかという点においては。

library(mlbench)
data(BostonHousing)

testing <- scale(BostonHousing[, c("age", "nox")])
set.seed(5)
## A random sample of 5 data points
startSet <- sample(1:dim(testing)[1], 5)
samplePool <- testing[-startSet,]
start <- testing[startSet,]
newSamp <- maxDissim(start, samplePool, n = 20)
head(newSamp)

[1] 461 406  49 308 469  76

下図では、データセット(小さな点)を示しており、初期サンプル(大きな青い点)と他の20サンプルの点を加えています。
data_splitting01.png
(訳注:訳者作図。乱数のseedを同じにしたはずだが、、、。描画コード例:)

library(ggplot2)
df<-data.frame(BostonHousing[, c("age", "nox")], rep('pool', 506)); names(df)[3]<-'class'
df[, 3]<-as.character(df[, 3])
df[startSet, 3]<-'Starting Set'
df[newSamp, 3]<-'Sampled'
g<-ggplot(df, aes(x = age, y = nox, color = class, size = class))
g<-g + geom_point() + scale_size_manual(values = c(1, 10, 5))
g<-g + scale_color_manual(values = c('black', 'red', 'blue'))

(訳注:終わり)

4.3 時系列データのデータ分割

時系列データからの単純なランダムサンプリングは最も良い方法とは言えません。 (Hyndman and Athanasopoulos (2013)) によれば、時間によりトレーニングとテストデータセットを移動させていく rolling forecasting origin テクニックが議論されています。caret には、この形式の分割を行う createTimeSlices 関数があります。

この形式の分割の3つのパラメータは:
* initialWindow:   それぞれのトレーニングセットサンプル内での連続値の初期値
* horizon:      テストセットサンプルの連続値
* fixedWindow:論理値: もし FALSE ならば、トレーニングセットは常に最初のサンプルから開始され、分割の間トレーニングセットのサイズは変わります。

例として、20個のデータポイントからなる時系列データを考えます。initialWindow = 5 とし、他の2つの属性設定を変えることによる変化を見ていきます。下図では、各表の行がデータの分割に対応しており(すなわち、リサンプル)、列がデータポイントに対応しています。赤はトレーニングセットを示しており、青はテストセットを示しています。

(訳注:図略)

4.4 Simple Splitting with Important Groups

サンプリング、リサンプリングにおいて定性要素が重要な場合がある。例えば:

  • 臨床試験において、病院間での差を見る
  • 長期的あるいは繰り返し計測したデータにおいて、subject(あるいは独立した実験単位)が複数行ある場合、など

There may be an interest in making sure that these groups are not contained in the training and testing set since this may bias the test set performance to be more optimistic. Also, when one or more specific groups are held out, the resampling might capture the “ruggedness” of the model. In the example where clinical data is recorded over multiple sites, the resampling performance estimates partly measure how extensible the model is across sites.
それらのグループをトレーニングセットにもテストセットにも含めないならば、より明示的にテストセットにバイアスを掛けることになる。また、1つ以上の特徴的なグループを除くのであれば、リサンプリングはモデルの「凸凹」をみてしまう。臨床試験データの例では、複数のサイト(訳注、病院のこと?)を含めて記録することで、リサンプリングのパフォーマンスがどれくらいサイト間に拡張可能かを見積もります。
(訳注、定性要素が重要な場合にはそれらすべてを漏らすことなくサブサンプルに含めないといけないよ、ってことだと思いますが訳ごめんなさい)

To split the data base don groups, groupKFold can be used:
グループに基づく(訳注、base don は based on のミススペルだと思われる)データ分割では、groupKFold を用いることができ:

set.seed(3527)
subjects <- sample(1:20, size = 80, replace = TRUE)
table(subjects)
## subjects
##  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 
##  3  5  4  3  2  6  4  6  3  5  5  3  5  6  4  4  7  1  3  1
folds <- groupKFold(subjects, k = 15) 

folds に代入された結果は、trainControl 関数の index 属性の入力として用いることが出来る。

以下のプロットは、モデリングとホールド・アウトセット間の分割を示している。k が20以下の場合の fold を示しており、1つ以上のホールド・アウトがある。

(訳注、図は略)

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2