Demo-PY3: Clusteranalyse mit scikit-learn

Nachdem in Demo-PY1: Python-Tutorial der erste Einstieg in die Syntax und in Demo-PY2: Datenverwaltung mit Pandas die Datenverwaltung und - visualisierung mit Hilfe der Python-Bibliothek Pandas erfolgt ist, zeigt Demo-PY3 im nächsten Schritt, wie eine Clusteranalyse mit Hilfe der Python-Bibliotheken scikit-learn und SciPy durchgeführt wird.

Ein Datensatz zum Raumklima in Abhängigkeit von Luftfeuchtigkeit und Temperatur dient uns dabei als Anwendungsbeispiel. Die Daten werden in der interaktiven, webbasierten Anwendungsumgebung Jupyter Notebook analysiert. Im letzten Schritt der Demo erfolgt die Datenvisualisierung und die Zuordnung zu den Clustern mit Hilfe der Bibliothek Matplotlib.

  Motivation

Bei der Datenanalyse (gerade bei großen Datenmengen) stellt sich häufig die Frage nach gemeinsamen Gruppen ("Cluster") innerhalb der Daten. In einem Datensatz mit Raumklima-Daten sind z.B. die Beobachtungen M1 = {Temp = 23°C, Feuchtigkeit = 69%} und M2 = {Temp = 21°C, Feuchtigkeit = 80%} einander ähnlich und könnten einer Gruppe "zu feucht" zugeordnet werden. Gruppen ähnlicher Merkmale werden durch die Verwendung eines bestimmten Ähnlichkeits- bzw. Abstandsmaßes gebildet. Neue Daten können anhand ihrer Merkmale dann den Clustern zugeordnet werden.

Python stellt zwei leistungsfähige Bibliotheken für die Anwendung von Verfahren zum maschinellen Lernen zur Verfügung: scikit-learn und SciPy, deren typische Verwendung wir an einem konkreten Anwendungsfall veranschaulichen.

Warum scikit-learn?

scikit-learn ist eine Open-Source-Bibliothek zum maschinellen Lernen für die Programmiersprache Python und bietet leistungsstarke Algorithmen, wie Klassifikations-, Regressions- und Clustering-Algorithmen, siehe die sklearn-Funktionen. In diesem Abschnitt wird die Bibliothek scikit-learn eine zentrale Rolle spielen, da sie die von uns benötigten Clusterverfahren "KMeans" und "hierarchische Modelle" zur Verfügung stellt, siehe sklearn.cluster.

Warum SciPy?

SciPy ist eine Python-Programmbibliothek für wissenschaftliches Rechnen und Visualisierung von Modellen. SciPy umfasst numerische Algorithmen und mathematische Werkzeuge, wie das in dieser Demo verwendete Cluster-Paket scipy.cluster.hierarchy, das die Funktionen dendrogram zur Erstellung eines Dendrogramms und linkage zur Durchführung einer Clusteranalyse enthält.

  Übersicht

Demo-PY3 ist in 6 Abschnitte gegliedert. Zunächst wird der Raumklima-Datensatz beschrieben und die Fragestellung, die wir mit unserer Datenanalyse beantworten wollen. Danach beschreiben wir kurz die Funktionsweise und Anwendung von Clusteranalysen. Danach wird die Erstellung des Jupyter Notebooks und Vorbereitung benötigter Bibliotheken erläutert. In den folgenden Abschnitten beschreiben wir die Datenanalyse mit scikit-learn und SciPy inkl. der Daten- und Clustervisualisierung mit Matplotlib.

1 Der Raumklima-Datensatz

Der Raumklima-Datensatz enthält 15 Beobachtungen / Messungen zur Temperatur (in Grad Celsius) und der Luftfeuchtigkeit (in %). Je nach Kombination aus Temperatur und Luftfeuchtigkeit wird das Raumklima als "behaglich", "zu trocken" oder "zu feucht" empfunden.

