Ошибка при использовании predic () на объекте randomForest, обученном с помощью функции caret train () с использованием формулы

Использование R 3.2.0 с кареткой 6.0-41 и randomForest 4.6-10 на 64-битной машине Linux.

При попытке использовать метод predict() на объекте randomForest, обученном с помощью функции train() из пакета caret с использованием формулы, функция возвращает ошибку. При обучении с помощью randomForest() и / или с использованием x= и y=, а не формулы, все проходит гладко.

Вот рабочий пример:

library(randomForest)
library(caret)

data(imports85)
imp85     <- imports85[, c("stroke", "price", "fuelType", "numOfDoors")]
imp85     <- imp85[complete.cases(imp85), ]
imp85[]   <- lapply(imp85, function(x) if (is.factor(x)) x[,drop=TRUE] else x) ## Drop empty levels for factors.

modRf1  <- randomForest(numOfDoors~., data=imp85)
caretRf <- train( numOfDoors~., data=imp85, method = "rf" )
modRf2  <- caretRf$finalModel
modRf3  <- randomForest(x=imp85[,c("stroke", "price", "fuelType")], y=imp85[, "numOfDoors"])
caretRf <- train(x=imp85[,c("stroke", "price", "fuelType")], y=imp85[, "numOfDoors"], method = "rf")
modRf4  <- caretRf$finalModel

p1      <- predict(modRf1, newdata=imp85)
p2      <- predict(modRf2, newdata=imp85)
p3      <- predict(modRf3, newdata=imp85)
p4      <- predict(modRf4, newdata=imp85)

Из последних 4 строк только вторая p2 <- predict(modRf2, newdata=imp85) возвращает следующую ошибку:

Error in predict.randomForest(modRf2, newdata = imp85) : 
variables in the training data missing in newdata

Похоже, что причина этой ошибки в том, что метод predict.randomForest использует rownames(object$importance) для определения имени переменных, используемых для обучения случайного леса object. И глядя на

rownames(modRf1$importance)
rownames(modRf2$importance)
rownames(modRf3$importance)
rownames(modRf4$importance)

Мы видим:

[1] "stroke"   "price"    "fuelType"
[1] "stroke"   "price"    "fuelTypegas"
[1] "stroke"   "price"    "fuelType"
[1] "stroke"   "price"    "fuelType"

Итак, каким-то образом при использовании функции caret train() с формулой изменяется имя (факторных) переменных в поле importance объекта randomForest.

Действительно ли это несоответствие между формулой и версией функции каретки train() без формулы? Или я что-то упускаю?


person Adrien Combaz    schedule 07.05.2015    source источник
comment
Как уже отмечалось, вы не определили dataTrain в своем примере, что означает, что проблема не в воспроизводимый. Нелегко помочь вам, если мы не можем запустить код и получить те же результаты, что и вы.   -  person MrFlick    schedule 07.05.2015
comment
Моя ошибка, dataTrain должно было быть imp85, я отредактировал код в исходном вопросе. Я также удалил параметр data=imp85 в вызове, в котором явно упоминаются x и y, поскольку он бесполезен.   -  person Adrien Combaz    schedule 07.05.2015


Ответы (4)


Во-первых, почти никогда не используйте объект $finalModel для прогнозирования. Используйте predict.train. Это хороший пример того, почему.

Существует некоторая несогласованность между тем, как некоторые функции (включая randomForest и train) обрабатывают фиктивные переменные. Большинство функций в R, использующих метод формул, преобразуют факторные предикторы в фиктивные переменные, поскольку их модели требуют числового представления данных. Исключениями являются модели на основе деревьев и правил (которые могут разбиваться на категориальные предикторы), наивный байесовский метод и некоторые другие.

Таким образом, randomForest не будет создавать фиктивные переменные, когда вы используете randomForest(y ~ ., data = dat), но train (и большинство других) будет использовать вызов типа train(y ~ ., data = dat).

Ошибка возникает из-за того, что fuelType является фактором. У фиктивных переменных, созданных train, разные имена, поэтому predict.randomForest не может их найти.

Использование метода без формулы с train передаст предикторы фактора в randomForest, и все будет работать.

TL;DR

Используйте метод без формулы с train, если вы хотите одинаковые уровни , или используйте predict.train

Максимум

person topepo    schedule 11.05.2015
comment
К сожалению, у меня недостаточно репутации, чтобы проголосовать за ваш ответ, но вы отлично ответили на мой вопрос. Для всех тех функций, которые позволяют использовать формулы, мне было интересно, есть ли разница в способе обработки данных между формульной и неформульной версиями вызова функции. Теперь я знаю! Что касается использования $finalModel, я согласен с тем, что, как правило, использовать его не рекомендуется. Здесь я просто хотел сравнить результаты методов caret и randomForest. - person Adrien Combaz; 11.05.2015

Эта ошибка может быть вызвана двумя причинами.

1. Категории категориальных переменных в обучающем и тестовом наборах не совпадают. Чтобы проверить это, вы можете запустить что-то вроде следующего.

Ну, во-первых, рекомендуется хранить независимые переменные / функции в списке. Скажем, этот список - «вары». Допустим, вы разделили «Данные» на «Поезд» и «Тест». Пойдем:

for (v in vars){
  if (class(Data[,v]) == 'factor'){
    print(v)
    # print(levels(Train[,v])) 
    # print(levels(Test[,v]))
    print(all.equal(levels(Train[,v]) , levels(Test[,v])))
  }  
}

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

levels(Test$nonMatchingVar) <- levels(Train$nonMatchingVar)

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

person FatihAkici    schedule 05.01.2017

Другой способ - явно закодировать данные тестирования, используя model.matrix, например.

p2 <- predict(modRf2, newdata=model.matrix(~., imp85))
person WeimusT    schedule 27.02.2018

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

person Corey Levinson    schedule 01.05.2018