crwgregory/php-kmeans

PHP 的 K-Means 算法

1.0.0 2015-12-03 09:55 UTC

This package is not auto-updated.

Last update: 2024-09-18 20:14:42 UTC


README

聚类变得简单

k-means 聚类是一种向量量化方法,最初来自信号处理,在数据挖掘中的聚类分析中很受欢迎。k-means 聚类旨在将 n 个观测值划分为 k 个聚类,其中每个观测值属于最近的均值所在的聚类,作为该聚类的原型。这导致数据空间被划分为 Voronoi 单元。

更多信息请参阅 维基百科

PHP K-Means,正如其名所示,是 K-Means 和 K-Means++ 算法的 PHP 平台实现。它可以在无限维数下工作。

用法

给定以下 R² 的点

$points = [
    [80,55],[86,59],[19,85],[41,47],[57,58],
	[76,22],[94,60],[13,93],[90,48],[52,54],
	[62,46],[88,44],[85,24],[63,14],[51,40],
	[75,31],[86,62],[81,95],[47,22],[43,95],
	[71,19],[17,65],[69,21],[59,60],[59,12],
	[15,22],[49,93],[56,35],[18,20],[39,59],
	[50,15],[81,36],[67,62],[32,15],[75,65],
	[10,47],[75,18],[13,45],[30,62],[95,79],
	[64,11],[92,14],[94,49],[39,13],[60,68],
	[62,10],[74,44],[37,42],[97,60],[47,73],
];

我们想要找到 3 个聚类

// create a 2 dimentionnal space and fill it
$space = new KMeans\Space(2);

foreach ($points as $point)
    $space->addPoint($point);

 // resolve 3 clusters
$clusters = $space->solve(3);

现在我们可以检索每个聚类的质心(其点的平均值)以及其中的所有点

foreach ($clusters as $i => $cluster)
    printf("Cluster %d [%d,%d]: %d points\n", $i, $cluster[0], $cluster[1], count($cluster));

输出示例

Cluster 0 [79,58]: 18 points
Cluster 1 [57,19]: 19 points
Cluster 2 [31,66]: 13 points

注意!

K-Means 算法是非确定性的,因此使用相同的数据多次运行时可能会得到不同的结果。空间中添加的点越多,结果越准确。

强烈建议在使用此库之前仔细阅读维基百科文章。

K-Means++

在触发 Kmeans\Space::solve 方法时,您可以提供替代的种子方法,以使用 David Arthur 和 Sergei Vassilvitskii 算法 初始化聚类,以避免产生较差的聚类结果。

// resolve 3 clusters using David Arthur and Sergei Vassilvitskii seeding algorithm
$clusters = $space->solve(3, KMeans\Space::SEED_DASV);

如何使用

获取点/聚类的坐标

$x = $point[0];
$y = $point[1];

// or

list($x,$y) = $point->getCoordinates();

列出空间/聚类的所有点

foreach ($cluster as $point)
    printf('[%d,%d]', $point[0], $point[1]);

将数据附加到点

$space->addPoint($coordinate, $data);

检索点数据

$data = $space[$point];

观察算法运行

可以通过传递给 Kmeans\Space::solve 的回调函数来监控每次迭代的步骤

$clusters = $space->solve(3, KMeans\Space::SEED_DEFAULT, function($space, $clusters) {
    static $iterations = 0;

    printf("Iteration: %d\n", ++$iterations);

    foreach ($clusters as $i => $cluster)
        printf("Cluster %d [%d,%d]: %d points\n", $i, $cluster[0], $cluster[1], count($cluster));
});