Wir wollen mit Hilfe einer Clusteranalyse Fragen beantworten wie:
Welche Kombination aus Temperatur und Luftfeuchtigkeit führt zu einem optimalen Klima?
Können Daten mit gewissen Kombinationen aus Temperatur und Luftfeuchtigkeit einer Gruppe bzw. einem Cluster "behaglich", "zu trocken" oder "zu feucht" zugeordnet werden?

2 Was ist eine Clusteranalyse?

Eine Clusteranalyse ist ein Verfahren des maschinellen Lernens, mit dessen Hilfe man in einem Datensatz Gruppen ähnlicher Beobachtungen ("Cluster") identifizieren kann.
Die Clusterbildung kann mit unterschiedlichen Algorithmen umgesetzt werden. Zwei der bekanntesten Verfahren sind K-Means-Clustering und hierarchisches Clustering.

Die Idee bei K-Means-Clustering ist, dem Algorithmus als Input eine feste Anzahl k von Clustern vorzugeben, der zu diesen Clustern die Clusterzentren bestimmt, und diese so lange verschiebt, bis sich die Zuordnung der Beobachtungen zu den Clusterzentren nicht mehr verändert. Dabei wird eine vorgegebene Fehlerfunktion minimiert.

Die Idee beim hierarchischen Clustering ist, dass der Algorithmus eine hierarchische Struktur der Daten aufbaut, ein sogenanntes Dendogramm. Beim agglomerativen ("bottom up") Clustering bildet zunächst jede Beobachtung ein Cluster, d.h. man hat zunächst ebensoviele Cluster wie Datenpunkte. Diese werden dann sukzessiv zusammengeführt in größere Cluster, wobei die Zusammenfassung auf Basis einer Fusionsvorschrift (engl. Linkage) geschieht. Bei Single Linkage werden die Cluster, deren nächste Objekte die kleinste Distanz zueinander haben, fusioniert. Bei der Ward-Methode werden die Cluster, die den kleinsten Zuwachs der totalen Varianz haben, fusioniert.

3 Jupyter Notebook erstellen

Für die Datenverwaltung, die Clusteranalyse und die Datenvisualisierung wird ein Jupyter Notebook erstellt. Über Programme öffnen wir die Jupyter Notebooks-Anwendung und erstellen mit Hilfe des Menüpunkts "New" ein neues Python3-Notizbuch mit dem Namen elab2go-Demo-PY3.

Die Details der Verwendung von Jupyter Notebooks sind im Abschnitt Jupyter Notebooks verwenden beschrieben.

4 Clusteranalyse mit K-Means-Verfahren

Die Clusteranalyse mit K-Means-Verfahren ist einfach anzuwenden, benötigt jedoch als Input die Anzahl der Cluster, diese ist bei den meisten Datensätzen nicht vorab bekannt.

4-1 Importieren der Programmbibliotheken

In der ersten Codezelle des Jupyter Notebooks importieren wir die benötigten Programmbibliotheken: scikit-learn und sciPy, sowie die aus Demo-PY2: Datenverwaltung mit Pandas bekannten Bibliotheken Pandas, Matplotlib, Seaborn und NumPy.
In Python kann man mit Hilfe der import-Anweisung entweder eine komplette Programmbibliothek importieren, oder nur einzelne Funktionen der Programmbibliothek (from-import-Anweisung). Beim Import werden für die jeweiligen Bibliotheken oder Funktionen Alias-Namen vergeben: für pandas vergeben wir den Alias pd, etc.

Die erste Codezelle enthält insgesamt sieben Import-Anweisungen und den Befehl %matplotlib inline, der bewirkt, dass die Plots innerhalb des Notizbuches erzeugt werden.

 import matplotlib.pyplot as plt   
 import seaborn as sns; sns.set()  
 import numpy as np  
 import pandas as pd 
 import scipy.cluster.hierarchy as shc  
 from sklearn.cluster import KMeans 
 from sklearn.cluster import AgglomerativeClustering 
 %matplotlib inline # Erzeuge Plots innerhalb des Notizbuches

4-2 Daten einlesen

