R пакет для взвешенного случайного леса? вариант classwt?


16

Я пытаюсь использовать Случайный Лес, чтобы предсказать исход крайне несбалансированного набора данных (уровень меньшинства составляет около 1% или даже меньше). Поскольку традиционный алгоритм случайного леса минимизирует общую частоту ошибок, вместо того, чтобы уделять особое внимание классам меньшинства, он не применим напрямую к несбалансированным данным. Поэтому я хочу назначить высокую цену неправильной классификации класса меньшинства (обучение с учетом затрат).

Я прочитал несколько источников , которые мы можем использовать опцию classwtиз randomForestв R, но я не знаю , как использовать это. И есть ли у нас какие-либо альтернативы этой функции randomForest?

Ответы:


29

Эта тема ссылается на две другие темы и прекрасную статью по этому вопросу. Кажется, что взвешивание классов и даунсамплинг одинаково хороши. Я использую понижающую дискретизацию, как описано ниже.

Помните, что тренировочный набор должен быть большим, поскольку только 1% будет характеризовать редкий класс. Менее 25-50 образцов этого класса, вероятно, будут проблематичными. Несколько образцов, характеризующих класс, неизбежно сделают изученный образец грубым и менее воспроизводимым.

РФ использует большинство голосов по умолчанию. Классовая распространенность учебного комплекта будет действовать как своего рода эффективный априор. Таким образом, если редкий класс не является полностью отделимым, маловероятно, что этот редкий класс выиграет большинство голосов при прогнозировании. Вместо агрегирования большинством голосов вы можете агрегировать фракции голосов.

Стратифицированная выборка может использоваться, чтобы увеличить влияние редкого класса. Это делается на основе затрат на сокращение числа других классов. Выращенные деревья станут менее глубокими, так как необходимо разделить гораздо меньшее количество образцов, что ограничивает сложность изученного образца. Количество выращиваемых деревьев должно быть большим, например, 4000, чтобы большинство наблюдений участвовало в нескольких деревьях.

В приведенном ниже примере я смоделировал набор обучающих данных из 5000 выборок в 3 классах с преобладанием 1%, 49% и 50% соответственно. Таким образом, будет 50 выборок класса 0. На первом рисунке показан истинный класс обучения, заданный как функция двух переменных x1 и x2. Эта картина показывает смоделированный шаблон для изучения

Были обучены четыре модели: модель по умолчанию и три стратифицированных модели со стратификацией классов 1:10:10 1: 2: 2 и 1: 1: 1. Основное, в то время как количество образцов входящих пакетов (включая перерисовки) в каждом дереве будет 5000, 1050, 250 и 150. Поскольку я не использую большинство голосов, мне не нужно делать идеально сбалансированное расслоение. Вместо этого голоса по редким классам могут быть взвешены 10 раз или по другому правилу принятия решения. Ваша цена ложных негативов и ложных срабатываний должна влиять на это правило.

На следующем рисунке показано, как стратификация влияет на долю голосов. Обратите внимание, что стратифицированные классовые отношения всегда являются центром предсказаний. стратификация и голосование

Наконец, вы можете использовать ROC-кривую, чтобы найти правило голосования, которое дает вам хороший компромисс между специфичностью и чувствительностью. Черная линия не стратифицирована, красная 1: 5: 5, зеленая 1: 2: 2 и синяя 1: 1: 1. Для этого набора данных 1: 2: 2 или 1: 1: 1 кажется лучшим выбором. рока кривая

Кстати, фракции для голосования здесь неуместны.

И код:

library(plotrix)
library(randomForest)
library(AUC)

make.data = function(obs=5000,vars=6,noise.factor = .2,smallGroupFraction=.01) {
X = data.frame(replicate(vars,rnorm(obs)))
yValue = with(X,sin(X1*pi)+sin(X2*pi*2)+rnorm(obs)*noise.factor)
yQuantile = quantile(yValue,c(smallGroupFraction,.5))
yClass = apply(sapply(yQuantile,function(x) x<yValue),1,sum)
yClass = factor(yClass)
print(table(yClass)) #five classes, first class has 1% prevalence only
Data=data.frame(X=X,y=yClass)
}

