web-dev-qa-db-ja.com

非常に不均衡なクラスを持つランダムフォレスト

非常にアンバランスな応答クラスを持つビッグデータ問題でランダムフォレストを使用しているので、ドキュメントを読んだところ、次のパラメーターが見つかりました。

strata 

sampsize

これらのパラメーターのドキュメントはまばらで(またはそれを見つけることができませんでした)、実装方法が本当にわかりません。私は次のコードを使用しています:

randomForest(x=predictors, 
             y=response, 
             data=train.data, 
             mtry=lista.params[1], 
             ntree=lista.params[2], 
             na.action=na.omit, 
             nodesize=lista.params[3], 
             maxnodes=lista.params[4],
             sampsize=c(250000,2000), 
             do.trace=100, 
             importance=TRUE)

応答は2つの可能な値を持つクラスで、最初のものが2番目よりも頻繁に表示されます(10000:1以上)。

list.paramsは、さまざまなパラメータを持つリストです(ええと!私は知っています...)

さて、質問は(再び)です:どうすれば 'strata'パラメータを使用できますか? sampsizeを正しく使用していますか?

そして最後に、次のエラーが発生することがあります。

Error in randomForest.default(x = predictors, y = response, data = train.data,  :
  Still have fewer than two classes in the in-bag sample after 10 attempts.

申し訳ありませんが、私が非常に多くの(そしておそらく愚かな)質問をしている場合...

18
nanounanue

不均衡の程度を1:10,000から1:100または1:10に減らすサンプリング方法を使用してみてください。また、生成されるツリーのサイズを小さくする必要があります。 (現時点では、これらは私が記憶からのみ繰り返すことを推奨していますが、海綿状の皮質よりも多くの権限を追跡できるかどうかを確認します。)

ツリーのサイズを小さくする1つの方法は、「ノードサイズ」を大きく設定することです。その程度の不均衡があると、ノードサイズを非常に大きくする必要がある場合があります(たとえば、5〜10,000)。これがrhelpのスレッドです: https://stat.ethz.ch/pipermail/r-help/2011-September/289288.html

質問の現在の状態では、sampsize=c(250000,2000),がありますが、sampsize = c(8000,2000)のようなものは、私の提案とより一致していると思います。 2000だけでサンプリングされたグループがないサンプルを作成していると思います。

7
42-

申し訳ありませんが、以前の回答にコメントを投稿する方法がわからないため、別の回答を作成します。

この問題は、データセットの不均衡が大きいことが原因であると考えられます(いずれかのクラスのケースが少なすぎます)。 RF=の各ツリーについて、アルゴリズムはこのツリーのトレーニングセットであるbootstrapサンプルを作成します。そして、クラスの1つの例が少なすぎる場合データセットでbootstrapサンプリングすると、1つのクラス(主要なクラス)のみの例が選択されます。したがって、1つのクラスの例だけでツリーを成長させることはできません。10には制限があるようですサンプリングの試みが失敗したため、不均衡の度合いを低い値(1:100または1:10)に減らすというDWinの命題は、最も合理的なものです。

4
DrDom

いくつかのオプションがあります。

データがたくさんある場合は、データのランダムなサンプルを取っておきます。 1つのセットでモデルを構築し、もう1つのセットを使用して、ROC曲線を使用してクラス確率の適切なカットオフを決定します。

マイノリティクラスのデータをアップサンプリングすることもできます。 SMOTEアルゴリズムが役立つ場合があります(関数については、以下のリファレンスとDMwRパッケージを参照してください)。

他の手法を使用することもできます。 rpart()および他のいくつかの関数では、エラーのコストが異なる可能性があるため、少数派クラスをより優先することができます。このタイプのrpart()モデルをバッグに入れて、ランダムフォレストが実行していることを概算できます。

kernlabパッケージのksvm()も不均衡なコストを使用する可能性があります(ただし、これを行うと、確率の見積もりは適切ではなくなります)。他の多くのパッケージには、事前設定を設定するための引数があります。これを調整して、マイノリティクラスをより強調することもできます。

最後に考えたのは、精度に基づいてモデルを最大化しても、どこにも到達できないということです(99.99%オフになる可能性があります)。キャレットは、Kappa統計に基づいてモデルを調整できます。これは、あなたのケースでははるかに良い選択です。

4
topepo

サンプルから観察結果を削除するという考えに同意しません。

代わりに、層別のサンプルを使用して、再サンプリングされるたびに各クラスの固定パーセンテージを設定することを検討してください。これは、キャレットパッケージを使用して実行できます。このようにして、トレーニングサンプルのサイズを小さくすることで観測を省略しません。クラスを過度に表現することはできませんが、各サブサンプルに代表的なサンプルがあることを確認します。

これが私が見つけた例です:

len_pos <- nrow(example_dataset[example_dataset$target==1,])
len_neg <- nrow(example_dataset[example_dataset$target==0,])

train_model <- function(training_data, labels, model_type, ...) {
  experiment_control <- trainControl(method="repeatedcv",
                                     number = 10,
                                     repeats = 2,
                                     classProbs = T,
                                     summaryFunction = custom_summary_function)
  train(x = training_data,
        y = labels,
        method = model_type,
        metric = "custom_score",
        trControl = experiment_control,
        verbose = F,
        ...)
}

# strata refers to which feature to do stratified sampling on.
# sampsize refers to the size of the bootstrap samples to be taken from each class. These samples will be taken as input
# for each tree. 

fit_results <- train_model(example_dataset
                           , as.factor(sprintf("c%d", as.numeric(example_dataset$target)))        
                           ,"rf"
                           ,tuneGrid = expand.grid(mtry = c( 3,5,10))
                           ,ntree=500
                           ,strata=as.factor(example_dataset$target)
                           ,sampsize = c('1'=as.integer(len_pos*0.25),'0'=as.integer(len_neg*0.8))
)
1
mmann1123