如何从 R 中的 3D 图中的分类算法绘制分区平面
How do you draw a partition plane from a classification algorithm in a 3D plot in R
我正在尝试从 R 中的 3D 绘图中的分类算法绘制分区边界(使用 plot3D
)。如果我们只有两个预测变量,这将是一个相对简单的任务,只需要绘制两个轴(例如使用 partimat
函数)。我还没有找到在 3D 中绘制基于三个预测变量的分类分区的令人满意的方法 space。
为了使问题可视化,让我们首先在 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)
我想根据像 LDA 这样的分类算法绘制一个平面来分隔两个数据 类。从 中汲取灵感,这是我定义三个预测变量之间的分区的糟糕尝试。本质上,我已经建立了一个具有三个预测变量的 LDA 模型,然后将物种(setosa 或 versicolor)预测到最大值之间的多个点上。和分钟。所有三个预测变量的值。当绘制在 3D 图上时,这会生成一个点云,以不同的颜色表示 3D space 根据三个预测变量应该出现任何一种鸢尾花的位置:
# 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)
我还添加了数据点。您可以将分区视为点云中蓝色和红色之间的模糊交集:
这不是一个理想的解决方案,因为很难看到隐藏在点云中的数据点。点云也有点让人分心。也许一些巧妙地绘制具有透明度的点会有所改善,但我怀疑更好的解决方案是在物种 类 之间的交点处绘制一个平面(类似于 regression plane)(即蓝点和红点相遇)。请注意,我最终希望使用不同的分类器(例如随机森林),以防万一存在仅限于 LDA 或类似的解决方案。
非常感谢任何解决方案或建议。
您可以使用 lda 模型中的系数来生成分隔判别体积的平面。实际上,平面是 3D space 中的一组点,其中 (x, y, z) 坐标乘以它们各自的模型系数的总和等于模型的阈值(即平面模型无法将一组与另一组区分开来)。
我们可以通过创建一个 10 x 10 的网格来做到这一点,其中 spaced 个值沿 x 轴和 y 轴相等,并计算 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)
我正在尝试从 R 中的 3D 绘图中的分类算法绘制分区边界(使用 plot3D
)。如果我们只有两个预测变量,这将是一个相对简单的任务,只需要绘制两个轴(例如使用 partimat
函数)。我还没有找到在 3D 中绘制基于三个预测变量的分类分区的令人满意的方法 space。
为了使问题可视化,让我们首先在 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)
我想根据像 LDA 这样的分类算法绘制一个平面来分隔两个数据 类。从
# 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)
我还添加了数据点。您可以将分区视为点云中蓝色和红色之间的模糊交集:
这不是一个理想的解决方案,因为很难看到隐藏在点云中的数据点。点云也有点让人分心。也许一些巧妙地绘制具有透明度的点会有所改善,但我怀疑更好的解决方案是在物种 类 之间的交点处绘制一个平面(类似于 regression plane)(即蓝点和红点相遇)。请注意,我最终希望使用不同的分类器(例如随机森林),以防万一存在仅限于 LDA 或类似的解决方案。
非常感谢任何解决方案或建议。
您可以使用 lda 模型中的系数来生成分隔判别体积的平面。实际上,平面是 3D space 中的一组点,其中 (x, y, z) 坐标乘以它们各自的模型系数的总和等于模型的阈值(即平面模型无法将一组与另一组区分开来)。
我们可以通过创建一个 10 x 10 的网格来做到这一点,其中 spaced 个值沿 x 轴和 y 轴相等,并计算 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)