【问题标题】:How to calculate fuzzy performance index and normalized classification entropy in R如何在R中计算模糊性能指标和归一化分类熵
【发布时间】:2021-12-12 17:47:02
【问题描述】:

我正在使用 e1071 包运行模糊 C 均值聚类。我想根据以下公式中给出的模糊性能指数(FPI)(模糊程度)和归一化分类熵(NCE)(特定类的无组织程度)来确定最佳聚类数

其中 c 是聚类数,n 是观测数,μik 是模糊隶属度,loga 是自然对数。

我正在使用以下代码

library(e1071)
x <- rbind(matrix(rnorm(100,sd=0.3),ncol=2),
         matrix(rnorm(100,mean=1,sd=0.3),ncol=2))
cl <- cmeans(x,2,20,verbose=TRUE,method="cmeans")
cl$membership

我已经能够提取 μik 即模糊隶属度。现在,cmeans 必须针对不同数量的集群,例如2 到 6 和 FPI 和 NCE 必须计算有如下图

如何在 R 中实现?

编辑

我已经使用以下代码尝试了@nya 为iris 数据集提供的代码

df <- scale(iris[-5])

FPI <- function(cmem){
  c <- ncol(cmem)
  n <- nrow(cmem)
  
  1 - (c / (c - 1)) * (1 - sum(cmem^2) / n)
}

NCE <- function(cmem){
  c <- ncol(cmem)
  n <- nrow(cmem)
  
  (n / (n - c)) * (- sum(cmem * log(cmem)) / n)
}

# prepare variables
cl <- list()
fpi <- nce <- NULL

# cycle through the desired number of clusters
for(i in 2:6){
  cl[[i]] <- cmeans(df, i, 20, method = "cmeans")
  fpi <- c(fpi, FPI(cl[[i]]$membership))
  nce <- c(nce, NCE(cl[[i]]$membership))
}

# add space for the second axis label
par(mar = c(5,4,1,4) + .1)

# plot FPI
plot(2:6, fpi, lty = 2, pch = 18, type = "b", xlab = "Number of clusters", ylab = "FPI")

# plot NCE, manually adding the second axis
par(new = TRUE)
plot(2:6, nce, lty = 1, pch = 15, type = "b", xlab = "", ylab = "", axes = FALSE)
axis(4, at = pretty(range(nce)))
mtext("NCE", side = 4, line = 3)

# add legend
legend("top", legend = c("FPI", "NCE"), pch = c(18,15), lty = c(2,1), horiz = TRUE)

考虑模糊性能指数(FPI)和归一化分类熵(NCE)的最小值来确定最佳聚类数。 NCE 一直在增加,而 FPI 则呈下降趋势。理想情况下应该是

