当前位置:首页 > 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实现类

JavaScript 实现类的几种方式 JavaScript 是一种基于原型的语言,但在 ES6 之后引入了 class 语法糖,使得实现类更加直观。以下是几种常见的实现方式: 使用构造函数 传统的…

js实现求导

js实现求导

实现数值求导的方法 在JavaScript中实现求导通常采用数值方法,因为JavaScript不是符号计算语言。以下是常见的数值微分方法: 中心差分法 中心差分法提供较高精度的导数近似: func…

js实现轮播代码

js实现轮播代码

基础轮播实现 使用HTML、CSS和JavaScript创建一个简单的轮播效果。HTML部分定义轮播容器和图片元素。 <div class="carousel"> <div c…

js实现的游戏

js实现的游戏

JavaScript 游戏开发基础 JavaScript 是开发网页游戏的流行选择,因其无需插件即可在浏览器中运行。以下是一些关键技术和资源: HTML5 Canvas Canvas 提供了绘制图形…

实现继承js

实现继承js

实现继承的方式 在JavaScript中,实现继承可以通过多种方式完成,每种方式都有其优缺点。以下是几种常见的实现继承的方法: 原型链继承 原型链继承是最基本的继承方式,通过将子类的原型指向父类的实…

js 实现图片 放大

js 实现图片 放大

使用 CSS transform 实现图片放大 通过 CSS 的 transform: scale() 属性可以实现图片的平滑放大效果。结合 JavaScript 监听鼠标事件控制放大状态: con…