我无法完全理解K-Means++ 算法。我对如何选择第一个k
质心很感兴趣,即初始化,其余部分就像原始K-Means 算法一样。
- 使用的概率函数是基于距离还是高斯?
- 同时,选择最远的点(从其他质心)作为新质心。
我将欣赏一步一步的解释和一个例子。维基百科中的那个不够清楚。还有一个很好注释的源代码也会有所帮助。如果您使用 6 个阵列,请告诉我们哪个阵列用于什么用途。
我无法完全理解K-Means++ 算法。我对如何选择第一个k
质心很感兴趣,即初始化,其余部分就像原始K-Means 算法一样。
我将欣赏一步一步的解释和一个例子。维基百科中的那个不够清楚。还有一个很好注释的源代码也会有所帮助。如果您使用 6 个阵列,请告诉我们哪个阵列用于什么用途。
有趣的问题。感谢您让我注意到这篇论文 - K-Means++:小心播种的优势
简单来说,聚类中心最初是从输入观察向量集中随机选择的,如果不靠近任何先前选择的中心,则选择向量的概率x
很高。x
这是一个一维的例子。我们的观察结果是 [0, 1, 2, 3, 4]。令第一个中心c1
为 0。下一个聚类中心 为 x 的概率与c2
成正比||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
编辑说明: 的输出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
一个班轮。
假设我们需要选择 2 个聚类中心,而不是随机选择它们{就像我们在简单的 k 均值中所做的},我们将随机选择第一个,然后找到离第一个中心最远的点{这些点最有可能做不属于第一个聚类中心,因为它们离它很远}并在这些远点附近分配第二个聚类中心。
我已经根据 Toby Segaran 的《集体智能》一书和此处提供的 k-menas++ 初始化准备了 k-means++ 的完整源代码实现。
实际上,这里有两个距离函数。对于初始质心,使用基于 numpy.inner 的标准质心,然后使用 Pearson 固定质心。也许 Pearson 也可以用于初始质心。他们说这样更好。
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'
数据.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