23

我无法完全理解k-means ++算法。我对如何选取前k个质心有兴趣(其余部分与原始k-means相似)。k-means ++究竟如何工作?

  1. 是基于距离还是高斯使用的概率函数?
  2. 在同一时间内,最长距离点(从其他质心)被挑选出一个新的质心。

我会欣赏一步一步的解释和一个例子。维基百科中的那个不够清楚。另外一个非常好的评论源代码也会有所帮助。如果你正在使用6个阵列,那么请告诉我们哪个是什么。

+6

可能是http://stats.stackexchange.com/ – Chase 2011-03-28 23:47:37

回答

34

有趣的问题。感谢您将本文引入我的视线。 PDF link here of the original paper.

简单来说,聚类中心最初从一组输入观察矢量的,其中选择载体x的概率为高,如果x不靠近任何先前选择的中心随机选择。

这里是一个一维的例子。我们的观察结果是[0,1,2,3,4]。让第一个中心c1为0.下一个聚类中心c2为x的概率与||c1-x||^2成比例。所以P(c2 = 1)= 1a,P(c2 = 2)= 4a,P(c2 = 3)= 9a,P(c2 = 4)= 16a,其中a = 1 /(1 + 4 + 9 + 16)。

假设c2 = 4。那么,P(c3 = 1)= 1a,P(c3 = 2)= 4a,P(c3 = 3)= 1a,其中a = 1 /(1 + 4 + 1)。

我编写了Python中的初始化过程;我不知道这是否有助于你。

def initialize(X, K): 
    C = [X[0]] 
    for k in range(1, K): 
     D2 = scipy.array([min([scipy.inner(c-x,c-x) for c in C]) for x in X]) 
     probs = D2/D2.sum() 
     cumprobs = probs.cumsum() 
     r = scipy.rand() 
     for j,p in enumerate(cumprobs): 
      if r < p: 
       i = j 
       break 
     C.append(X[i]) 
    return C 

EDIT与澄清:的cumsum输出给我们的边界来划分区间[0,1]。这些分区的长度等于相应点被选为中心的概率。那么,因为r在[0,1]之间被一致地选择,所以它将恰好落入这些间隔中的一个(因为break)。所述for环进行检查以查看r是在哪个分区

例:

probs = [0.1, 0.2, 0.3, 0.4] 
cumprobs = [0.1, 0.3, 0.6, 1.0] 
if r < cumprobs[0]: 
    # this event has probability 0.1 
    i = 0 
elif r < cumprobs[1]: 
    # this event has probability 0.2 
    i = 1 
elif r < cumprobs[2]: 
    # this event has probability 0.3 
    i = 2 
elif r < cumprobs[3]: 
    # this event has probability 0.4 
    i = 3 
+0

的好候选谢谢您的回答。我检查了Python代码。 – 2011-03-29 08:50:57

+0

因此,对于X中的每个点,我们生成一个概率。然后cumsum应该加重这些概率。我认为这个想法是将更多的权重放在概率更高的点上,所以当我们选择“随机矩心选择”时,我们会选择它们。但是我们怎么知道我们应该在哪些点上放更多的权重(?) - 我们还没有对probs数组进行排序,并且cumsum函数使得数组末尾的权重更大(cumsum定义)。 – 2011-03-29 09:46:21

+0

我的意思是说,cumsum具有特定的行为来累积到右侧(x1 2011-03-29 11:09:06

2

我已经准备的基础上,书“集体智慧”由托比·西格伦和第k k均值++一个完整的源执行这里提供的设置++初始化。

事实上,这里有两个距离函数。对于初始质心,使用基于numpy.inner的标准质心,然后使用Pearson 1的质心固定。也许Pearson one也可以用于初始质心。他们说这样更好。

from __future__ import division 

def readfile(filename): 
    lines=[line for line in file(filename)] 
    rownames=[] 
    data=[] 
    for line in lines: 
    p=line.strip().split(' ') #single space as separator 
    #print p 
    # First column in each row is the rowname 
    rownames.append(p[0]) 
    # The data for this row is the remainder of the row 
    data.append([float(x) for x in p[1:]]) 
    #print [float(x) for x in p[1:]] 
    return rownames,data 

from math import sqrt 

def pearson(v1,v2): 
    # Simple sums 
    sum1=sum(v1) 
    sum2=sum(v2) 

    # Sums of the squares 
    sum1Sq=sum([pow(v,2) for v in v1]) 
    sum2Sq=sum([pow(v,2) for v in v2])  

    # Sum of the products 
    pSum=sum([v1[i]*v2[i] for i in range(len(v1))]) 

    # Calculate r (Pearson score) 
    num=pSum-(sum1*sum2/len(v1)) 
    den=sqrt((sum1Sq-pow(sum1,2)/len(v1))*(sum2Sq-pow(sum2,2)/len(v1))) 
    if den==0: return 0 

    return 1.0-num/den 

import numpy 
from numpy.random import * 

def initialize(X, K): 
    C = [X[0]] 
    for _ in range(1, K): 
     #D2 = numpy.array([min([numpy.inner(c-x,c-x) for c in C]) for x in X]) 
     D2 = numpy.array([min([numpy.inner(numpy.array(c)-numpy.array(x),numpy.array(c)-numpy.array(x)) for c in C]) for x in X]) 
     probs = D2/D2.sum() 
     cumprobs = probs.cumsum() 
     #print "cumprobs=",cumprobs 
     r = rand() 
     #print "r=",r 
     i=-1 
     for j,p in enumerate(cumprobs): 
      if r 0: 
     for rowid in bestmatches[i]: 
      for m in range(len(rows[rowid])): 
      avgs[m]+=rows[rowid][m] 
     for j in range(len(avgs)): 
      avgs[j]/=len(bestmatches[i]) 
     clusters[i]=avgs 

    return bestmatches 

rows,data=readfile('/home/toncho/Desktop/data.txt') 

kclust = kcluster(data,k=4) 

print "Result:" 
for c in kclust: 
    out = "" 
    for r in c: 
     out+=rows[r] +' ' 
    print "["+out[:-1]+"]" 

print 'done' 

的data.txt:

 
p1 1 5 6 
p2 9 4 3 
p3 2 3 1 
p4 4 5 6 
p5 7 8 9 
p6 4 5 4 
p7 2 5 6 
p8 3 4 5 
p9 6 7 8 

+0

代码在此处可用:[a-algorithms](http://code.google.com/p/a-algorithms/source/browse/ #svn%2Ftrunk%2Fk-means%2B%2B)用于CPython和IronPython。 – 2011-04-05 15:00:43

1

一行。假设我们需要选择2个聚类中心,而不是随机选择它们(就像我们用简单的k意味着的那样),我们将随机选择第一个聚类中心,然后找到离第一个中心最远的点{这些点最有可能做到不属于第一个聚类中心,因为它们距离它很远},并将第二个聚类中心分配在这些远点附近。