K-均值聚类是流行、经典、简单的聚类方法之一。聚类是非监督学习的一种方法,也是常用的统计数据分析技术,应用领域很广,涉及机器学习、数据挖掘、模式识别、图像分析和生物信息学等。
●下载源码
●下载样例程序
上面的源码是Accord.NET Framework的一部分.Accord.NET Framework是一个开发机器学习,计算机视觉,计算机音频,统计和数学应用的框架.它是基于已有的强大AForge.NET Framework开发的.请参考starting guide了解更多细节.最新的框架包扩了最新的下载源码并带有很多其他的统计和机器学习工具(statistics and machine learning tools.).
介绍
在统计和机器学习中, K-均值算法是一种聚类分析方法,它将n个观察对象分类到k个聚类,每个观察对象将被分到与均值最接近的聚类中.在其最常见的形式中.K-均值是一种通过反复迭代直至收敛到确定值的迭迭代贪婪算法.
图解K-均值算法
算法如下:
1)首先为聚类任意选出k个初始化的的质心.每个个观察对象被分类到与质心最近的聚类中,
2)接着使用委派的观察对象聚类的均值重新计算质心.
3)用新计算出的质心对观察对象重新聚类如1)那样分派到与质心最近的聚类中.
4)重复2) , 3)步骤直至聚类质心不再变化,或者小于给定的阈值.
(注:意译,本意请参考原文)
上面是K-均值聚类算法常见的形式。还有其他的改进和拓展的算法,称作劳合社的算法Lloyd’s algorithm.
劳合社算法
1.把k个点表示被聚类的对象位置,这些点表示相应初始组质心
2.分配每个对象到离质心最近的组里
3.当所有的对象被分配完后,重新计算k个质心的位置
4.重复2,3步骤直到质心不再移动.
这些过程将对象分类到不同组,组间的最小化度量可以计算出来
源码
源码使用了Accord.NET,而且是框架的一部分.在当前本版(2.1.2) ,如和k-均值算法相关的类在theAccord. MachineLearning空间里
K-均值算法的类图
KMeans类k-均值算法的主类,算法在用Compute(double[][] data, double threshold)方法实现,Compute输入是一系列的观察对象和一个用来决定方法如何结束的收敛阈值
现实是直接明朗的,没有使用特别的技术来避免收敛难题.以后更多的技术会加入实现.所以请为最新修订的算法源码下载最新的Accord.NET框架 使用源码为了使用源码,创建一个KMeans类新实例,传递期望的聚类给构造器.另外,你可能传递一个距离函数用来聚类距离度量.默认使用的是平方欧氏距离(square Euclidean distance).
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
// Declare some observations
double
[][] observations =
{
new
double
[] { -5, -2, -1 },
new
double
[] { -5, -5, -6 },
new
double
[] { 2, 1, 1 },
new
double
[] { 1, 1, 2 },
new
double
[] { 1, 2, 2 },
new
double
[] { 3, 1, 2 },
new
double
[] { 11, 5, 4 },
new
double
[] { 15, 5, 6 },
new
double
[] { 10, 5, 6 },
};
// Create a new K-Means algorithm with 3 clusters
KMeans kmeans =
new
KMeans(3);
// Compute the algorithm, retrieving an integer array
// containing the labels for each of the observations
int
[] labels = kmeans.Compute(observations);
// As a result, the first two observations should belong to the
// same cluster (thus having the same label). The same should
// happen to the next four observations and to the last three.
|
样例应用
在计算机视觉中, K-均值聚类算法通常被用在图像分割(image segmentation).分割结果被用来边界检测(border detection) 和目标识别(object recognition).样品应用使用标准平方欧氏距离度量RGB像素颜色空间来分割图像.然而还有其他更好的距离度量方法来处理图像分割,如加权距离其他颜色空间.这里就不列举在应用中.
原图(来自Ossi Petruska Flickr page*)
为了展示图像分割,首先将图片变换成像素值数组.图片会被一个个像素的逐步读进一个不规则数组,数组的类型的一个长度为三的双精度浮点数数组.每个双精度浮点数数组储存着范围在[-1, 1]的3个RGB值.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
|
///
/// Divides the input data into K clusters.
///
public
int
[] Compute(
double
[][] data,
double
threshold)
{
int
k =
this
.K;
int
rows = data.Length;
int
cols = data[0].Length;
// pick K unique random indexes in the range 0..n-1
int
[] idx = Accord.Statistics.Tools.Random(rows, k);
// assign centroids from data set
this
.centroids = data.Submatrix(idx);
// initial variables
int
[] count =
new
int
[k];
int
[] labels =
new
int
[rows];
double
[][] newCentroids;
do
// main loop
{
// Reset the centroids and the
// cluster member counters'
newCentroids =
new
double
[k][];
for
(
int
i = 0; i < k; i++)
{
newCentroids[i] =
new
double
[cols];
count[i] = 0;
}
// First we will accumulate the data points
// into their nearest clusters, storing this
// information into the newClusters variable.
// For each point in the data set,
for
(
int
i = 0; i < data.Length; i++)
{
// Get the point
double
[] point = data[i];
// Compute the nearest cluster centroid
int
c = labels[i] = Nearest(data[i]);
// Increase the cluster's sample counter
count[c]++;
// Accumulate in the corresponding centroid
double
[] centroid = newCentroids[c];
for
(
int
j = 0; j < centroid.Length; j++)
centroid[j] += point[j];
}
// Next we will compute each cluster's new centroid
// by dividing the accumulated sums by the number of
// samples in each cluster, thus averaging its members.
for
(
int
i = 0; i < k; i++)
{
double
[] mean = newCentroids[i];
double
clusterCount = count[i];
for
(
int
j = 0; j < cols; j++)
mean[j] /= clusterCount;
}
// The algorithm stops when there is no further change in
// the centroids (difference is less than the threshold).
if
(centroids.IsEqual(newCentroids, threshold))
break
;
// go to next generation
centroids = newCentroids;
}
while
(
true
);
// Compute cluster information (optional)
for
(
int
i = 0; i < k; i++)
{
// Extract the data for the current cluster
double
[][] sub = data.Submatrix(labels.Find(x => x == i));
// Compute the current cluster variance
covariances[i] = Statistics.Tools.Covariance(sub, centroids[i]);
// Compute the proportion of samples in the cluster
proportions[i] = (
double
)sub.Length / data.Length;
}
// Return the classification result return labels;
}
|
在那个数组像素值进行聚类后,每个像素有个相关的聚类标签.标签的值将会被其相应的聚类质心交换.当应用程序的Run按钮被点击时,下面的代码就会被调用.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
private
void
btnRun_Click(
object
sender, EventArgs e)
{
// Retrieve the number of clusters
int
k = (
int
)numClusters.Value;
// Load original image
Bitmap image = Properties.Resources.leaf;
// Transform the image into an array of pixel values
double
[][] pixels = image.ToDoubleArray();
// Create a K-Means algorithm using given k and a
// square euclidean distance as distance metric.
KMeans kmeans =
new
KMeans(k, Distance.SquareEuclidean);
// Compute the K-Means algorithm until the difference in
// cluster centroids between two iterations is below 0.05
int
[] idx = kmeans.Compute(pixels, 0.05);
// Replace every pixel with its corresponding centroid
pixels.ApplyInPlace((x, i) => kmeans.Clusters.Centroids[idx[i]]);
// Show resulting image in the picture box
pictureBox.Image = pixels.ToBitmap(image.Width, image.Height);
}
|
在分割后,获得如下图片结果:
图像标本,在k = 5的K-均值聚类处理后
图像在k = 10的K-均值聚类处理后
以上样本图像已经Ossi Petruska的Creative Commons Attribution-NonCommercial-ShareAlike 2.0 Generic授权
总结
K-均值聚类是一种非常简单,流行的聚类方法,.这里展现的样品实现使用了in Accord.NET框架.就如所见.随着通过代理函数或lambda表达式实现的自定义函数,聚类函数很容易被拓展.可以用到不同环境,如图像分割,而不用过多修改.一个关于改进的建议:正如Charles Elkan.的论文《使用三角不等式加速K-均值算法》(“Using the triangle inequality to accelerate k-means”)所建议聚类方法可以变得更快.
在下一篇文章中,我们将会看到在高斯混合模型怎样使用K-均值算法来初始化期望-最大算法来评估高斯混合密度.这些文章将会成为连续致密隐马尔可夫模型的基础.
致谢
感谢Antonino Porcino提供了第一个版本的代码和其有价值的他算法和方法。
参考文献
●[1] Matteo Matteucci. “Tutorial on Clustering Algorithms,” Politecnico di Milano,http://home.dei.polimi.it/matteucc/Clustering/tutorial_html/kmeans.html(acessed October 4, 2010).
●[2] Teknomo, Kardi. “K-Means Clustering Tutorials,”http://people.revoledu.com/kardi/ tutorial/kMean/(acessed October 6, 2010).
●[3] Wikipedia contributors, “Cluster analysis,”Wikipedia, The Free Encyclopedia,http://en.wikipedia.org/wiki/Cluster_analysis(accessed October 4, 2010).
●[4] Wikipedia contributors, “K-means clustering,”Wikipedia, The Free Encyclopedia,http://en.wikipedia.org/wiki/K-means_clustering(accessed October 4, 2010).