Почему naiveBayes возвращает все NA для многоклассической классификации в R?

Начинал писать этот вопрос, а затем выяснил ответ. Собираюсь поместить его сюда для потомков, так как было трудно найти ответы на это.

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

Пример:

> model <- naiveBayes(formula=as.factor(V11)~., data=table, laplace=3)
> predict(model, table[,1:10]) 
[1] 4 4 4 4 4 4 4 4 1 1 1 3 3 1 1
> predict(model, table[,1:10], type="raw")
       1  2  3  4
 [1,] NA NA NA NA
 [2,] NA NA NA NA
 [3,] NA NA NA NA
 [4,] NA NA NA NA
 [5,] NA NA NA NA
 [6,] NA NA NA NA
 [7,] NA NA NA NA
 [8,] NA NA NA NA
 [9,] NA NA NA NA
[10,] NA NA NA NA
[11,] NA NA NA NA
[12,] NA NA NA NA
[13,] NA NA NA NA
[14,] NA NA NA NA
[15,] NA NA NA NA

Это кажется мне абсурдным, поскольку тот факт, что модель может выводить прогнозы, означает, что она должна иметь оценки вероятности для классов. Что вызывает это странное поведение?

Некоторые вещи, которые я уже пробовал без успеха:

  • добавление типа = "raw" к вызову конструкции модели.
  • Вместо этого используйте функцию NaiveBayes из пакета klaR (который не может обрабатывать.

Пример некоторых данных, которые вызывают эту ошибку:

table[1:5,]
  V1 V2       V3         V4        V5        V6        V7        V8        V9
1  0  0 0.000000  0.0000000  0.000000 0.0000000 0.6711444 0.7110409 0.0000000
2  0  0 0.000000  0.0000000 -1.345804 2.1978370 0.6711444 0.7110409 0.0000000
3  0  0 1.923538 -3.6718725  0.000000 0.0000000 0.0000000 0.0000000 0.8980172
4  0  0 1.923538 -0.4079858  0.000000 0.0000000 0.0000000 0.0000000 0.8980172
5  0  0 0.000000  0.0000000 -1.345804 0.2930449 0.6711444 0.7110409 0.0000000
         V10 V11
1  0.0000000   6
2  0.0000000   3
3 -3.1316213   2
4 -0.2170431   5
5  0.0000000   4

Ответ 1

Это происходит потому, что один из классов в наборе данных имеет только один экземпляр.

Легким решением для моего приложения было клонирование этой записи и добавление небольшого количества шума, после чего предсказание работает, как ожидалось.

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

> table <- as.data.frame(rbind(as.matrix(table),as.matrix(table))
> nms <- colnames(table)
> model <- naiveBayes(table[,1:length(nms)-1], factor(table[,length(nms)]))
> predict(model, table[,1:(length(nms)-1)], type='raw')
                 2            3            4            5            6
 [1,] 2.480502e-34 6.283185e-12 6.283185e-12 2.480502e-34 1.000000e+00
 [2,] 1.558542e-45 9.999975e-01 2.506622e-06 1.558542e-45 6.283170e-12
 [3,] 1.000000e+00 1.558545e-45 1.558545e-45 6.283185e-12 2.480502e-34
 [4,] 6.283185e-12 1.558545e-45 1.558545e-45 1.000000e+00 2.480502e-34
 [5,] 1.558542e-45 2.506622e-06 9.999975e-01 1.558542e-45 6.283170e-12
 [6,] 2.480502e-34 6.283185e-12 6.283185e-12 2.480502e-34 1.000000e+00
 [7,] 1.558542e-45 9.999975e-01 2.506622e-06 1.558542e-45 6.283170e-12
 [8,] 1.000000e+00 1.558545e-45 1.558545e-45 6.283185e-12 2.480502e-34
 [9,] 6.283185e-12 1.558545e-45 1.558545e-45 1.000000e+00 2.480502e-34
[10,] 1.558542e-45 2.506622e-06 9.999975e-01 1.558542e-45 6.283170e-12