In der zweiten Codezelle werden Daten, die in der csv-Datei raumklima.csv gespeichert sind, mit Hilfe der Funktion read_csv() der Pandas-Bibliothek eingelesen, siehe auch Demo-PY2: Datenverwaltung mit Pandas.

 # Lese CSV-Datei ein 
 klima_data = pd.read_csv('raumklima.csv',sep=';', header=0)  
 
 # Merkmale/Variablen Feuchtigk. und Temp. separat speichern
 X = klima_data.iloc[:,[0,1]].copy() 
 
 # Wahre Zuordnung zu den Kategorien speichern
 cluster_true=klima_data.iloc[:,2].copy() 
 
 # Zeige ausgewählte Zeilen zur Kontrolle an 
 klima_data.head(10)

Die Ausgabe nach Ausführung dieses Codeblocks sieht ähnlich aus wie abgebildet.


4-3 Daten visualisieren

Nach einer Datenkonvertierung des DataFrames in ein Array mittels der NumPy-Bibliothek werden die Daten mit der scatter-Anweisung der Matplotlib-Bibliothek als Streudiagramm dargestellt. Ein Streudiagramm (auch: Punktwolke, engl. scatter plot) ist die graphische Darstellung der (x,y) Wertepaare zweier statistischer Merkmale (hier: Feuchtigkeit und Temperatur). Durch das Muster der Punkte im Streudiagramm erkennt man Informationen über die Abhängigkeitsstruktur der beiden Merkmale.

 X = np.array(X) # Typkonvertierung: DataFrame->Array  
 print(type(X))  
 # Daten visualisieren  
 plt.scatter(X[:,0], X[:,1],s=40);  
 plt.title('Raumklima-Daten als Scatter-Plot')  
 plt.xlabel('Feuchtigkeit (%)');plt.ylabel('Temperatur ()');  

Die Ausgabe nach Ausführung dieses Codeblocks sieht ähnlich aus wie abgebildet. Das Streudiagramm zeigt die Anordnung der Merkmale in drei klar abgegrenzte Punktwolken.

4-4 Clusteranalyse durchführen

Die Clusteranalyse wird mittels der KMeans-Funktion aus dem sklearn.cluster-Paket der scikit-learn-Bibliothek durchgeführt.

 #Anzahl der Zentren festlegen
 kmeans = KMeans(n_clusters=3) 
 
 # Vorhersage mittels K-Means-Verfahren
 kmeans.fit(X)
 y_kmeans = kmeans.predict(X)
 
 # vorhergesagte Zuordnungen der Merkmalskombinationen zu den geschätzten Zentren
 y_kmeans

Die Ausgabe nach Ausführung dieses Codeblocks sieht ähnlich aus wie abgebildet.


4-5 Zuordnung der Daten zu den Clustern visualisieren

Die Ergebnis, d.h. die Zuordnung der Beobachtungen zu den drei möglichen Zentren/Clustern, wird als Plot dargestellt.

 # Daten visualisieren: Merkmale
 plt.scatter(X[:, 0], X[:, 1], c=y_kmeans, s=40, cmap='magma')
 
 # Daten visualisieren: Zentren
 centers = kmeans.cluster_centers_
 plt.scatter(centers[:, 0], centers[:, 1], c='black', s=60, alpha=0.7);
 
 plt.title("Raumklima")
 plt.xlabel('Feuchtigkeit (%)');plt.ylabel('Temperatur ()'); 
 
 # Merkmalswerte der Zentren ausgeben
 print('Merkmalswerte der Zentren:')  
 print(centers)  

Die Ausgabe nach Ausführung dieses Codeblocks sieht ähnlich aus wie abgebildet.

Output 1 Output 2

5 Clusteranalyse mit Hilfe hierarchischer Modelle

Bei Ungewissheit zur Anzahl der Cluster/Zentren wird als vorbereitendes Mittel zur Auswahl der Clusteranzahl über eine hierarchische Clusteranalyse [1,3] ein Dendogramm erstellt. Aus diesem kann die Anzahl der Cluster abgelesen werden. In einem zweiten Schritt kann eine detaillierte agglomerative Clusteranalyse [4] verwendet werden, die als Input die Vorgabe einer festen Anzahl von Clustern erfordert.

