RandomForest ve sınıf ağırlıkları


11

Bir cümlede soru: Birisi rastgele bir orman için iyi sınıf ağırlıklarının nasıl belirleneceğini biliyor mu?

Açıklama: Dengesiz veri kümeleriyle oynuyorum. RPaketi randomForest, çok az pozitif örnek ve çok sayıda negatif örnekle çok çarpık bir veri kümesi üzerinde bir model eğitmek için kullanmak istiyorum . Biliyorum, başka yöntemler var ve sonunda bunları kullanacağım ama teknik nedenlerden dolayı rastgele bir orman inşa etmek ara bir adımdır. Bu yüzden parametre ile oynadım classwt. Yarıçap 2 olan diskte 5000 negatif örneğin çok yapay bir veri kümesini ayarlıyorum ve daha sonra yarıçap 1 olan diskte 100 pozitif örnek veriyorum.

1) sınıf ağırlığı olmadan model 'dejenere' olur, yani FALSEher yerde tahmin eder .

2) adil bir sınıf ağırlığı ile ortada bir 'yeşil nokta' göreceğim, yani TRUEnegatif örnekler varmış gibi yarıçap 1 ile diski tahmin edecektir .

Veriler şöyle görünür:

resim açıklamasını buraya girin

Bu ağırlık olmadan olur: (çağrısıdır: randomForest(x = train[, .(x,y)],y = as.factor(train$z),ntree = 50))

resim açıklamasını buraya girin

Kontrol için de, ilişkiyi tekrar 1: 1 olacak şekilde negatif sınıfı altörnekleyerek veri kümesini şiddetle dengelediğimde ne olduğunu denedim. Bu bana beklenen sonucu verir:

resim açıklamasını buraya girin

Ancak, 'YANLIŞ' = 1, 'DOĞRU' = 50 sınıf ağırlığı olan bir modeli hesapladığımda (pozitiflerden 50 kat daha fazla negatif olduğu için bu adil bir ağırlıktır) o zaman bunu elde ederim:

resim açıklamasını buraya girin

Sadece ağırlıkları 'YANLIŞ' = 0.05 ve 'DOĞRU' = 500000 gibi garip bir değere ayarladığımda anlamlı sonuçlar elde ederim:

resim açıklamasını buraya girin

Ve bu oldukça kararsızdır, yani 'YANLIŞ' ağırlığın 0.01 olarak değiştirilmesi, modeli tekrar dejenere eder (yani TRUEher yerde tahmin eder ).

Soru: Birisi rastgele bir orman için iyi sınıf ağırlıklarının nasıl belirleneceğini biliyor mu?

R kodu:

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")

eğer örnekleme çalışıyorsa neden kullanmıyorsunuz? Ayrıca, örneklemenin bunu çözmek için daha iyi çalıştığını ve diğerleri gibi buldum. Ayrıca burada harika bir cevap bakın stats.stackexchange.com/questions/157714/…
katya

daply plyr'de, bunu aramalısın.
EngrStudent

classwt Sınıfların öncelikleri. En fazla bir tane eklemeniz gerekmez. Regresyon için yok sayıldı.
Diego

@Diego: Bu parametre çok sorunlu gibi görünüyor, bu parametrenin nasıl davrandığını anlamıyorum (sorudaki yorumlara bakın!) ...
Fabian Werner

Yanıtlar:


2

Zor bir üyeliği sınıflandırmak için zor bir kesim kullanmayın ve bu kadar zor bir üyelik tahminine dayanan KPI'ları kullanmayın. Bunun yerine, olasılıksal bir tahminde çalışın predict(..., type="prob"), bunları kullanarak ve uygun kullanarak değerlendirin .

Bu önceki iş parçacığı yararlı olmalıdır: Doğruluk neden sınıflandırma modellerini değerlendirmek için en iyi ölçü değildir? Şaşırtıcı olmayan bir şekilde, cevabımın daha önceki bir cevabım gibi özellikle yararlı olacağını düşünüyorum (utanmazlık için özür dilerim) .


1
bugün bahsettiğiniz konu bu, değil mi? İşimde bunun için bakacağım :-)
Jonas Heidelberg
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.