gpt4 book ai didi

r - 如何计算质心和数据矩阵之间的距离(对于 kmeans 算法)

转载 作者:行者123 更新时间:2023-12-04 02:52:16 24 4
gpt4 key购买 nike

我是聚类和 R 的学生。为了更好地掌握两者,我想计算每次迭代的质心和我的 xy 矩阵之间的距离,直到它“收敛”。如何使用 R 解决第 2 步和第 3 步?

library(fields)
x <- c(3,6,8,1,2,2,6,6,7,7,8,8)
y <- c(5,2,3,5,4,6,1,8,3,6,1,7)

df <- data.frame(x,y) initial matrix
a <- c(3,6,8)
b <- c(5,2,3)

df1 <- data.frame(a,b) # initial centroids

这是我想要做的:
  • I0 <- t(rdist(df, df1))零迭代后
  • 基于最小距离的集群对象
  • 基于聚类平均值确定质心
  • 与 I1 重复

  • 我试过 kmeans功能。但由于某些原因,它会产生那些必须在最后出现的质心。那就是我定义的开始:
    start   <- matrix(c(3,5,6,2,8,3), 3, byrow = TRUE)
    cluster <- kmeans(df,centers = start, iter.max = 1) # one iteration
    kmeans不允许我跟踪质心的运动。因此,我想通过使用 R 应用步骤 2 和 3 来“手动”执行此操作。

    最佳答案

    您的主要问题似乎是如何计算数据矩阵和某些点集(“中心”)之间的距离。

    为此,您可以编写一个函数,该函数将数据矩阵和您的一组点作为输入,并返回数据矩阵中每一行(点)到所有“中心”的距离。

    这是一个这样的函数:

    myEuclid <- function(points1, points2) {
    distanceMatrix <- matrix(NA, nrow=dim(points1)[1], ncol=dim(points2)[1])
    for(i in 1:nrow(points2)) {
    distanceMatrix[,i] <- sqrt(rowSums(t(t(points1)-points2[i,])^2))
    }
    distanceMatrix
    }
    points1是以点为行,维度为列的数据矩阵。 points2是中心矩阵(点再次作为行)。第一行代码只定义了答案矩阵(它的行数与数据矩阵中的行数一样多,列数与中心数一样多)。所以点 i,j结果矩阵中将是从第 i 个点到第 j 个中心的距离。

    然后 for 循环遍历所有中心。对于每个中心,它计算每个点到当前中心的欧几里德距离并返回结果。此行: sqrt(rowSums(t(t(points1)-points2[i,])^2))是欧几里得距离。如果您有任何问题,请仔细检查并查找公式。 (那里的转置主要是为了确保减法是按行进行的)。

    现在您还可以实现 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)
    }

    正如你所看到的,它也是一个非常简单的函数——它需要数据矩阵、中心、距离函数(上面定义的那个)和想要的迭代次数。

    通过为每个点分配最近的中心来定义集群。并且中心被更新为分配给该中心的点的平均值。这是一个基本的k-means算法)。

    让我们试试看。定义一些随机点(在 2d 中,因此列数 = 2)
    mat <- matrix(rnorm(100), ncol=2)

    从该矩阵中分配 5 个随机点作为初始中心:
    centers <- mat[sample(nrow(mat), 5),]

    现在运行算法:
    theResult <- myKmeans(mat, centers, myEuclid, 10)

    以下是第 10 次迭代中的中心:
    theResult$centers[[10]]
    [,1] [,2]
    1 -0.1343239 1.27925285
    2 -0.8004432 -0.77838017
    3 0.1956119 -0.19193849
    4 0.3886721 -1.80298698
    5 1.3640693 -0.04091114

    与已实现的 kmeans 进行比较功能:
    theResult2 <- kmeans(mat, centers, 10, algorithm="Forgy")

    theResult2$centers
    [,1] [,2]
    1 -0.1343239 1.27925285
    2 -0.8004432 -0.77838017
    3 0.1956119 -0.19193849
    4 0.3886721 -1.80298698
    5 1.3640693 -0.04091114

    工作正常。然而,我们的函数跟踪迭代。我们可以像这样绘制前 4 次迭代的进度:
    par(mfrow=c(2,2))
    for(i in 1:4) {
    plot(mat, col=theResult$clusters[[i]], main=paste("itteration:", i), xlab="x", ylab="y")
    points(theResult$centers[[i]], cex=3, pch=19, col=1:nrow(theResult$centers[[i]]))
    }

    Kmeans

    好的。

    然而,这个简单的设计允许更多。例如,如果我们想使用另一种距离(不是欧几里得),我们可以使用任何以数据和中心作为输入的函数。这是相关距离之一:
    myCor <- function(points1, points2) {
    return(1 - ((cor(t(points1), t(points2))+1)/2))
    }

    然后我们可以基于这些来做 Kmeans:
    theResult <- myKmeans(mat, centers, myCor, 10)

    4 次迭代的结果图片如下所示:

    enter image description here

    即使你指定了 5 个集群 - 最后还剩下 2 个。这是因为对于 2 维,相关性可能必须与值 - +1 或 -1。然后在寻找集群时,每个点都被分配到一个中心,即使它与多个中心的距离相同 - 选择第一个。

    无论如何,这现在已经超出了范围。底线是有许多可能的距离度量,一个简单的函数允许您使用任何您想要的距离并跟踪迭代结果。

    关于r - 如何计算质心和数据矩阵之间的距离(对于 kmeans 算法),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27082378/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com