3

我正在尝试从 R 中的 3D 图中的分类算法中绘制分区边界(使用plot3D)。如果我们只有两个预测变量,那么这是一个相对简单的任务,只需要绘制两个轴(例如使用partimat函数)。我还没有找到一种令人满意的方法来在 3D 空间中绘制基于三个预测器的分类分区。

为了可视化这个问题,让我们首先使用 iris 数据集上的线性判别分析 (LDA) 分类算法为两个轴构建一个分区:

# Load packages and subset the iris dataset:
library(klaR)

data = droplevels(iris[iris$Species != 'virginica', ])

partimat(Species ~ Sepal.Length + Sepal.Width, data, 
         method = 'lda')

我们得到一个二维图,在两个物种之间有明确的划分:

两个轴上的线性判别分析结果

但是,partimat一次只能处理两个预测变量(请参阅 参考资料?partimat)。现在让我们看看 3D 问题:

library(plot3D)
    
# Plot the raw data:
points3D(data$Sepal.Length, data$Sepal.Width, data$Petal.Length,
             colkey = F,
             pch = 16, cex = 2,
             theta = 30, phi = 30, 
             ticktype = 'detailed',
             col = data$Species)

鸢尾植物指标的 3D 图

我想根据 LDA 之类的分类算法绘制一个将两个数据类分开的平面。从Roman Luštrik 的示例中汲取灵感,这是我在定义三个预测变量之间的划分方面的糟糕尝试。本质上,我建立了一个包含三个预测变量的 LDA 模型,然后将物种(setosa 或 versicolor)预测到最大值之间的多个点上。和分钟。所有三个预测变量的值。当绘制在 3D 图上时,这会生成一个点云,以不同的颜色表示 3D 空间,其中任何一种虹膜物种应基于三个预测变量出现:

# Build a classification model with three predictors:
m = lda(Species ~ Sepal.Length + Sepal.Width + Petal.Length, data)

# Predict 'Species' for the full range of each plant metric: 
np = 50

nx = seq(from = min(data[, 1]), to = max(data[, 1]), length.out = np)
ny = seq(from = min(data[, 2]), to = max(data[, 2]), length.out = np)
nz = seq(from = min(data[, 3]), to = max(data[, 3]), length.out = np)
nd = expand.grid(Sepal.Length = nx, Sepal.Width = ny, Petal.Length = nz)

p    = as.numeric(predict(m, newdata = nd)$class)
part = cbind(nd, Partition = p)

# Plot the partition and add the data points:  
scatter3D(part$Sepal.Length, part$Sepal.Width, part$Petal.Length, 
          colvar = part$Partition, 
          colkey = F,
          alpha = 0.5,
          pch = 16, cex = 0.3, 
          theta = 30, phi = 30, 
          ticktype = 'detailed',
          plot = F)
points3D(data$Sepal.Length, data$Sepal.Width, data$Petal.Length,
         colkey = F,
         pch = 16, cex = 2,
         theta = 30, phi = 30, 
         ticktype = 'detailed',
         col = data$Species,
         add = T)

我还添加了数据点。您可以将分区确定为点云中蓝色和红色之间的模糊交集:

三轴线性判别分析

这不是一个理想的解决方案,因为很难看到隐藏在点云中的数据点。点云也有点分散注意力。也许一些聪明的点与透明度的绘图会改善事情,但我怀疑一个更好的解决方案是在物种类别之间的相交处(即蓝色和红色点相遇的地方)绘制一个平面(类似于回归平面)。请注意,我最终希望使用不同的分类器(例如随机森林),以防万一存在仅限于 LDA 或类似的解决方案。

非常感谢您提供任何解决方案或建议。

4

1 回答 1

3

您可以使用来自 lda 模型的系数来生成分离判别体积的平面。实际上,平面是 3D 空间中的一组点,其中 (x, y, z) 坐标的总和乘以它们各自的模型系数等于模型的阈值(即模型可以不要将一个群体与另一个群体区分开来)。

我们可以通过沿 x 和 y 轴创建一个 10 x 10 的等距值网格并计算 z 值,从而根据模型为我们提供阈值:

threshold <-  sum(coef(m) * data[1, 1:3]) - predict(m)$x[1] 

Sepal_Lengths <- seq(min(data$Sepal.Length), max(data$Sepal.Length), length.out = 10)
Sepal_Widths  <- seq(min(data$Sepal.Width), max(data$Sepal.Width), length.out = 10)
Petal_Lengths <- outer(Sepal_Lengths, Sepal_Widths, function(x, y) {
                  (threshold - x * coef(m)[1] - y * coef(m)[2]) / coef(m)[3]})

所以现在当我们得出我们的观点时:

points3D(data$Sepal.Length, data$Sepal.Width, data$Petal.Length,
         colkey = F,
         pch = 16, cex = 2,
         theta = 30, phi = 30, 
         ticktype = 'detailed',
         col = data$Species)

在此处输入图像描述

添加飞机很简单:

persp3D(x = Sepal_Lengths, 
        y = Sepal_Widths, 
        z = Petal_Lengths, 
        col = "gold", add = TRUE, alpha = 0.5)

在此处输入图像描述

于 2021-10-29T13:43:41.333 回答