Wie kann man bei K-Means den "Elbow" berechnen?

3 Antworten

Du nimmst die Steigung.

Steigung = flach -> nach dem Knick.

Oder du verwendest einfach ein Verfahren bei dem die Anzahl der Cluster nicht vorgegeben werden muss.

Woher ich das weiß:Studium / Ausbildung – Informatikstudium

AldoradoXYZ 
Beitragsersteller
 28.06.2020, 19:54

Dann wäre im ersten Beispiel 8 der Elbow, was nicht stimmt.

0
triopasi  28.06.2020, 19:56
@AldoradoXYZ

Du musst halt einen sinnvollen Grenzwert für die Steigung finden. Steigung = 0 gibt es nur wenn k = Anzahl der Daten.

0

wie gesagt : lang her : man muss "echte" statistische Verfahren anwenden.

Ich empfehle daher erst mal

Bild zum Beitrag

https://en.wikipedia.org/wiki/Elbow_method_%28clustering%29

und

normalerweise macht man das mit einem Statistikprogramm. Aber du willst es selbst machen , was keine Kosten verursacht und du kannst es sogar verkaufen :))

und dieses wirst du schon kennen

https://de.wikipedia.org/wiki/K-Means-Algorithmus

 - (Computer, Mathematik, programmieren)

AldoradoXYZ 
Beitragsersteller
 04.07.2020, 10:28

K-Means habe ich natürlich schon, der funktioniert auch wunderbar.

Interessant, dass bei der Elbow-Method auch dort geschrieben wird, dass man die Daten plottet und dann selbst wählt. Aber vielleicht geht das ja über einen prozentualen Schwellwert wie das in der Grafik erklärt wird.

Gruß

0
To determine the optimal number of clusters, we have to select the value of k at the “elbow” ie the point after which the distortion/inertia start decreasing in a linear fashion.

Was bedeutet das? Naja, das bedeutet, dass das Optimale k genau dann gegeben ist, wenn du von diesem Punkt aus alle weiteren Werte durch ein lineares Modell einigermaßen erklären kannst. Im Code würde ich das wie folgt lösen

import numpy as np
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error
import matplotlib.pyplot as plt

def find_elbow(inertia, eps=10e-3):
	current = 0
	kmax = inertia.shape[0]
	ks = np.arange(kmax)
	for k in range(kmax):
		ks = np.arange(k, kmax).reshape(-1,1)
		vals = inertia[ks].reshape(-1,1)
		reg = LinearRegression().fit(ks, vals)
		err = mean_squared_error(vals, reg.predict(ks))
		if err < eps:
			return k
	return ks[-1]

def main():
	# We create some synthetic data
	inertia = [210., 150., 20.]
	kfirst, klast = len(inertia), 10
	# Generate data by interpolating between values
	yfirst, ylast = inertia[-1], 1.
	ks = np.arange(kfirst, klast+1)
	interpoalted = (ylast-yfirst)/(klast-kfirst) * (ks-kfirst) + yfirst
	interpoalted = interpoalted[1:]
	# Add some noise
	interpoalted += np.random.normal(0, 10e-3, interpoalted.shape[0])
	# Concat to previous values
	inertia += interpoalted.tolist()
	inertia = np.array(inertia)
	optimal_k = find_elbow(inertia)
	print(optimal_k)
	plt.plot(np.arange(len(inertia)), np.array(inertia), marker='o')
	plt.vlines(optimal_k, 0, np.max(inertia), linestyles='dashed')
	plt.show()

if __name__ == '__main__':
	main()

Diese Lösung geht im Wesentlichen durch alle ks und versucht eine Gerade durch die Punkte zu legen. Das erste k, für das der Fehler kleiner als ein gewisses Epsilon wird, wird von der Funktion zurückgegeben. Natürlich hat dieser Ansatz einige Schwächen, in jedem Fall kann es zu Skalenproblemen kommen (d.h. wenn die Werte bereits sehr klein sind). Außerdem ist die Wahl des richtigen Epsilons entscheidend, d.h. du handelst dir einen zusätzlichen Hyperparameter ein. Der Idee nach sollte das aber einigermaßen funktionieren, wenn man die Suche nach dem optimalen k denn unbedingt automatisieren möchte.

Ich habe das jetzt nur für diese künstlichen Beispiel getestet. Du kannst gerne mal probieren, deine eigenen Daten in den Algorithmus zu stecken.


AldoradoXYZ 
Beitragsersteller
 29.06.2020, 09:55

Ah nice, werde ich gerne testen.

Mein Ansatz (der super primitiv ist) findet aktuell bei 4 deutlich erkennbaren Klustern nur 2, verbindet also jeweils 2 Kluster.

Gruß

0
AldoradoXYZ 
Beitragsersteller
 03.07.2020, 14:13
@Halbrecht

Hatte jetzt mehr auf Hinweise gehofft wie ich mein Problem lösen kann.

Aber gut

Gruß

0
Halbrecht  03.07.2020, 14:18
@AldoradoXYZ

Clusteranalyse ist lang her bei mir ..............genau wie Faktorenanalyse fand ich sie immer recht willkürlich ............

0
AldoradoXYZ 
Beitragsersteller
 03.07.2020, 14:19
@Halbrecht

Jetzt habe ich so schön k-mean implementiert (naja, eine Lib benutzt) und langsam bekomme ich das Gefühl ich müsste ein anderes Verfahren nutzen, eines welches auch die Anzahl optimiert

-.-°

Gruß

0