RandomForestとクラスの重み


11

一文の質問:誰かがランダムなフォレストの適切なクラスの重みを決定する方法を知っていますか?

説明:私は不均衡なデータセットで遊んでいます。このRパッケージを使用して、randomForestポジティブな例がほとんどなく、ネガティブな例が多い、非常にゆがんだデータセットでモデルをトレーニングします。他にも方法はありますが、最終的にはそれらを利用しますが、技術的な理由から、ランダムフォレストの構築は中間段階です。そこで、パラメータをいじってみましたclasswt。半径2のディスクに5000の負の例の非常に人工的なデータセットを設定し、半径1のディスクに100の正の例をサンプリングします。

1)クラスの重み付けを行わないと、モデルは「退化」しFALSEます。つまり、どこでも予測されます。

2)公平なクラスの重み付けを使用すると、中央に「緑色の点」が表示されます。つまり、TRUE負の例があるように、半径1のディスクを予測します。

データは次のようになります。

ここに画像の説明を入力してください

これは、重み付けせずに何が起こるかである:(呼び出しは次のとおりです。randomForest(x = train[, .(x,y)],y = as.factor(train$z),ntree = 50)

ここに画像の説明を入力してください

チェックのために、関係が再び1:1になるように、負のクラスをダウンサンプリングしてデータセットを激しくバランス調整したときに何が起こるかを試しました。これは私に期待される結果を与えます:

ここに画像の説明を入力してください

ただし、クラスの重みが「FALSE」= 1、「TRUE」= 50のモデルを計算すると(これは、正の50倍のネガティブがあるため、これは適切な重みです)、次のようになります。

ここに画像の説明を入力してください

重みを 'FALSE' = 0.05や 'TRUE' = 500000などの奇妙な値に設定した場合のみ、意味のある結果が得られます。

ここに画像の説明を入力してください

そして、これは非常に不安定です。つまり、「FALSE」の重みを0.01に変更すると、モデルは再び縮退します(つまり、TRUEどこでも予測されます)。

質問:ランダムフォレストの適切なクラスの重みを決定する方法を誰かが知っていますか?

Rコード:

library(plot3D)
library(data.table)
library(randomForest)
set.seed(1234)
amountPos = 100
amountNeg = 5000

# positives
r = runif(amountPos, 0, 1)
phi = runif(amountPos, 0, 2*pi)
x = r*cos(phi)
y = r*sin(phi)
z = rep(T, length(x))
pos = data.table(x = x, y = y, z = z)

# negatives
r = runif(amountNeg, 0, 2)
phi = runif(amountNeg, 0, 2*pi)
x = r*cos(phi)
y = r*sin(phi)
z = rep(F, length(x))
neg = data.table(x = x, y = y, z = z)

train = rbind(pos, neg)

# draw train set, verify that everything looks ok
plot(train[z == F]$x, train[z == F]$y, col="red")
points(train[z == T]$x, train[z == T]$y, col="green")
# looks ok to me :-)

Color.interpolateColor = function(fromColor, toColor, amountColors = 50) {
  from_rgb = col2rgb(fromColor)
  to_rgb = col2rgb(toColor)

  from_r = from_rgb[1,1]
  from_g = from_rgb[2,1]
  from_b = from_rgb[3,1]

  to_r = to_rgb[1,1]
  to_g = to_rgb[2,1]
  to_b = to_rgb[3,1]

  r = seq(from_r, to_r, length.out = amountColors)
  g = seq(from_g, to_g, length.out = amountColors)
  b = seq(from_b, to_b, length.out = amountColors)

  return(rgb(r, g, b, maxColorValue = 255))
}
DataTable.crossJoin = function(X,Y) {
  stopifnot(is.data.table(X),is.data.table(Y))
  k = NULL
  X = X[, c(k=1, .SD)]
  setkey(X, k)
  Y = Y[, c(k=1, .SD)]
  setkey(Y, k)
  res = Y[X, allow.cartesian=TRUE][, k := NULL]
  X = X[, k := NULL]
  Y = Y[, k := NULL]
  return(res)
}

drawPredictionAreaSimple = function(model) {
  widthOfSquares = 0.1
  from = -2
  to = 2

  xTable = data.table(x = seq(from=from+widthOfSquares/2,to=to-widthOfSquares/2,by = widthOfSquares))
  yTable = data.table(y = seq(from=from+widthOfSquares/2,to=to-widthOfSquares/2,by = widthOfSquares))
  predictionTable = DataTable.crossJoin(xTable, yTable)
  pred = predict(model, predictionTable)
  res = rep(NA, length(pred))
  res[pred == "FALSE"] = 0
  res[pred == "TRUE"] = 1
  pred = res
  predictionTable = predictionTable[, PREDICTION := pred]
  #predictionTable = predictionTable[y == -1 & x == -1, PREDICTION := 0.99]
  col = Color.interpolateColor("red", "green")

  input = matrix(c(predictionTable$x, predictionTable$y), nrow = 2, byrow = T)
  m = daply(predictionTable, .(x, y), function(x) x$PREDICTION)
  image2D(z = m, x = sort(unique(predictionTable$x)), y = sort(unique(predictionTable$y)), col = col, zlim = c(0,1))
}


rfModel = randomForest(x = train[, .(x,y)],y = as.factor(train$z),ntree = 50)
rfModelBalanced = randomForest(x = train[, .(x,y)],y = as.factor(train$z),ntree = 50, classwt = c("FALSE" = 1, "TRUE" = 50))
rfModelBalancedWeird = randomForest(x = train[, .(x,y)],y = as.factor(train$z),ntree = 50, classwt = c("FALSE" = 0.05, "TRUE" = 500000))


drawPredictionAreaSimple(rfModel)
title("unbalanced")
drawPredictionAreaSimple(rfModelBalanced)
title("balanced with weights")
pos = train[z == T]
neg = train[z == F]
neg = neg[sample.int(neg[, .N], size = 100, replace = FALSE)]
trainSampled = rbind(pos, neg)
rfModelBalancedSampling = randomForest(x = trainSampled[, .(x,y)],y = as.factor(trainSampled$z),ntree = 50)
drawPredictionAreaSimple(rfModelBalancedSampling)
title("balanced with sampling")


drawPredictionAreaSimple(rfModelBalancedWeird)
title("balanced with weird weights")

sampsizeが機能する場合、なぜそれを使用しないのですか?他の人と同様に、sampsizeはこれを解決するのに適しています。また、ここでは偉大な答えを見るstats.stackexchange.com/questions/157714/...
カティア

daplyはplyrにあります。それを呼び出す必要があります。
EngrStudent 2017年

classwtクラスの事前知識。合計する必要はありません。回帰では無視されます。
ディエゴ

@ディエゴ:このパラメーターは非常に問題があるようです。このパラメーターの動作がわかりません(質問のコメントを参照してください)...
Fabian Werner

回答:


2

ハードメンバーシップを分類するためにハードカットオフを使用しないでください。また、このようなハードメンバーシップの予測に依存するKPIを使用しないでください。代わりに、を使用して確率的予測を処理しpredict(..., type="prob")、適切なを使用してこれらを評価し

この以前のスレッドは役に立ちます:なぜ正確さが分類モデルを評価するための最良の尺度ではないのですか?当然のことながら、私の回答、以前の私の回答と同様に特に役立つ(恥知らずで申し訳ない)と思います。


1
これが今日お話ししたトピックですね。私は私の仕事でこれに気をつけます:-)
Jonas Heidelberg
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.