plot.separation = function(rf,...) {
triax.plot(rf$votes,...,col.symbols = c("#FF0000FF",
                                       "#00FF0010",
                                       "#0000FF10")[as.numeric(rf$y)])
}

#make data set where class "0"(red circles) are rare observations
#Class 0 is somewhat separateble from class "1" and fully separateble from class "2"
Data = make.data()
par(mfrow=c(1,1))
plot(Data[,1:2],main="separation problem: identify rare red circles",
     col = c("#FF0000FF","#00FF0020","#0000FF20")[as.numeric(Data$y)])

#train default RF and with 10x 30x and 100x upsumpling by stratification
rf1 = randomForest(y~.,Data,ntree=500, sampsize=5000)
rf2 = randomForest(y~.,Data,ntree=4000,sampsize=c(50,500,500),strata=Data$y)
rf3 = randomForest(y~.,Data,ntree=4000,sampsize=c(50,100,100),strata=Data$y)
rf4 = randomForest(y~.,Data,ntree=4000,sampsize=c(50,50,50)  ,strata=Data$y)

#plot out-of-bag pluralistic predictions(vote fractions).
par(mfrow=c(2,2),mar=c(4,4,3,3))
plot.separation(rf1,main="no stratification")
plot.separation(rf2,main="1:10:10")
plot.separation(rf3,main="1:5:5")
plot.separation(rf4,main="1:1:1")

par(mfrow=c(1,1))
plot(roc(rf1$votes[,1],factor(1 * (rf1$y==0))),main="ROC curves for four models predicting class 0")
plot(roc(rf2$votes[,1],factor(1 * (rf1$y==0))),col=2,add=T)
plot(roc(rf3$votes[,1],factor(1 * (rf1$y==0))),col=3,add=T)
plot(roc(rf4$votes[,1],factor(1 * (rf1$y==0))),col=4,add=T)

Подпись к цифре 1: 5: 5 вместо 1: 2: 2
Сорен Хавелунд Веллинг

Большое спасибо за ваш подробный ответ, который определенно мне очень поможет в моей повседневной работе. Есть одно предложение, которое я не понимаю: «Главное, в то время как число образцов входящих пакетов (включая перерисовки) в каждом дереве будет 5000, 1050, 250 и 150». Не могли бы вы объяснить, откуда взялись цифры?
Метариат

1
мое удовольствие;) в этом примере редкий класс имел 50 участников. При стратификации 1:10:10 нам нужно было бы указать sampsize = c (50 500 500). 50 + 500 + 500 = 1050. Полностью выросшее дерево из 1050 образцов будет иметь 1050x2 узлов.
Сорен Хавелунд Веллинг

Извините, если у меня вопрос идиотский, но какой здесь смысл стратификации 1:10:10, 1: 2: 2 и 1: 1: 1? И когда вы сказали, что «голоса по редким классам могут быть взвешены в 10 раз». Какая часть кода представляет это? 1:10:10? Большое спасибо!
Метариат

1
1:10:10 это соотношение между классами. Имитированный набор данных был разработан, чтобы иметь отношения 1:49:50. Эти отношения были изменены путем понижающей выборки двух больших классов. Выбирая, например, sampsize = c (50 500 500) так же, как c (1,10,10) * 50, вы меняете классовые соотношения в деревьях. 50 - количество образцов редкого класса. Кроме того, если вы установите keep.inbag = TRUE и осмотрите rf $ inbag, вы увидите, что выборки редких классов содержат inbag в ~ 2/3 деревьев, тогда как каждая не редкая выборка классов включена в очень мало деревьев из-за понижающей выборки.
Сорен Хавелунд Веллинг
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.