ป่าสุ่มและน้ำหนักของชั้นเรียน


11

คำถามในประโยคเดียว: มีใครรู้วิธีกำหนดน้ำหนักชั้นดีสำหรับป่าสุ่มหรือไม่

คำอธิบาย: ฉันกำลังเล่นกับชุดข้อมูลที่ไม่สมดุล ฉันต้องการใช้RแพคเกจrandomForestเพื่อฝึกอบรมโมเดลบนชุดข้อมูลที่เบ้มากโดยมีตัวอย่างบวกเพียงเล็กน้อยและตัวอย่างเชิงลบจำนวนมาก ฉันรู้ว่ามีวิธีการอื่น ๆ และในที่สุดฉันจะใช้ประโยชน์จากพวกเขา แต่ด้วยเหตุผลทางเทคนิคการสร้างป่าสุ่มเป็นขั้นตอนกลาง classwtดังนั้นผมจึงเล่นรอบกับพารามิเตอร์ ฉันกำลังตั้งค่าชุดข้อมูลเทียมจำนวน 5,000 ตัวอย่างในแผ่นดิสก์ที่มีรัศมี 2 และจากนั้นฉันสุ่มตัวอย่างบวก 100 ตัวอย่างในแผ่นดิสก์ที่มีรัศมี 1 สิ่งที่ฉันสงสัยคือ

1) ถ้าไม่มีคลาสที่มีน้ำหนักโมเดลจะกลายเป็น 'เสื่อม' เช่นคาดการณ์FALSEทุกที่

2) ด้วยการถ่วงน้ำหนักชั้นเรียนที่เป็นธรรมฉันจะเห็น 'จุดสีเขียว' ที่อยู่ตรงกลางนั่นคือมันจะทำนายแผ่นดิสก์ด้วยรัศมี 1 ราวกับว่าTRUEมีตัวอย่างเชิงลบ

นี่คือข้อมูลที่มีลักษณะ:

ป้อนคำอธิบายรูปภาพที่นี่

นี่คือสิ่งที่เกิดขึ้นโดยไม่ต้องถ่วงน้ำหนัก: (การโทรคือ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/…
katya

daply อยู่ใน plyr คุณควรเรียกมันว่า
EngrStudent

classwt Priors ของคลาส ไม่จำเป็นต้องเพิ่มขึ้นอีกหนึ่งรายการ ไม่สนใจการถดถอย
Diego

@Diego: พารามิเตอร์นี้ดูเหมือนว่าจะเป็นปัญหามากผมไม่เข้าใจวิธีการนี้จะทำงานพารามิเตอร์ (ดูการแสดงความคิดเห็นในคำถาม!) ...
เคลเวอร์เนอร์

คำตอบ:


2

อย่าใช้ตัวเลือกที่ยากต่อการจำแนกประเภทสมาชิกภาพและอย่าใช้ตัวชี้วัดที่ขึ้นอยู่กับการคาดการณ์สมาชิกภาพแบบแข็ง แต่การทำงานที่มีการคาดการณ์น่าจะใช้predict(..., type="prob")และประเมินการใช้ที่เหมาะสมเหล่านี้ให้คะแนนกฎ

หัวข้อก่อนหน้านี้ควรมีประโยชน์: เหตุใดความแม่นยำจึงไม่ใช่วิธีที่ดีที่สุดในการประเมินแบบจำลองการจำแนกประเภท แปลกใจพอผมเชื่อว่าคำตอบของฉันจะเป็นประโยชน์อย่างยิ่ง (ขออภัยสำหรับไร้ยางอาย) เช่นจะคำตอบก่อนหน้านี้ของฉัน


1
นี่คือหัวข้อที่คุณพูดถึงวันนี้ใช่ไหม ฉันจะระวังเรื่องนี้ในที่ทำงาน :-)
Jonas Heidelberg
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.