Dividiamo i dati in cluster con Python, scikit-learn e l’algoritmo K-means

algoritmo di clustering con Python e scikit-learn

Il clustering è una potente tecnica di Machine Learning non supervisionato, capace di suddividere autonomamente una serie di dati in due o più gruppi (detti appunto cluster). In questa lezione vediamo il codice per implementare un algoritmo di clustering con la libreria scikit-learn di Python.

Prepariamo i dati per il clustering

Importiamo come al solito il dataset Iris.

import pandas as pd
f = "https://raw.githubusercontent.com/iantomasinicola/Machine-Learning-con-SQL/main/IrisDataset.csv"
iris = pd.read_csv(filepath_or_buffer = f,
                             sep = ";",
                             skiprows = 4)

A differenza degli algoritmi di classificazione supervisionati visti nelle lezioni precedenti, in questo caso non terremo conto del contenuto della colonna class. La clusterizzazione infatti agisce autonomamente, non ha bisogno di dati storici per cui la classificazione è già stata fatta manualmente. Tuttavia sarà interessante confrontare i gruppi ottenuti tramite il clustering con le specie reali.

Creiamo allora un array di numpy a partire dai dati del dataframe Iris, escludendo le colonna class e Rownumber.

iris_array= iris.drop(["class","Rownumber"],axis=1).values

Creiamo una Pipeline per effettuare le operazioni basilari di pre-processing

from sklearn.impute import SimpleImputer
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline
pre_processing = Pipeline ([("vn", SimpleImputer(strategy = "mean")),
                                             ("sc", StandardScaler())
                                              ] )

Applichiamo allora la pipeline al nostro array

pre_processing.fit(iris_array)
iris_array = pre_processing.transform(iris_array)

e saremo pronti ad effettuare il clustering! Osserviamo che questi algoritmi non richiedono di suddividere i dati in training e test in quanto il loro obiettivo primario è solamente quello di suddividere i dati in più gruppi, senza la necessità di assegnargli un’etichetta specifica. Comunque, la suddivisione trovata potrà essere interpretata a posteriori anche come una forma di classificazione.

Eseguiamo l’algoritmo Kmeans

Esistono vari algoritmi matematici per effettuare il clustering dei dati. In questo articolo utilizzeremo l’implementazione in scikit-learn di uno dei più noti e utilizzati: l’algoritmo K-means.

from sklearn.cluster import KMeans
km = KMeans(n_clusters = 3,
                        init = "auto",
                        random_state = 0)
cluster = km.fit_predict(iris_array)

Commentiamo il codice in alto:

  • all’inizio abbiamo importato la classe KMeans dal modulo sklearn.cluster
  • abbiamo istanziato l’oggetto km valorizzando l’argomento n_clusters con 3 per chiedere all’algoritmo di suddividere i dati in tre classi
  • abbiamo valorizzato la variabile cluster con l’output del metodo fit_predict applicato all’array di dati di input

L’array cluster conterrà così valori nell’insieme 0, 1 e 2.

Interpretiamo i risultati del K-means

Per interpretare i risultati del K-means, creiamo una nuova colonna del Dataframe di partenza Iris a partire dall’output ottenuto dall’algoritmo.

iris["cluster"] = cluster

Analizzando visivamente il dataset così ottenuto troveremo una buona correlazione tra la classe di partenza e il cluster trovato. In particolare tra “Iris setosa” e il cluster 0, “Iris versicolor” con il cluster 1 e “Iris virginica” con il cluster 2. Andiamo a esplicitare meglio questo legame.

dizionario = {"Iris setosa":0, "Iris versicolor":1, "Iris virginica":2}
iris["class"]= iris["class"].map(dizionario)
iris.query(" `class` != cluster ")

Con il codice precedente abbiamo:

  • creato un dizionario per trascodificare le specie nei cluster secondo quando osservato manualmente
  • aggiornato la colonna class con i valori 0, 1 e 2 tramite il metodo map
  • applicato il metodo query per trovare le righe dove la trascodifica è errata (facciamo attenzione ad usare il carattere di escape per la colonna class)

Otteniamo 27 errori su un totale di 150 righe, che coinvolgono tutti le specie Iris versicolor e Iris virginica.

corso di analisi dei dati
Se vuoi diventare un esperto (qualunque sia il tuo livello di partenza) ti invito a visitare l’anteprima gratuita della piattaforma –> La Scuola dei Dati <–

Come stimare il numero di cluster più adeguato

Nell’esempio precedente abbiamo fornito direttamente in input all’algoritmo il numero di cluster da creare pari a 3. In generale però non sappiamo a priori quale sia il numero più corretto da utilizzare. Vediamo allora ora una possibile tecnica per individuare il numero di cluster più idoneo ai dati di partenza.

L’idea è di ripetere tante volte l’algoritmo k-means utilizzando un numero di cluster differenti. Ad ogni iterazione calcoleremo una misura dell’errore tramite l’attributo inertia_. Infine analizzeremo il grafico che mette in relazione questo errore con il numero di cluster.

errors = []
for k in range(1,15):
   km = KMeans(n_clusters = k,
                          n_init = "auto",
                          random_state = 0)
    km = km.fit(iris_array)
    errors.append(km.inertia_)

Il codice parte creando una lista vuota di nome errors, che andremo poi a popolare ad ogni iterazione del ciclo for con l’attributo inertia_, ottenuto valorizzando l’argomento n_clusters dell’algoritmo Kmeans con la variabile k con cui iteriamo il ciclo for.

A questo punto possiamo utilizzare la libreria matplotlib per creare un semplice grafico

import matplotlib.pyplot as plt
plt.plot(range(1,15),errors)
plt.xlabel("Numero cluster")
plt.ylabel("Errore")
plt.xticks(range(1,15))
plt.show()

Il grafico assomiglierà spesso al braccio e all’avambraccio di una persona. L’elbow method ci suggerisce di considerare come numero idoneo di cluster quello in corrispondenza del gomito, in questo caso sembra essere proprio il numero 3!

Continua a imparare

Torna in alto
Torna su