Случайный лес с очень несбалансированными классами

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

strata 

sampsize

Документация для этих параметров скудна (или мне не повезло найти ее), и я действительно не понимаю, как ее реализовать. Я использую следующий код:

randomForest(x=predictors, 
             y=response, 
             data=train.data, 
             mtry=lista.params[1], 
             ntree=lista.params[2], 
             na.action=na.omit, 
             nodesize=lista.params[3], 
             maxnodes=lista.params[4],
             sampsize=c(250000,2000), 
             do.trace=100, 
             importance=TRUE)

Ответ представляет собой класс с двумя возможными значениями, первое из которых появляется чаще, чем второе (10000:1 или более).

list.params это список с разными параметрами (да! Я знаю...)

Ну, вопрос (опять же): как я могу использовать параметр "страты"? Я правильно использую типоразмер?

И, наконец, иногда я получаю следующую ошибку:

Error in randomForest.default(x = predictors, y = response, data = train.data,  :
  Still have fewer than two classes in the in-bag sample after 10 attempts.

Извините, если я делаю так много (и, возможно, глупо) вопросов...

4 ответа

Решение

Вы должны попытаться использовать методы выборки, которые уменьшают степень дисбаланса с 1:10000 до 1:100 или 1:10. Вы также должны уменьшить размер генерируемых деревьев. (На данный момент это рекомендации, которые я повторяю только по памяти, но я посмотрю, смогу ли я отследить больше авторитета, чем моя губчатая кора.)

Один из способов уменьшить размер деревьев - увеличить размер узла. При такой степени дисбаланса вам может понадобиться очень большой размер узла, скажем, 5-10 000. Вот нить в справке: https://stat.ethz.ch/pipermail/r-help/2011-September/289288.html

В текущем состоянии вопроса у вас есть sampsize=c(250000,2000), тогда как я бы подумал, что что-то вроде sampsize=c(8000,2000) больше соответствует моим предложениям. Я думаю, что вы создаете сэмплы, в которых у вас нет ни одной группы, в которую были сэмплированы только 2000.

Есть несколько вариантов.

Если у вас много данных, отложите случайную выборку данных. Постройте свою модель на одном наборе, а затем используйте другой, чтобы определить правильное ограничение вероятностей классов, используя кривую ROC.

Вы также можете увеличить выборку данных в классе меньшинства. Алгоритм SMOTE может помочь (см. Ссылку ниже и пакет DMwR для функции).

Вы также можете использовать другие методы. rpart() и несколько других функций могут позволить различные затраты на ошибки, так что вы могли бы отдать предпочтение классу меньшинства больше. Вы можете сумку этого типа rpart() модель, чтобы приблизиться к тому, что делает случайный лес.

ksvm() в пакете kernlab также можно использовать несбалансированные затраты (но оценки вероятности больше не хороши, когда вы делаете это). Многие другие пакеты имеют аргументы для установки приоров. Вы также можете настроить это, чтобы сделать больший акцент на классе меньшинства.

Последняя мысль: максимизация моделей на основе точности ни к чему вас не приведет (вы можете получить 99,99% скидки). Каретка может настраивать модели на основе статистики Каппа, что является гораздо лучшим выбором в вашем случае.

Извините, я не знаю, как оставить комментарий к предыдущему ответу, поэтому я создам отдельный ответ.

Я предполагаю, что проблема вызвана большим дисбалансом набора данных (слишком мало случаев одного из классов присутствуют). Для каждого дерева в RF алгоритм создает образец начальной загрузки, который является обучающим набором для этого дерева. И если в вашем наборе данных слишком мало примеров одного из классов, то при начальной загрузке будут выбраны примеры только одного класса (основного). И, таким образом, дерево не может быть выращено только на одном примере. Похоже, что существует ограничение на 10 неудачных попыток выборки. Таким образом, предложение DWin уменьшить степень дисбаланса до более низких значений (1:100 или 1:10) является наиболее разумным.

Я уверен, что я не согласен с идеей удаления наблюдений из вашего образца.

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

Вот пример, который я нашел:

len_pos <- nrow(example_dataset[example_dataset$target==1,])
len_neg <- nrow(example_dataset[example_dataset$target==0,])

train_model <- function(training_data, labels, model_type, ...) {
  experiment_control <- trainControl(method="repeatedcv",
                                     number = 10,
                                     repeats = 2,
                                     classProbs = T,
                                     summaryFunction = custom_summary_function)
  train(x = training_data,
        y = labels,
        method = model_type,
        metric = "custom_score",
        trControl = experiment_control,
        verbose = F,
        ...)
}

# strata refers to which feature to do stratified sampling on.
# sampsize refers to the size of the bootstrap samples to be taken from each class. These samples will be taken as input
# for each tree. 

fit_results <- train_model(example_dataset
                           , as.factor(sprintf("c%d", as.numeric(example_dataset$target)))        
                           ,"rf"
                           ,tuneGrid = expand.grid(mtry = c( 3,5,10))
                           ,ntree=500
                           ,strata=as.factor(example_dataset$target)
                           ,sampsize = c('1'=as.integer(len_pos*0.25),'0'=as.integer(len_neg*0.8))
)
Другие вопросы по тегам