Python k-means算法

49
我正在寻找使用 Python 实现 k-means 算法的示例,以对我的坐标数据库进行聚类和缓存。

1
我对图像做了类似的实现。你可以使用2D数组代替RGB值。这很朴素,但对我来说有效。https://github.com/keremgocen/pattern-recog-notes。 - Kerem
8个回答

57

更新:(在原始答案发布11年后,现在是时候进行更新了。)

首先,您确定要使用k-means吗?此页面提供了一些不同聚类算法的出色图形摘要。我建议除了图形之外,特别关注每种方法所需的参数,并决定是否可以提供所需的参数(例如,k-means需要聚类数量,但您可能在开始聚类之前不知道它)。

以下是一些资源:

旧答案:

Scipy的聚类实现效果很好,其中包括k-means实现。

还有scipy-cluster,它执行凝聚聚类;这具有一个优点,即您不需要提前决定聚类数量。


为什么在k-means算法中scipy比sklearn更受欢迎?最近我使用了两者,但我发现我更喜欢sklearn的实现方式。 - shallow_water

29

SciPy的kmeans2()存在一些数值问题:其他人已经报告了错误消息,如版本0.6.0中出现的“Matrix is not positive definite - Cholesky decomposition cannot be computed”,我在版本0.7.1中也遇到了相同的问题。

目前,我建议使用PyCluster代替。 示例用法:

>>> import numpy
>>> import Pycluster
>>> points = numpy.vstack([numpy.random.multivariate_normal(mean, 
                                                            0.03 * numpy.diag([1,1]),
                                                            20) 
                           for mean in [(1, 1), (2, 4), (3, 2)]])
>>> labels, error, nfound = Pycluster.kcluster(points, 3)
>>> labels  # Cluster number for each point
array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0,
       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2,
       2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2], dtype=int32)
>>> error   # The within-cluster sum of distances for the solution
1.7721661785401261
>>> nfound  # Number of times this solution was found
1

2
似乎scipy集群kmeans函数不接受距离方法并始终使用欧几里得距离。使用PyCluster的另一个原因? - Sid
只需点击所提到的错误即可...我在您的示例中看到了群集分组,但是您能否获取群集“中心”? (Translated text: "只需点击所提到的错误即可...我在您的示例中看到了群集分组,但是您能否获取群集“中心”?") - monkut
使用 numpy.vstack([points[labels == i].mean(0) for i in range(labels.max() + 1)]) 命令获取聚类中心。@monkup - Vebjorn Ljosa
1
你可以通过使用关键字参数minit='points'来消除kmeans2中的错误。 - forefinger

21

对于连续数据,k-means非常简单。

您需要列出均值列表,并针对每个数据点,找到其最接近的平均值并将新数据点平均到该平均值。您的均值将代表输入数据中最近的显着点簇。

我持续地进行平均处理,因此无需拥有旧数据即可获得新的平均值。给定旧平均值k,下一个数据点x和常数n(要保留过去数据点的数量),新平均值为:

k*(1-(1/n)) + n*(1/n)

这是完整的Python代码

from __future__ import division
from random import random

# init means and data to random values
# use real data in your code
means = [random() for i in range(10)]
data = [random() for i in range(1000)]

param = 0.01 # bigger numbers make the means change faster
# must be between 0 and 1

for x in data:
    closest_k = 0;
    smallest_error = 9999; # this should really be positive infinity
    for k in enumerate(means):
        error = abs(x-k[1])
        if error < smallest_error:
            smallest_error = error
            closest_k = k[0]
        means[closest_k] = means[closest_k]*(1-param) + x*(param)

你可以在所有数据通过后打印平均值,但实时观察它的变化会更加有趣。我将其用于20毫秒音频信号的频率包络,并在与它交互了一两分钟后,它对短“a”元音、长“o”元音和“s”辅音有了一致的分类结果。真是奇怪!


这是一个很棒的在线学习kmeans算法!但是代码的最后一行存在一个错误。应该将此行的一个制表符删除:means[closest_k] = means[closest_k](1-param) + x(param) - lai

6

5

1

SciKit Learn的KMeans()是在Python中应用k-means聚类的最简单方法。拟合聚类很简单:

kmeans = KMeans(n_clusters=2, random_state=0).fit(X)

这段代码展示了如何存储质心坐标并预测一组坐标的聚类。

>>> from sklearn.cluster import KMeans
>>> import numpy as np
>>> X = np.array([[1, 2], [1, 4], [1, 0],
...               [4, 2], [4, 4], [4, 0]])
>>> kmeans = KMeans(n_clusters=2, random_state=0).fit(X)
>>> kmeans.labels_
array([0, 0, 0, 1, 1, 1], dtype=int32)
>>> kmeans.predict([[0, 0], [4, 4]])
array([0, 1], dtype=int32)
>>> kmeans.cluster_centers_
array([[ 1.,  2.],
       [ 4.,  2.]])

(来自上面链接的SciKit Learn文档)

0

0

您也可以使用GDAL,它具有许多函数来处理空间数据。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接