Эта тема ссылается на две другие темы и прекрасную статью по этому вопросу. Кажется, что взвешивание классов и даунсамплинг одинаково хороши. Я использую понижающую дискретизацию, как описано ниже.
Помните, что тренировочный набор должен быть большим, поскольку только 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)