punkty danych: (7,1), (3,4), (1,5), (5,8), (1,3), (7,8), (8,2), (5,9) , (8,0)
l = 2 // współczynnik nadpróbkowania
k = 3 // nie. pożądanych klastrów
Krok 1:
Załóżmy, że pierwszym centroidem jest to . C{c1}={(8,0)}X={x1,x2,x3,x4,x5,x6,x7,x8}={(7,1),(3,4),(1,5),(5,8),(1,3),(7,8),(8,2),(5,9)}
Krok 2:
ϕX(C) to suma wszystkich najmniejszych 2-normowych odległości (odległość euklidesowa) od wszystkich punktów ze zbioru do wszystkich punktów z . Innymi słowy, dla każdego punktu znaleźć odległość do najbliższego punktu w w końcowej obliczeniowych suma wszystkich tych minimalnych odległościach, po jednym dla każdego punktu .XCXCX
Oznacz za pomocą jako odległość od do najbliższego punktu w . Mamy wtedy .d2C(xi)xiCψ=∑ni=1d2C(xi)
W kroku 2 zawiera pojedynczy element (patrz krok 1), a jest zbiorem wszystkich elementów. Zatem w tym kroku to po prostu odległość między punktem w i . Zatem .CXd2C(xi)Cxiϕ=∑ni=1||xi−c||2
ψ=∑ni=1d2(xi,c1)=1.41+6.4+8.6+8.54+7.61+8.06+2+9.4=52.128
log(ψ)=log(52.128)=3.95=4(rounded)
Należy jednak pamiętać, że w kroku 3 stosowana jest ogólna formuła, ponieważ będzie zawierał więcej niż jeden punkt.C
Krok 3:
W pętli wykonywane w uprzednio obliczonej.log(ψ)
Rysunki nie są takie, jak zrozumiałeś. Rysunki są niezależne, co oznacza, że będzie wykonywać losowanie dla każdego punktu . Zatem dla każdego punktu w , oznaczonego jako , oblicz prawdopodobieństwo z . Tutaj masz współczynnik podany jako parametr, to odległość do najbliższego centrum, a wyjaśniono w kroku 2.XXxipx=ld2(x,C)/ϕX(C)ld2(x,C)ϕX(C)
Algorytm jest po prostu:
- iteruj w aby znaleźć wszystkieXxi
- dla każdego obliczeniaxipxi
- wygeneruj jednolitą liczbę w , jeśli jest mniejsza niż wybierz ją, aby utworzyć[0,1]pxiC′
- po zakończeniu wszystkich losowań uwzględnij wybrane punkty z doC′C
Zauważ, że na każdym kroku 3 wykonanym w iteracji (linia 3 oryginalnego algorytmu) spodziewasz się wybrać punktów z (można to łatwo pokazać, pisząc bezpośrednio wzór na oczekiwanie).lX
for(int i=0; i<4; i++) {
// compute d2 for each x_i
int[] psi = new int[X.size()];
for(int i=0; i<X.size(); i++) {
double min = Double.POSITIVE_INFINITY;
for(int j=0; j<C.size(); j++) {
if(min>d2(x[i],c[j])) min = norm2(x[i],c[j]);
}
psi[i]=min;
}
// compute psi
double phi_c = 0;
for(int i=0; i<X.size(); i++) phi_c += psi[i];
// do the drawings
for(int i=0; i<X.size(); i++) {
double p_x = l*psi[i]/phi;
if(p_x >= Random.nextDouble()) {
C.add(x[i]);
X.remove(x[i]);
}
}
}
// in the end we have C with all centroid candidates
return C;
Krok 4:
Prostym algorytmem jest utworzenie wektora o wielkości równej liczbie elementów w i zainicjowanie wszystkich jego wartości za pomocą . Teraz iteruj w (elementy nie wybrane jako centroidy), a dla każdego znajdź indeks najbliższego środka ciężkości (element z ) i zwiększ o . W końcu trzeba będzie wektor obliczone prawidłowo.wC0Xxi∈XjCw[j]1w
double[] w = new double[C.size()]; // by default all are zero
for(int i=0; i<X.size(); i++) {
double min = norm2(X[i], C[0]);
double index = 0;
for(int j=1; j<C.size(); j++) {
if(min>norm2(X[i],C[j])) {
min = norm2(X[i],C[j]);
index = j;
}
}
// we found the minimum index, so we increment corresp. weight
w[index]++;
}
Krok 5:
Biorąc pod uwagę wagi obliczone w poprzednim kroku, postępujesz zgodnie z algorytmem kmeans ++, aby wybrać tylko punktów jako początkowe centroidy. W ten sposób wykonasz dla pętli, w każdej pętli wybierając pojedynczy element, losowany losowo z prawdopodobieństwem, że każdy element jest . Na każdym kroku wybierasz jeden element i usuwasz go z kandydatów, usuwając również odpowiadającą mu wagę.wkkp(i)=w(i)/∑mj=1wj
for(int k=0; k<K; k++) {
// select one centroid from candidates, randomly,
// weighted by w
// see kmeans++ and you first idea (which is wrong for step 3)
...
}
Wszystkie poprzednie kroki są kontynuowane, podobnie jak w przypadku kmeans ++, przy normalnym przepływie algorytmu klastrowania
Mam nadzieję, że teraz jest jaśniej.
[Później, później edytuj]
Znalazłem także prezentację autorów, w której nie można jednoznacznie stwierdzić, że przy każdej iteracji można wybrać wiele punktów. Prezentacja jest tutaj .
[Późniejsza edycja wydania @ pera]
Oczywiste jest, że zależy od danych, a podniesiony przez ciebie problem byłby prawdziwym problemem, gdyby algorytm był wykonywany na jednym hoście / maszynie / komputerze. Należy jednak pamiętać, że ten wariant klastrowania kmeans jest dedykowany dużym problemom i działa na systemach rozproszonych. Co więcej, autorzy w poniższych akapitach powyżej opisu algorytmu stwierdzają, co następuje:log(ψ)
Zauważ, że rozmiar jest znacznie mniejszy niż rozmiar wejściowy; przekierowanie można zatem wykonać szybko. Na przykład w MapReduce, ponieważ liczba centrów jest niewielka, można je wszystkie przypisać do pojedynczej maszyny, a dowolny algorytm przybliżenia (taki jak k-średnia ++) może zostać użyty do grupowania punktów w celu uzyskania k centrów. Implementacja algorytmu MapReduce 2 została omówiona w rozdziale 3.5. Chociaż nasz algorytm jest bardzo prosty i nadaje się do naturalnej równoległej implementacji (w rundach ), wyzwaniem jest wykazanie, że ma on możliwe do udowodnienia gwarancje.Clog(ψ)
Kolejną rzeczą do odnotowania jest następująca uwaga na tej samej stronie, która stwierdza:
W praktyce nasze wyniki eksperymentalne w rozdziale 5 pokazują, że wystarczy kilka rund, aby znaleźć dobre rozwiązanie.
Co oznacza, że możesz uruchomić algorytm nie dla czasów , ale dla danego stałego czasu.log(ψ)