当前位置:首页 > JavaScript

js实现kmeans

2026-04-06 05:43:51JavaScript

K-means 算法简介

K-means 是一种无监督聚类算法,通过迭代将数据点分配到最近的聚类中心(质心),并重新计算质心位置,直到收敛。适用于数据分组、图像分割等场景。

JavaScript 实现步骤

初始化质心

随机选择 k 个数据点作为初始质心,或采用更智能的初始化方法(如 K-means++)。

js实现kmeans

function initCentroids(data, k) {
  const centroids = [];
  const indices = new Set();
  while (indices.size < k) {
    const idx = Math.floor(Math.random() * data.length);
    if (!indices.has(idx)) {
      centroids.push([...data[idx]]);
      indices.add(idx);
    }
  }
  return centroids;
}

计算欧氏距离

使用欧氏距离衡量数据点与质心的相似度。

function euclideanDistance(a, b) {
  return Math.sqrt(
    a.reduce((sum, val, i) => sum + Math.pow(val - b[i], 2), 0)
  );
}

分配数据点到最近质心

遍历所有数据点,将其分配到距离最近的质心所属的簇。

js实现kmeans

function assignClusters(data, centroids) {
  const clusters = new Array(data.length).fill(-1);
  data.forEach((point, i) => {
    let minDist = Infinity;
    centroids.forEach((centroid, j) => {
      const dist = euclideanDistance(point, centroid);
      if (dist < minDist) {
        minDist = dist;
        clusters[i] = j;
      }
    });
  });
  return clusters;
}

更新质心位置

根据当前簇分配重新计算质心(取簇内点的均值)。

function updateCentroids(data, clusters, k) {
  const centroids = new Array(k).fill().map(() => new Array(data[0].length).fill(0));
  const counts = new Array(k).fill(0);

  data.forEach((point, i) => {
    const cluster = clusters[i];
    point.forEach((val, dim) => {
      centroids[cluster][dim] += val;
    });
    counts[cluster]++;
  });

  return centroids.map((centroid, i) =>
    centroid.map(val => (counts[i] > 0 ? val / counts[i] : val))
  );
}

迭代至收敛

重复分配和更新步骤,直到质心变化小于阈值或达到最大迭代次数。

function kmeans(data, k, maxIterations = 100, threshold = 0.001) {
  let centroids = initCentroids(data, k);
  let prevCentroids = null;
  let iterations = 0;

  while (iterations < maxIterations) {
    const clusters = assignClusters(data, centroids);
    prevCentroids = [...centroids];
    centroids = updateCentroids(data, clusters, k);

    const delta = centroids.reduce(
      (sum, centroid, i) => sum + euclideanDistance(centroid, prevCentroids[i]), 0
    );
    if (delta < threshold) break;
    iterations++;
  }

  return { centroids, clusters: assignClusters(data, centroids) };
}

使用示例

const data = [
  [1, 2], [1, 4], [1, 0],
  [10, 2], [10, 4], [10, 0]
];
const k = 2;
const result = kmeans(data, k);
console.log("质心:", result.centroids);
console.log("簇分配:", result.clusters);

注意事项

  • 数据标准化:若特征量纲差异大,需先标准化(如 Z-score)。
  • K 值选择:可通过肘部法或轮廓系数确定最佳 k
  • 局部最优:多次运行取最优结果,或改用 K-means++ 初始化。

标签: jskmeans
分享给朋友:

相关文章

js实现图片放大缩小

js实现图片放大缩小

实现图片放大缩小的基础方法 使用CSS的transform: scale()属性可以快速实现图片的放大缩小效果。通过JavaScript动态修改该属性值: const img = document.…

js实现报表

js实现报表

使用JavaScript实现报表 在JavaScript中实现报表功能可以通过多种方式完成,常见的方法包括使用原生JavaScript、第三方库(如Chart.js、D3.js)或结合后端数据渲染。以…

链表实现js

链表实现js

链表的基本概念 链表是一种线性数据结构,由一系列节点组成,每个节点包含数据和一个指向下一个节点的指针(单向链表)或两个指针(双向链表)。与数组不同,链表在内存中非连续存储,插入和删除操作更高效,但随机…

js实现视口

js实现视口

js实现视口检测的方法 使用JavaScript检测元素是否进入视口(viewport)可以通过Intersection Observer API或手动计算元素位置实现。以下是两种常见方法: Int…

js怎么实现异步

js怎么实现异步

异步实现方法 JavaScript中实现异步操作主要通过以下几种方式: Promise Promise是ES6引入的异步解决方案,用于处理异步操作的成功或失败状态。 const promise =…

js实现图片

js实现图片

图片加载与显示 在JavaScript中,可以通过Image对象动态加载图片。创建实例后设置src属性触发加载,通过onload回调处理加载完成后的操作: const img = new Ima…