You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为R语言自定义K-means迭代函数添加收敛停止规则?

在K-means函数中添加收敛停止规则的实现方法

这是个很实用的优化需求——K-means确实不需要固定跑满所有迭代次数,当相邻两次迭代的簇分配结果完全一致时,说明算法已经收敛,此时可以提前终止循环,节省计算资源。下面是具体的修改方案:

核心思路

我们需要在迭代过程中记录上一次的簇分配结果,每次计算出新的簇分配后,和上一次做对比:

  • 如果两者完全一致,说明簇结构不再变化,算法收敛,直接终止迭代
  • 如果不一致,继续迭代,直到达到预设的最大迭代次数(防止极端情况下出现无限循环)

修改后的完整代码

# 保留原有的欧氏距离计算函数
euclid <- 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
}

# 修改后的K-means函数,添加收敛停止规则
K_means <- function(x, centers, distFun, maxItter) {
  # 初始化历史记录列表,动态添加迭代结果
  clusterHistory <- list()
  centerHistory <- list()
  
  # 第一次迭代:计算初始簇分配
  distsToCenters <- distFun(x, centers)
  clusters <- apply(distsToCenters, 1, which.min)
  clusterHistory[[1]] <- clusters
  centerHistory[[1]] <- centers
  
  # 开始迭代(从第2次到最大迭代次数)
  for(i in 2:maxItter) {
    # 基于当前簇更新聚类中心
    centers <- apply(x, 2, tapply, clusters, mean)
    centerHistory[[i]] <- centers
    
    # 计算新的簇分配结果
    distsToCenters <- distFun(x, centers)
    new_clusters <- apply(distsToCenters, 1, which.min)
    clusterHistory[[i]] <- new_clusters
    
    # 检查收敛:对比新簇和旧簇是否完全一致
    if(all(new_clusters == clusters)) {
      message(paste("算法在第", i, "次迭代时收敛,提前终止"))
      break
    }
    
    # 更新簇变量,为下一次迭代做准备
    clusters <- new_clusters
  }
  
  # 返回包含所有迭代历史的结果列表
  list(clusters=clusterHistory, centers=centerHistory)
}

关键改动说明

  1. 参数调整:把原函数的nItter改为maxItter,明确这是迭代的上限,而非必须执行的次数
  2. 动态历史记录:将clusterHistory和centerHistory改为空列表,根据实际迭代次数动态添加结果,避免内存浪费
  3. 收敛判断逻辑:每次迭代后用all(new_clusters == clusters)检查簇分配是否完全不变,满足条件则打印收敛信息并终止循环
  4. 迭代流程优化:先更新中心,再计算新簇,确保每次迭代的逻辑连贯

使用示例

和原来的调用方式几乎一致,只是明确maxItter是最大迭代次数:

test=data # 你的输入data.frame
ktest=as.matrix(test) # 转换为矩阵格式
centers <- ktest[sample(nrow(ktest), 5),] # 随机选取5个初始中心
res <- K_means(ktest, centers, euclid, 100) # 最大迭代100次,收敛则提前停止

可选扩展(额外优化)

如果你想更严谨,还可以添加中心变化阈值的判断:比如当所有聚类中心的欧氏距离变化之和小于某个极小值(如1e-6)时,也判定为收敛。不过根据你的需求,簇分配不变的判断已经足够直接有效。

内容的提问来源于stack exchange,提问作者HelpNeeded3

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.09 21:17:50