RandomForest và trọng lượng lớp


11

Câu hỏi trong một câu: Có ai biết cách xác định trọng số lớp tốt cho một khu rừng ngẫu nhiên không?

Giải thích: Tôi đang chơi xung quanh với các bộ dữ liệu mất cân bằng. Tôi muốn sử dụng Rgói randomForestđể đào tạo một mô hình trên bộ dữ liệu rất sai lệch chỉ với một vài ví dụ tích cực và nhiều ví dụ tiêu cực. Tôi biết, có những phương pháp khác và cuối cùng tôi sẽ sử dụng chúng nhưng vì lý do kỹ thuật, xây dựng một khu rừng ngẫu nhiên là một bước trung gian. Vì vậy, tôi chơi xung quanh với các tham số classwt. Tôi đang thiết lập một bộ dữ liệu nhân tạo gồm 5000 ví dụ tiêu cực trong đĩa có bán kính 2 và sau đó tôi lấy mẫu 100 ví dụ tích cực trong đĩa có bán kính 1. Điều tôi nghi ngờ là

1) không có trọng số lớp, mô hình trở nên 'suy biến', tức là dự đoán FALSEở mọi nơi.

2) với trọng số của lớp công bằng, tôi sẽ thấy một 'chấm xanh' ở giữa, tức là nó sẽ dự đoán đĩa có bán kính 1 như TRUEmặc dù có các ví dụ tiêu cực.

Đây là cách dữ liệu trông như thế nào:

nhập mô tả hình ảnh ở đây

Đây là những gì xảy ra mà không có trọng số: (gọi là randomForest(x = train[, .(x,y)],y = as.factor(train$z),ntree = 50):)

nhập mô tả hình ảnh ở đây

Để kiểm tra, tôi cũng đã thử những gì xảy ra khi tôi cân bằng dữ liệu dữ liệu bằng cách lấy mẫu lớp âm để mối quan hệ lại là 1: 1. Điều này mang lại cho tôi kết quả mong đợi:

nhập mô tả hình ảnh ở đây

Tuy nhiên, khi tôi tính toán một mô hình có trọng số lớp là 'FALSE' = 1, 'TRUE' = 50 (đây là một trọng số hợp lý vì có số âm hơn 50 lần so với số dương) thì tôi nhận được điều này:

nhập mô tả hình ảnh ở đây

Chỉ khi tôi đặt trọng số thành một số giá trị kỳ lạ như 'FALSE' = 0,05 và 'TRUE' = 500000 thì tôi mới nhận được kết quả hợp lý:

nhập mô tả hình ảnh ở đây

Và điều này khá không ổn định, tức là việc thay đổi trọng lượng 'FALSE' thành 0,01 khiến mô hình bị thoái hóa trở lại (tức là nó dự đoán TRUEở mọi nơi).

Câu hỏi: Có ai biết cách xác định trọng số lớp tốt cho một khu rừng ngẫu nhiên không?

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

Nếu sampize hoạt động tại sao không sử dụng? Tôi cũng tìm thấy sampize hoạt động tốt hơn để giải quyết điều này, cũng như những người khác. Ngoài ra, hãy xem câu trả lời tuyệt vời tại đây stats.stackexchange.com/questions/157714/ Kẻ
katya

daply là trong plyr, bạn nên gọi đó.
EngrStudent

Classwt Priors của các lớp. Không cần thêm tối đa một. Bỏ qua cho hồi quy.
Diego

@Diego: Tham số này có vẻ rất có vấn đề, tôi không hiểu cách tham số này hoạt động (xem các bình luận trong câu hỏi!) ...
Fabian Werner

Câu trả lời:


2

Đừng sử dụng một giới hạn cứng để phân loại thành viên cứng và không sử dụng KPI phụ thuộc vào dự đoán thành viên cứng như vậy. Thay vào đó, làm việc với một dự đoán xác suất, sử dụng predict(..., type="prob")và đánh giá những điều này bằng cách sử dụng thích hợp .

Chủ đề sớm hơn này sẽ hữu ích: Tại sao độ chính xác không phải là biện pháp tốt nhất để đánh giá các mô hình phân loại? Không đủ ngạc nhiên, tôi tin rằng câu trả lời của tôi sẽ đặc biệt hữu ích (xin lỗi vì sự không biết xấu hổ), cũng như một câu trả lời trước đó của tôi .


1
đây là chủ đề bạn nói về ngày hôm nay, phải không? Tôi sẽ xem xét điều này trong công việc của mình :-)
Jonas Heidelberg
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.