【问题标题】:How to find the right cluster algorithm?如何找到合适的聚类算法?
【发布时间】:2015-01-21 07:13:17
【问题描述】:

我想找到一种可以规避 k-Means 一些缺点的算法:

给定:

x<- c(4,4,5,5,6,7,8,9,9,10,2,3,3,4,5,6,6,7,8,8)
y<- c(2,3,3,4,4,5,5,7,6,8,4,5,6,5,7,8,9,9,9,10)

matrix<-cbind(x,y)# defining matrix
Kmeans<-kmeans(matrix,centers=2) # with 3 centroids

plot(x,y,col=Kmeans$cluster,pch=19,cex=2)
points(Kmeans$centers,col=1:3,pch=3,cex=3,lwd=3)

在这里我想要一个算法将数据聚类成两个簇,从左角到右角被对角线划分。

【问题讨论】:

  • 这不会最大程度地减少组内惰性,对吗?因此,我认为您正在寻找不聚类的东西。你有没有想过拟合两条线?或者尝试拟合高斯混合?真正的问题是:为什么你认为你的团队应该是这样的?
  • 嗯,这似乎是一个自然的选择。我的意思是显然有一些线性。但是我想找到一个集群算法,它可能接近我对这两个集群的感觉。
  • 我认为在这种情况下混合高斯可能会很好。该算法将自动选择您需要的集群数量(此处为 2)及其相关结构(此处为 45° 拉伸)。我还不知道你需要什么包,但应该不难找到。

标签: r cluster-analysis k-means


【解决方案1】:

尝试mclust 包中的Mclust,它会尝试在您的数据上拟合高斯混合。 默认行为:

mc = Mclust(matrix);
points(t(mc$parameters$mean));
plot(mc);

.. 将找到 4 个组,但您可以将其强制为 2 或强制将高斯的相关结构向正确的方向拉伸。

请注意,除非您非常了解您希望他们成为 2 等的原因,否则很难解释和证明您的组的含义。

【讨论】:

    【解决方案2】:

    您的要求可以通过多种方式解决。这里有两个:

    1. 第一种方法是简单地定义集群的分隔线。既然您知道应如何对您的点进行分组(按一条线),您就可以使用它。

    如果你想让你的线从原点开始,那么只需检查 x > y:

    x<- c(4,4,5,5,6,7,8,9,9,10,2,3,3,4,5,6,6,7,8,8)
    y<- c(2,3,3,4,4,5,5,7,6,8,4,5,6,5,7,8,9,9,9,10)
    
    thePoints <- cbind(x,y)
    
    
    as.integer(thePoints[,1] > thePoints[,2])
    [1] 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0
    

    这会将对角线上方的点(从 0 开始)放在一组中,而将其他点放在另一组中。请记住,如果您的线路可能不通过原点 (0),那么您必须稍微修改此示例。

    1. 具有相关距离的 Kmeans:

    K-means 函数:

    myKmeans <- function(x, centers, distFun, nItter=10) {
        clusterHistory <- vector(nItter, mode="list")
        centerHistory <- vector(nItter, mode="list")
    
        for(i in 1:nItter) {
            distsToCenters <- distFun(x, centers)
            clusters <- apply(distsToCenters, 1, which.min)
            centers <- apply(x, 2, tapply, clusters, mean)
            # Saving history
            clusterHistory[[i]] <- clusters
            centerHistory[[i]] <- centers
        }
    
        list(clusters=clusterHistory, centers=centerHistory)
    }
    

    与相关距离:

    myCor <- function(points1, points2) {
        return(1 - ((cor(t(points1), t(points2))+1)/2))
    }
    
    theResult <- myKmeans(mat, centers, myCor, 10)
    

    也显示了HERE

    这两种解决方案的外观如下:

    plot(points, col=as.integer(points[,1] > points[,2])+1, main="Using a line", xlab="x", ylab="y")
    plot(points, col=theResult$clusters[[10]], main="K-means with correlation clustering", xlab="x", ylab="y")
    points(theResult$centers[[10]], col=1:2, cex=3, pch=19)
    

    所以更多的是关于你使用什么样的距离度量,而不是关于 K-means 的某种缺陷。

    您还可以找到具有 R 相关距离的 K-means 的更好实现,而不是使用我在此处提供的实现。

    【讨论】:

    • 请注意,如果您使用其他距离函数,k-means 可能无法收敛。特别是对于绝对相关距离,我可以给出一个反例,为什么 mean 不适合使用。在这个特定的数据集中,我也不相信真的有两个集群。鉴于值是整数并且数据集很小,这可能只是机会。设计聚类以适应您的假设是一种过度拟合
    • 感谢您的富有洞察力的评论@Anony-Mousse。关于1-((cor+1)/2)距离的使用:它并不是真正的绝对相关,而是相关转换为0到1之间的距离。它应该与缩放点的欧几里得距离成正比。我真的不明白为什么它不能收敛,但如果你有一个反例 - 那会解决它。
    • 关于过拟合 - 如果我们假设数据具有某种“集群结构”并且需要发现“真实”数量的集群,那么您是正确的。然而,聚类也可以是任意的。我们可以找到几个真实世界的例子,其中这种聚类(按对角线)是有意义的。即 - 对象是人的头。 x=白发的数量,y=非白发的数量。那么根据 x>y 对人进行聚类是有意义的。因为这是关于我们所遇到问题的先验知识。它高于过拟合。想出组和方法不需要任何拟合。
    • 相关性(尤其是全局相关性)并不意味着以这种方式强制聚类有意义。这意味着我们应该减少和去相关特征......因为否则,您对相关特征的权重会加倍;换句话说,白发的差异也意味着非白发的差异,你不应该计算两次。
    • 在上面的例子中,简单地对x-y 进行聚类可能已经可以解决问题了,如果理论支持使用差异应该没问题。
    猜你喜欢
    • 2013-12-11
    • 2019-01-02
    • 2016-10-14
    • 2017-07-23
    • 2019-08-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-19
    相关资源
    最近更新 更多