【问题讨论】:

    标签: r cluster-analysis fuzzy-c-means


    【解决方案1】:

    使用可用的方程,我们可以编写自己的函数。在这里,这两个函数使用了您建议的论文中的方程式和作者引用的参考文献之一。

    FPI <- function(cmem, method = c("FuzME", "McBrathney", "Rahul")){
        method = match.arg(method)
        C <- ncol(cmem)
        N <- nrow(cmem)
    
        # Rahul et al. 2019. https://doi.org/10.1080/03650340.2019.1578345
        if(method == "Rahul"){
            res <- 1 - (C / (C - 1)) * (1 - sum(cmem^2) / N)
        }
        # McBrathney & Moore 1985 https://doi.org/10.1016/0168-1923(85)90082-6
        if(method == "McBrathney"){
            F <- sum(cmem^2) / N
            res <- 1 - (C * F - 1) / (F - 1)
        }
        # FuzME https://precision-agriculture.sydney.edu.au/resources/software/
        # MATLAB code file fvalidity.m, downloaded on 11 Nov, 2021 
        if(method == "FuzME"){
            F <- sum(cmem^2) / N
            res <- 1 - (C * F - 1) / (C - 1)
        }
        return(res)
    }
    
    NCE <- function(cmem, method = c("FuzME", "McBrathney", "Rahul")){
        method = match.arg(method)
        C <- ncol(cmem)
        N <- nrow(cmem)
    
        if(method == "Rahul"){
            res <- (N / (N - C)) * (- sum(cmem * log(cmem)) / N)
        }
        if(method %in% c("FuzME", "McBrathney")){
            H <- -1 / N * sum(cmem * log(cmem)) 
            res <- H / log(C)
        }
        return(res)
    }
    

    然后使用这些来计算来自iris 数据集的cmeans 函数的隶属度指数。

    # prepare variables
    cl <- list()
    fpi <- nce <- NULL
    
    # cycle through the desired number of clusters
    for(i in 2:6){
        cl[[i]] <- e1071::cmeans(iris[, -5], i, 20, method = "cmeans")
        fpi <- c(fpi, FPI(cl[[i]]$membership, method = "M"))
        nce <- c(nce, NCE(cl[[i]]$membership, method = "M"))
    }
    

    最后,将two different axes 绘制在一个情节中。

    # add space for the second axis label
    par(mar = c(5,4,1,4) + .1)
    
    # plot FPI
    plot(2:6, fpi, lty = 2, pch = 18, type = "b", xlab = "Number of clusters", ylab = "FPI")
    
    # plot NCE, manually adding the second axis
    par(new = TRUE)
    plot(2:6, nce, lty = 1, pch = 15, type = "b", xlab = "", ylab = "", axes = FALSE)
    axis(4, at = pretty(range(nce)))
    mtext("NCE", side = 4, line = 3)
    
    # add legend
    legend("top", legend = c("FPI", "NCE"), pch = c(18,15), lty = c(2,1), horiz = TRUE)
    

    EDIT1:根据来自两个不同出版物的可选方程更新函数,并在iris 数据集上计算示例。

    EDIT2:为 FuzME MATLAB 代码中指定的 FPI 和 NCE 计算添加了代码here

    【讨论】:

    • 我已经用iris 数据集测试了你的代码。考虑模糊性能指数(FPI)和归一化分类熵(NCE)的最小值来确定最佳聚类数。 NCE 一直在增加,而 FPI 则呈下降趋势。我已经更新了我的问题。你能看一下吗?
    • @BappaDas 你能检查一下函数FPINCE 是否正确实现了?具体来说,cn 参数应该是聚类数和观察数。这些数字是否对应cl$membership 的尺寸? IE。对于iris 数据集n = 150 是2,3,4,5,6。
    • 另外,在您的问题中生成参考图像中的值的代码是什么?
    • 我没有编码。我取自this 手稿。
    • 方程因出版物而异(我检查了编辑答案中指定的两个)。答案现在显示了 McBrathney & Moore 1985 的替代方案。但是,他们使用的软件 (FuzMe) 以不同的方式实现了这两个索引,与任何出版物都不匹配。你也想要 FuzMe 选项吗?
    【解决方案2】:

    希望对你有帮助

    library(dplyr)
    library(ggplot2)
    
    f <- function(cl) {
      C <- length(cl$size)
      N <- sum(cl$size)
      mu <- cl$membership
      fpi <- 1 - C / (C - 1) * (1 - sum((mu)^2) / N)
      nce <- N / (N - C) * (-sum(log(mu) * mu) / N)
      c(FPI = fpi, NCE = nce)
    }
    
    data.frame(t(rbind(
      K = 2:6,
      sapply(
        K,
        function(k) f(cmeans(x, k, 20, verbose = TRUE, method = "cmeans"))
      )
    ))) %>%
      pivot_longer(cols = FPI:NCE, names_to = "Index") %>%
      ggplot(aes(x = K, y = value, group = Index)) +
      geom_line(aes(linetype = Index, color = Index)) +
      geom_point() +
      scale_y_continuous(
        name = "FPI",
        sec.axis = sec_axis(~., name = "NCE")
      ) +
      theme(legend.position = "top")
    

    【讨论】:

      猜你喜欢
      • 2019-08-24
      • 1970-01-01
      • 2016-10-12
      • 1970-01-01
      • 2019-06-28
      • 1970-01-01
      • 1970-01-01
      • 2017-02-08
      • 1970-01-01
      相关资源
      最近更新 更多