Das Importieren der benötigten Bibliotheken bzw. derer Funktionen und das Einlesen und Visualisieren der Daten erfolgt wie bereits im vorherigen Abschnitt beschrieben. Wir starten in diesem Abschnitt direkt bei der Durchführung der Clusteranalyse und der Erstellung eines Dendrogramms mit Hilfe der entsprechenden Funktionen der scikit-learn- und SciPy-Bibliotheken.

5-1 Vorbereitung: Dendrogramm erstellen

Das Dendrogramm wird mittels dendrogram-Funktion des cluster.hierarchy-Pakets der sciPy-Bibliothek erstellt.

 plt.figure(figsize=(10, 7))
 plt.title("Dendrogramm")
 dend = shc.dendrogram(shc.linkage(X, method='ward'))

Die Ausgabe nach Ausführung dieses Codeblocks sieht ähnlich aus wie abgebildet.

Die Wurzel des Dendogramms entspricht dem kompletten Raumklima-Datensatz mit 15 Beobachtungen. Die Blätter des Dendogramms sind mit den IDs der Beobachtungen beschriftet, d.h. das äußerste linke Blatt mit der Beschriftung 6 entspricht der Beobachtung M6 = {ID = 6, Feuchte = 80%, Temp = 21°C}.
Das Dendrogramm bestätigt das Vorhandensein von 3 Clustern. Der erste Cluster enthält die Beobachtungen mit den IDs {6,7,5,8,9}, die dem Cluster "zu feucht" entsprechen. Der zweite Cluster enthält die Beobachtungen mit den IDs {10,14,13,11,12}, die dem Cluster "zu trocken" entsprechen. Der dritte Cluster enthält die Beobachtungen mit den IDs {0, 1, 2, 3, 4}, die dem Cluster "behaglich" entsprechen. Die Information über die Anzahl der Cluster verwenden wir bei der Durchführung der Clusteranalyse, die im nächsten Schritt erfolgt.

5-2 Detaillierte Clusteranalyse durchführen

Die detaillierte Clusteranalyse wird mittels der AgglomerativeClustering aus dem sklearn.cluster-Paket der scikit-learn-Bibliothek durchgeführt.

 # hierarchisches Modell festlegen, inkl. Anzahl der Cluster
 cluster = AgglomerativeClustering(n_clusters=3, affinity='euclidean', linkage='ward')
 
 # Vorhersage mittels des hierarchischen Modells
 cluster = cluster.fit(X)
 y_cluster = cluster.fit_predict(X)
 
 # vorhergesagte Zuordnungen der Merkmalskombinationen zu den geschätzten Zentren
 y_cluster #or:
 # print(cluster.labels_)

Die Ausgabe nach Ausführung dieses Codeblocks sieht ähnlich aus wie abgebildet.

Hierarchische Clusteranalyse

5-3 Zuordnung der Daten zu den Clustern visualisieren

Das Ergebnis der Clusteranalyse, d.h. die Zuordnung der Beobachtungen zu den drei möglichen Zentren/Clustern, wird als Plot dargestellt.

 # Daten visualisieren: Merkmale
 plt.scatter(X[:, 0], X[:, 1], c=cluster.labels_, s=40, cmap='rainbow')
 
 plt.title("Raumklima")
 plt.xlabel("Luftfeuchtigkeit(%)")
 plt.ylabel("Temperatur(Celsius)")

Die Ausgabe nach Ausführung dieses Codeblocks sieht ähnlich aus wie abgebildet.

6 YouTube-Video

Die Verwendung des erstellten Jupyter Notebook wird durch ein Video (Screencast mit zusätzlichen Erläuterungen) veranschaulicht.

Autoren, Tools und Quellen

Autoren:
 M. Sc. Anke Welz
 Prof. Dr. Eva Maria Kiss
Tools:
Python, Anaconda, Jupyter Notebook, Pandas, Matplotlib, NumPy

elab2go Links:

Quellen und weiterführende Links: