在R中导出LDA/QDA划分线方程并同图绘制的方法咨询
在R中可视化LDA与QDA的划分线并导出方程
下面提供基于Base R和ggplot2的自定义方案,同时推导并导出LDA(线性)和QDA(二次)的划分线方程。
Base R 实现(自定义性强)
核心思路是生成覆盖数据范围的网格点,计算每个点的后验概率,再绘制概率等于0.5的轮廓线(即划分边界)。
library(MASS) # 原始数据与模型构建 set.seed(123) Ng <- 100 group.a.x <- rnorm(n = Ng, mean = 2, sd = 3) group.a.y <- rnorm(n = Ng, mean = 2, sd = 3) group.b.x <- rnorm(n = Ng, mean = 11, sd = 3) group.b.y <- rnorm(n = Ng, mean = 11, sd = 3) group.a <- data.frame(x = group.a.x, y = group.a.y, group = "A") group.b <- data.frame(x = group.b.x, y = group.b.y, group = "B") my.xy <- rbind(group.a, group.b) mdlLDA <- lda(group ~ x + y, data = my.xy) mdlQDA <- qda(group ~ x + y, data = my.xy) # 1. 创建密集网格数据 x_range <- range(my.xy$x) y_range <- range(my.xy$y) grid <- expand.grid( x = seq(x_range[1], x_range[2], length.out = 200), y = seq(y_range[1], y_range[2], length.out = 200) ) # 2. 计算每个网格点的后验概率 grid$lda_prob <- predict(mdlLDA, newdata = grid)$posterior[, "A"] grid$qda_prob <- predict(mdlQDA, newdata = grid)$posterior[, "A"] # 3. 绘制图形 plot(my.xy$x, my.xy$y, col = my.xy$group, pch = 16, xlab = "x", ylab = "y", main = "LDA vs QDA 划分线对比") # 添加LDA划分线(A类后验概率=0.5的边界) contour(grid$x, grid$y, matrix(grid$lda_prob, 200, 200), levels = 0.5, add = TRUE, col = "red", lwd = 2, lty = 1) # 添加QDA划分线 contour(grid$x, grid$y, matrix(grid$qda_prob, 200, 200), levels = 0.5, add = TRUE, col = "blue", lwd = 2, lty = 2) # 添加图例 legend("topleft", legend = c("LDA 划分线", "QDA 划分线", "Group A", "Group B"), col = c("red", "blue", "black", "red"), lwd = c(2,2,NA,NA), pch = c(NA,NA,16,16), lty = c(1,2,NA,NA))
ggplot2 实现(简洁易自定义)
利用geom_contour直接绘制概率边界,配合ggplot的主题系统轻松调整样式:
library(ggplot2) library(tidyr) # 延续上面的grid数据,转换为长格式 grid_long <- pivot_longer(grid, cols = c(lda_prob, qda_prob), names_to = "model", values_to = "prob") # 可视化 ggplot() + geom_point(data = my.xy, aes(x = x, y = y, color = group), size = 2) + geom_contour(data = grid_long, aes(x = x, y = y, z = prob, color = model, linetype = model), breaks = 0.5, linewidth = 1.2) + scale_color_manual(values = c("A" = "black", "B" = "red", "lda_prob" = "darkred", "qda_prob" = "darkblue")) + scale_linetype_manual(values = c("lda_prob" = 1, "qda_prob" = 2)) + labs(x = "x", y = "y", title = "LDA vs QDA 划分线对比", color = "类别/模型", linetype = "模型") + theme_minimal()
导出划分线方程
划分线的本质是两类后验概率相等的边界,我们可以通过模型参数直接推导方程:
LDA 线性划分线方程
LDA假设两类共享协方差矩阵,决策边界是直线,令两类判别函数相等即可推导:
# 提取LDA参数 mu_A <- mdlLDA$means[1,] mu_B <- mdlLDA$means[2,] cov_mat <- cov(my.xy[,1:2]) inv_cov <- solve(cov_mat) pi_A <- sum(my.xy$group == "A")/nrow(my.xy) pi_B <- 1 - pi_A # 计算线性方程系数 coef_x <- inv_cov[1,1]*(mu_A[1] - mu_B[1]) + inv_cov[1,2]*(mu_A[2] - mu_B[2]) coef_y <- inv_cov[2,1]*(mu_A[1] - mu_B[1]) + inv_cov[2,2]*(mu_A[2] - mu_B[2]) intercept <- -0.5*(t(mu_A) %*% inv_cov %*% mu_A - t(mu_B) %*% inv_cov %*% mu_B) + log(pi_A/pi_B) # 输出方程 cat("LDA划分线方程:", round(coef_x,4), "*x +", round(coef_y,4), "*y +", round(intercept,4), "= 0\n") cat("整理为y关于x的表达式:y =", round(-coef_x/coef_y,4), "*x +", round(-intercept/coef_y,4), "\n")
QDA 二次划分线方程
QDA允许两类有独立协方差矩阵,决策边界是二次曲线,推导如下:
# 提取QDA参数 cov_A <- cov(my.xy[my.xy$group == "A",1:2]) cov_B <- cov(my.xy[my.xy$group == "B",1:2]) inv_cov_A <- solve(cov_A) inv_cov_B <- solve(cov_B) # 计算二次项、一次项和常数项系数 coef_x2 <- 0.5*(inv_cov_B[1,1] - inv_cov_A[1,1]) coef_xy <- (inv_cov_B[1,2] - inv_cov_A[1,2]) coef_y2 <- 0.5*(inv_cov_B[2,2] - inv_cov_A[2,2]) coef_x <- (inv_cov_A %*% mu_A)[1] - (inv_cov_B %*% mu_B)[1] coef_y <- (inv_cov_A %*% mu_A)[2] - (inv_cov_B %*% mu_B)[2] intercept <- -0.5*(t(mu_A) %*% inv_cov_A %*% mu_A - t(mu_B) %*% inv_cov_B %*% mu_B) - 0.5*log(det(cov_A)/det(cov_B)) + log(pi_A/pi_B) # 输出方程 cat("QDA划分线方程:", round(coef_x2,4), "*x² +", round(coef_xy,4), "*xy +", round(coef_y2,4), "*y² +", round(coef_x,4), "*x +", round(coef_y,4), "*y +", round(intercept,4), "= 0\n")
内容的提问来源于stack exchange,提问作者Alex
相关产品推荐
相关产品推荐

