R случайная ошибка леса - тип предикторов в новых данных не соответствует

Я пытаюсь использовать функцию рекурсивного регрессионного рельефа в R (quantregForest), которая построена на пакете Random Forest. Я получаю ошибку несоответствия типа, что я не могу понять, почему.

Я тренирую модель, используя

qrf <- quantregForest(x = xtrain, y = ytrain)

который работает без проблем, но когда я пытаюсь протестировать новые данные, например

quant.newdata <- predict(qrf, newdata= xtest)

он дает следующую ошибку:

Error in predict.quantregForest(qrf, newdata = xtest) : 
Type of predictors in new data do not match types of the training data.

Мои данные для обучения и тестирования поступают из отдельных файлов (отсюда и отдельные кадры данных), но имеют одинаковый формат. Я проверил классы предикторов с помощью

sapply(xtrain, class)
sapply(xtest, class)

Вот результат:

> sapply(xtrain, class)
pred1     pred2     pred3     pred4     pred5     pred6     pred7     pred8 
"factor" "integer" "integer" "integer"  "factor"  "factor" "integer"  "factor" 
pred9    pred10    pred11    pred12 
"factor"  "factor"  "factor"  "factor" 


> sapply(xtest, class)
pred1     pred2     pred3     pred4     pred5     pred6     pred7     pred8 
"factor" "integer" "integer" "integer"  "factor"  "factor" "integer"  "factor" 
pred9    pred10    pred11    pred12 
"factor"  "factor"  "factor"  "factor" 

Они точно такие же. Я также проверил значения "NA". Ни xtrain, ни xtest не имеют значения NA в нем. Я пропустил что-то тривиальное здесь?

Обновление I: выполнение предсказания по данным обучения по-прежнему дает ту же ошибку

> quant.newdata <- predict(qrf, newdata = xtrain)
Error in predict.quantregForest(qrf, newdata = xtrain) : 
names of predictor variables do not match

Обновление II: я объединил свои тренировочные и тестовые наборы, чтобы строки от 1 до 101 были данными обучения, а остальное - тестированием. Я изменил пример, приведенный в (quantregForest) следующим образом:

data <-  read.table("toy.txt", header = T)
n <- nrow(data)
indextrain <- 1:101
xtrain <- data[indextrain, 3:14]
xtest <- data[-indextrain, 3:14]
ytrain <- data[indextrain, 15]
ytest <- data[-indextrain, 15]

qrf <- quantregForest(x=xtrain, y=ytrain)
quant.newdata <- predict(qrf, newdata= xtest)

И это работает! Я был бы признателен, если бы кто-нибудь мог объяснить, почему он работает таким образом, а не с другим путем?

Ответы

Ответ 1

У меня была та же проблема. Вы можете попытаться использовать небольшой трюк для выравнивания классов обучения и набора тестов. Привяжите первую строку тренировки к набору тестов и удалите ее. Для вашего примера это должно выглядеть так:

    xtest <- rbind(xtrain[1, ] , xtest)
    xtest <- xtest[-1,]

Ответ 2

@mgoldwasser прав в целом, но в predict.randomForest есть очень неприятная ошибка: даже если у вас точно такие же уровни в обучении и в наборе прогнозов, можно получить эту ошибку. Это возможно, если у вас есть фактор, в котором вы встроили NA в качестве отдельного уровня. Проблема в том, что predict.randomForest по существу делает следующее:

# Assume your original factor has two "proper" levels + NA level:
f <- factor(c(0,1,NA), exclude=NULL)

length(levels(f)) # => 3
levels(f)         # => "0" "1" NA

# Note that
sum(is.na(f))     # => 0
# i.e., the values of the factor are not `NA` only the corresponding level is.

# Internally predict.randomForest passes the factor (the one of the training set)
# through the function `factor(.)`.
# Unfortunately, it does _not_ do this for the prediction set.
# See what happens to f if we do that:
pf <- factor(f)

length(levels(pf)) # => 2
levels(pf)         # => "0" "1"

# In other words:
length(levels(f)) != length(levels(factor(f))) 
# => sad but TRUE

Таким образом, он всегда будет отбрасывать уровень NA из набора тренировок и всегда будет видеть один дополнительный уровень в наборе прогнозов.

Обходным решением является замена значения NA уровня перед использованием randomForest:

levels(f)[is.na(levels(f))] <- "NA"
levels(f) # => "0"  "1"  "NA"
          #              .... note that this is no longer a plain `NA`

Теперь вызов factor(f) не отменит уровень, и проверка завершится успешно.

Ответ 3

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

levels(test$SectionName) <- levels(train$SectionName)

Ответ 4

Расширение на решение @user1849895:

common <- intersect(names(train), names(test)) 
for (p in common) { 
  if (class(train[[p]]) == "factor") { 
    levels(test[[p]]) <- levels(train[[p]]) 
  } 
}

Ответ 5

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

Это странная причуда случайного леса, и для меня это не имеет смысла.

Ответ 6

Я просто решил сделать следующее:

## Creating sample data
values_development=factor(c("a", "b", "c")) ## Values used when building the random forest model
values_production=factor(c("a", "b", "c", "ooops")) ## New values to used when using the model

## Deleting cases which were not present when developing
values_production=sapply(as.character(values_production), function(x) if(x %in% values_development) x else NA)

## Creating the factor variable, (with the correct NA value level)
values_production=factor(values_production)

## Checking
values_production # =>  a     b     c  <NA> 

Ответ 7

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

Ответ 8

Я пытаюсь использовать этот способ, чтобы решить, и это работает.

получить уровень фактора непосредственно из самой модели ВЧ

levels(PredictData$columnName) <- rfmodels$forest$xlevels$columnName