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

13

Я пытаюсь делать прогнозы, используя модель случайного леса в R.

Однако я получаю ошибки, так как некоторые факторы имеют разные значения в тестовом наборе, чем в обучающем наборе. Например, фактор Cat_2имеет значения 34, 68, 76и т. Д. В тестовом наборе, которые не отображаются в обучающем наборе. К сожалению, я не могу контролировать набор тестов ... Я должен использовать его как есть.

Моим единственным обходным решением было преобразование проблемных факторов обратно в числовые значения, используя as.numeric(). Это работает, но я не очень доволен, так как эти значения являются кодами, которые не имеют числового смысла ...

Как вы думаете, было бы другое решение, чтобы сбросить новые значения из тестового набора? Но без удаления всех других значений факторов (скажем, значений 1, 2, 14, 32и т. Д.), Которые используются как для обучения, так и для тестирования, и содержат информацию, потенциально полезную для прогнозов.

Benoit_Plante
источник
1
Я знаю причину, по которой значения в тесте должны быть в тренировочном наборе. Идея классификации состоит в том, чтобы использовать обучающие данные, чтобы получить представление о том, как выглядят условные плотности классов. Вы не можете увидеть все возможные значения из плотности. Если переменная используется в разделенном дереве, то разделение определяет, какая ветвь должна следовать для любых невидимых значений, а также для тех, которые были замечены.
Майкл Р. Черник
Вы делаете правильное замечание, но на практическом уровне, используя конкретный инструмент, о котором идет речь (пакет RF в R), это недопустимо. Мой ответ, связанный с вменением, - один из способов, но, конечно, не лучшее решение. Это, по крайней мере, делает код не сбой, так что, по крайней мере, работает, для небольших значений работы.
Богдановист
Похоже на мой вопрос здесь: stats.stackexchange.com/questions/18004/… . Я думаю, что я мог бы использовать GBM вместо RF, так как он лучше справляется с новыми уровнями факторов. Кроме того, вы смотрели на реализацию РФ в партии? Мне никогда не нравился randomForest из-за этих проблем (и неспособности беспрепятственно справляться с пропущенными значениями).
B_Miner

Ответы:

2

Если в тестовом наборе много этих точек с новыми значениями коэффициентов, то я не уверен, что лучший подход. Если это всего лишь несколько моментов, вы можете избежать неприятностей, таких как обработка ошибочных уровней факторов как пропущенных данных и навязывание их любым подходящим способом. Реализация R имеет несколько способов расчета отсутствующих данных, вам просто нужно установить эти уровни факторов на NA, чтобы указать, что они отсутствуют.

богдановской
источник
8

Король и Бонуа , этот фрагмент может быть полезен для согласования уровней:

for(attr in colnames(training))
{
  if (is.factor(training[[attr]]))
  {
    new.levels <- setdiff(levels(training[[attr]]), levels(testing[[attr]]))
    if ( length(new.levels) == 0 )
    { print(paste(attr, '- no new levels')) }
    else
    {
      print(c(paste(attr, length(new.levels), 'of new levels, e.g.'), head(new.levels, 2)))
      levels(testing[[attr]]) <- union(levels(testing[[attr]]), levels(training[[attr]]))
    }
  }
}

Он также печатает, какие атрибуты изменены. Я не нашел хороший способ написать это более элегантно (с ldply или что-то). Любые советы приветствуются.

user41330
источник
4

Вот код, который я написал и который адресован ответу @ King выше. Исправлена ​​ошибка:

# loops through factors and standardizes the levels
for (f in 1:length(names(trainingDataSet))) {
    if (levels(testDataSet[,f]) > levels(trainingDataSet[,f])) {    
            levels(testDataSet[,f]) = levels(trainingDataSet[,f])       
    } else {
            levels(trainingDataSetSMOTEpred[,f]) = levels(testDataSet[,f])      
    }
}
lfarb
источник
Привет @ifarb, я пытаюсь понять ваше решение: что такое trainingDataSetSMOTEpred и где оно определено в коде?
Кася Кульма
3

Тест и тренировочный набор должны быть объединены в один набор, а затем изменить уровни тренировочного набора. Мои коды:

totalData <- rbind(trainData, testData)
for (f in 1:length(names(totalData))) {
  levels(trainData[, f]) <- levels(totalData[, f])
}

Это работает в любых случаях, когда количество уровней в тесте больше или меньше, чем обучение.

Cscode Li
источник
2

У меня паршивый обходной путь, когда я использую randomForest в R. Это, вероятно, не теоретически нормально, но оно работает.

levels(testSet$Cat_2) = levels(trainingSet$Cat_2)

или наоборот. По сути, он просто сообщает R, что это допустимое значение, просто есть 0 случаев; так что перестаньте меня беспокоить по поводу ошибки.

Я не достаточно умен, чтобы кодировать его так, чтобы он автоматически выполнял действие для всех категориальных функций. Отправьте мне код, если вы знаете, как ...

король
источник
Но это не работает, если количество уровней в тесте больше, чем обучение. Это работает только в том случае, если уровни фактора тестовых данных <= уровни фактора обучающих данных.
KarthikS
1

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

goldisfine
источник