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 R
gó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ư TRUE
mặc dù có các ví dụ tiêu cực.
Đây là cách dữ liệu trông như thế nào:
Đâ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)
:)
Để 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:
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:
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ý:
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")