K-Means ++アルゴリズム を完全に理解できません。最初のk
セントロイドがどのように選択されるか、つまり、残りが元の K-Meansアルゴリズム と同じように初期化されることに正確に興味があります。
ステップバイステップの説明と例をいただければ幸いです。 Wikipedia のものは十分に明確ではありません。また、非常によくコメントされたソースコードも役立ちます。 6つの配列を使用している場合は、どの配列が何のためのものか教えてください。
興味深い質問です。この文書をお読みいただきありがとうございます K-Means ++:慎重なシードの利点
簡単に言うと、クラスターの中心は最初に入力観測ベクトルのセットからランダムに選択されます。x
が以前に選択した中心の近くにない場合、ベクトルx
を選択する確率は高くなります。
これは1次元の例です。私たちの観察は[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
明確化した編集:cumsum
の出力は、区間[0,1]を分割するための境界を提供します。これらのパーティションの長さは、対応するポイントが中心として選択される確率と同じです。したがって、r
は[0,1]の間で均一に選択されるため、これらの間隔の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著の「Collective Intelligence」と、ここで提供されるk-menas ++初期化に基づいて、k-means ++の完全なソース実装を準備しました。
実際、ここには2つの距離関数があります。初期の重心にはnumpy.innerに基づく標準の重心が使用され、次に重心の固定にはピアソンの重心が使用されます。おそらく、ピアソンの1つを最初の重心に使用することもできます。彼らはそれが良いと言います。
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