Guida al clustering in Python

Guida al clustering in Python

18 Febbraio 2022 ai 0
metodi di clustering in python

Il clustering o analisi dei cluster è un processo importantissimo perché spesso consente di vedere nei dati di input dei modelli interessanti per le nostre analisi. Si tratta di apprendimento non supervisionato, che serve ad esempio per individuare il comportamento di un gruppo di clienti.

Ogni caso è a sé e richiedere degli algoritmi specifici, ecco perché in questa guida vorrei spiegare come si adattano e si usano a nostro piacimento alcuni algoritmi di clustering in Python, principalmente tramite la libreria di apprendimento automatico scikit-learn.

Iniziamo dalle basi.

Che cos’è l’analisi dei cluster (clustering)

L’analisi dei cluster, o clustering, è un compito di apprendimento automatico non supervisionato.

Il clustering consente in sostanza di individuare in automatico alcune caratteristiche comuni dei dati di input, a differenza dell’apprendimento supervisionato (come la modellazione predittiva).

Ad esempio, il clustering può essere usato per individuare le community di utenti sui social network, oppure il comportamento di alcuni clienti in base ai loro acquisti, oppure il posizionamento di alcuni prodotti sul mercato. 

Si può rappresentare un cluster come un’area spaziale densa, ovvero dove alcune caratteristiche del dataset sono più vicine tra loro, creando uno o più cluster. 

Il cluster può avere un centro (il centroide) che è un campione o un punto dello spazio in cui sono determinate caratteristiche, e può avere un confine o un’estensione.

Perché esistono i cluster? 

La risposta a questa domanda dipende dall’analista a cui viene formulata: c’è sicuramente qualche meccanismo all’opera, qualche pattern o informazione importante sul dominio di dati, che bisognerà poi scoprire e scomporre.

Esistono ovviamente molte misurazioni quantitative che è possibile fare, e si possono anche confrontare gli algoritmi di clustering con dei dataset artificiali dotati di cluster predefiniti.

Alcuni esempi di clustering possono essere l’albero filogenetico, l’identificazione degli outlier, la separazione manuale dei cluster in un dataset come ad esempio la segmentazione del mercato.

Algoritmi di clustering

Una delle best practice è scalare i dati prima di utilizzarli per qualsiasi analisi.

Detto ciò, molti algoritmi di clustering misurano la similarità o non-similarità tra le varie caratteristiche del campione. 

Altri algoritmi di clustering chiedono di specificare il numero di cluster da scoprire nei dati, in altri invece bisogna inserire più dettagli sulla distanza minima che devono avere due caratteristiche per essere considerate come “simili”. 

Dobbiamo ricordare che l’analisi dei cluster in sé è un processo che si ripete, dove la valutazione soggettiva dei cluster si modifica in base alla configurazione che darai all’algoritmo, a seconda di qual è il risultato che vuoi ottenere.

Parleremo da questo punto in poi della libreria scikit-learn, in particolare di 10 algoritmi che ho trovato estremamente utili per il clustering:

  • Propagazione di affinità
  • Clustering agglomerativo
  • BIRCH
  • DBSCAN
  • K-Means
  • Mini-Batch K-Means
  • Spostamento medio
  • OPTICS
  • Clustering di spettro
  • Miscela gaussiana

I 10 migliori algoritmi di clustering in scikit-learn

Installazione della libreria

Per prima cosa, installiamo la versione più aggiornata della libreria.

sudo pip install scikit-learn

Successivamente, confermiamo che la libreria è installata e che state usando una versione moderna:

# verifica la versione di scikit-learn
import sklearn
print(sklearn.__version__)

Così comparirà la versione della tua libreria. Consiglierei di mantenersi su un numero che superi la 0.22.1.

Clustering del dataset

Useremo la funzione make_classification() per creare un dataset di test di classificazione binaria.

Il dataset avrà 1.000 esempi, con due caratteristiche di input e un cluster per classe. I cluster sono in due dimensioni così da poter visualizzare i dati in uno scatter plot e colorare i punti nel plot in base al cluster assegnato. Questo aiuterà a vedere se i cluster sono stati identificati bene nel problema che stiamo prendendo in esame.

Useremo ora dei cluster basati su una gaussiana multivariata, quindi attenzione: non tutti gli algoritmi di clustering saranno efficaci nell’identificare questi tipi di cluster. Infatti questa guida è pensata più che altro come una base per fare un confronto tra i diversi metodi.

Iniziamo così:

# dataset sintetico di classificazione
from numpy import where
from sklearn.datasets import make_classification
from matplotlib import pyplot

# definire il dataset
X, y = make_classification(n_samples=1000, n_features=2, n_informative=2, n_redundant=0, n_clusters_per_class=1, random_state=4)

# crea un grafico di dispersione per i campioni di ogni classe
per class_value in range(2):
	
# ottieni gli indici di riga per i campioni con questa classe
	row_ix = where(y == class_value)
	
# crea lo scatter di questi campioni
	pyplot.scatter(X[row_ix, 0], X[row_ix, 1])

# mostra il grafico
pyplot.show()

L’esecuzione dell’esempio crea il set di dati sintetico di clustering, quindi crea uno scatter plot dei dati di input con punti colorati per etichetta di classe (cluster idealizzati).

Possiamo vedere chiaramente due gruppi distinti di dati in due dimensioni e la speranza è che un algoritmo di clustering automatico possa rilevare questi raggruppamenti.

Siamo pronti per iniziare ad applicare gli algoritmi a questo dataset.

1) Propagazione di affinità

L’Affinity Propagation consiste nel trovare un insieme di esemplari che sono rappresentativi per l’intero set di dati.

Come input usiamo delle misure della somiglianza tra coppie di punti dati. Messaggi con valore reale vengono scambiati tra i punti dati fino a quando non emergono gradualmente degli esemplari di alta qualità e i cluster corrispondenti.

È implementata tramite la classe AffinityPropagation e la configurazione principale da regolare è impostare il “damping” tra 0,5 e 1 (ovvero lo “smorzamento”), e anche “preference”.

Ecco come fare:

# clustering di propagazione dell'affinità
from numpy import unique
from numpy import where
from sklearn.datasets import make_classification
from sklearn.cluster import AffinityPropagation
from matplotlib import pyplot

# definire il set di dati
X, _ = make_classification(n_samples=1000, n_features=2, n_informative=2, n_redundant=0, n_clusters_per_class=1, random_state=4)

# definire il modello
modello = AffinityPropagation(damping=0.9)

# adattare il modello
model.fit(X)

# assegnare un cluster a ogni esempio
yhat = model.predict(X)

# trovare i cluster unici
cluster = unique(yhat)

# crea un grafico di dispersione per i campioni di ogni cluster
per cluster in cluster:

	# ottenere gli indici di riga per i campioni con questo cluster
	row_ix = where(yhat == cluster)

	# creare lo scatter plot di questi campioni
	pyplot.scatter(X[row_ix, 0], X[row_ix, 1])

# mostrare il grafico
pyplot.show()

L’esecuzione dell’esempio adatta il modello al dataset di allenamento e predice un cluster per ogni esempio nel dataset. Viene quindi creato un plot di dispersione con punti che hanno colori diversi a seconda del cluster assegnato.

Si può sicuramente fare di meglio!

2) Clustering agglomerativo

Il clustering agglomerativo (come parte del cossiddetto “clustering gerarchico”) comporta la fusione di esempi fino a raggiungere il numero desiderato di cluster.

È implementato tramite la classe AgglomerativeClustering e la configurazione principale da mettere a punto è il set “n_clusters”, una stima del numero di cluster nei dati.

Ecco un esempio completo:

# clustering agglomerativo
from numpy import unique
from numpy import where
from sklearn.datasets import make_classification
from sklearn.cluster import AgglomerativeClustering
from matplotlib import pyplot

# definire il set di dati
X, _ = make_classification(n_samples=1000, n_features=2, n_informative=2, n_redundant=0, n_clusters_per_class=1, random_state=4)

# definire il modello
model = AgglomerativeClustering(n_clusters=2)

# adattare il modello e predire i cluster
yhat = model.fit_predict(X)

# trovare i cluster unici
cluster = unico(yhat)

# creare un plot di dispersione per i campioni di ogni cluster
for cluster in clusters:
	
# ottenere gli indici di riga per i campioni con questo cluster
	row_ix = where(yhat == cluster)

	# creare lo scatter plot di questi campioni
	pyplot.scatter(X[row_ix, 0], X[row_ix, 1])

# mostrare il grafico
pyplot.show()

L’esecuzione dell’esempio adatta il modello al dataset di allenamento e predice un cluster per ogni esempio nel dataset. Viene quindi creato un plot di dispersione con punti colorati in base al cluster assegnato.

Questa modalità, rispetto alla precedente, ci consente di ottenere un raggruppamento più sensato.

3) BIRCH

BIRCH è l’acronimo di Balanced Iterative Reducing and Clustering using Hierarchies, e visualizza i dati in una struttura ad albero da cui vengono estratti i centroidi dei cluster.

Il vantaggio di BIRCH è quello di raggruppare in modo incrementale e dinamico i punti di dati metrici multidimensionali, con l’obiettivo di ottenere un clustering migliore in condizioni limitate, come una scarsa memoria o un tempo ridotto.

È implementata tramite la classe Birch e le configurazioni principali da sistemare sono l’iperparametro “threshold” e “n_clusters” (che fornisce una stima del numero di cluster).

# clustering birch
from numpy import unique
from numpy import dove
from sklearn.datasets import make_classification
from sklearn.cluster import Birch
from matplotlib import pyplot

# definire il set di dati
X, _ = make_classification(n_samples=1000, n_features=2, n_informative=2, n_redundant=0, n_clusters_per_class=1, random_state=4)

# definire il modello
model = Birch(threshold=0.01, n_clusters=2)

# adatta il modello
model.fit(X)

# assegnare un cluster ad ogni esempio
yhat = model.predict(X)

# recuperare i cluster unici
cluster = unique(yhat)

# creare scatter plot per i campioni di ogni cluster
per cluster in cluster:
	
# ottenere gli indici di riga per i campioni con questo cluster
	row_ix = where(yhat == cluster)
	
# crea lo scatter di questi campioni
	pyplot.scatter(X[row_ix, 0], X[row_ix, 1])

# mostrare il grafico
pyplot.show()

Così facendo il modello viene adattato al dataset di allenamento e può predire un cluster per ogni esempio. Viene quindi creato un plot di dispersione con punti colorati in base al cluster assegnato.

4) DBSCAN

Il clustering DBSCAN (Density-Based Spatial Clustering of Applications with Noise) prevede la ricerca di aree ad alta densità e l’espansione di quelle aree come cluster, basandosi sulle loro caratteristiche.

L’algoritmo di clustering DBSCAN è stato specificamente ideato per scoprire cluster di forma arbitraria. Basta avere un parametro di input e DBSCAN è in grado di aiutarti a determinare il suo esatto valore.

La classe è DBSCAN, mentre la configurazione principale prevede gli iperparametri “eps” e “min_samples”, come mostro nell’esempio qui sotto:

# dbscan clustering
from numpy import unique
from numpy import where
from sklearn.datasets import make_classification
from sklearn.cluster import DBSCAN
from matplotlib import pyplot

# defire dataset
X, _ = make_classification(n_samples=1000, n_features=2, n_informative=2, n_redundant=0, n_clusters_per_class=1, random_state=4)

# definire il modello 
model = DBSCAN(eps=0.30, min_samples=9)

# adattare il modello e predire i cluster
yhat = model.fit_predict(X)

# trovare cluster unici
clusters = unique(yhat)

# creare scatter plot per campioni da ogni cluster
for cluster in clusters:

	# creare indici di riga per campioni con questo cluster
	row_ix = where(yhat == cluster)

	# creare scatter plot da questi campioni
	pyplot.scatter(X[row_ix, 0], X[row_ix, 1])

# mostrare il grafico 
pyplot.show()

Questo esempio adatta il modello al dataset di allenamento e predice un cluster per ogni esempio nel set di dati. Viene quindi creato un grafico scatter plot con punti colorati in base al cluster assegnato.

In questo caso, viene trovato un raggruppamento ragionevole, anche se è necessario un perfezionamento.

5) K-Means

K-Means Clustering è uno degli algoritmi di clustering più conosciuti. Con K-Means si possono assegnare i campioni ai cluster minimizzando così la varianza all’interno di ogni cluster.

Grazie ad essi è possibile ad esempio frazionare una popolazione N-dimensionale in insiemi K sulla base di un campione. Il processo viene chiamato “k-means”, e restituisce delle partizioni molto efficienti per quanto riguarda la varianza all’interno della classe.

È implementata tramite la classe KMeans e la configurazione principale da mettere a punto è l’iperparametro “n_clusters” impostato sul numero stimato di cluster nei dati.

# clustering k-means
from numpy import unique
from numpy import where 
from sklearn.datasets import make_classification
from sklearn.cluster import KMeans
from matplotlib import pyplot

# definire il set di dati
X, _ = make_classification(n_samples=1000, n_features=2, n_informative=2, n_redundant=0, n_clusters_per_class=1, random_state=4)

# definire il modello
modello = KMeans(n_cluster=2)

# adatta il modello
model.fit(X)

# assegna un cluster ad ogni esempio
yhat = model.predict(X)
# recupera i cluster unici
cluster = unico(yhat)

# creare un grafico di dispersione per i campioni di ogni cluster
for cluster in clusters:
	
# ottenere gli indici di riga per i campioni con questo cluster
	row_ix = where(yhat == cluster)
	
# creare lo scatter plot di questi campioni
	pyplot.scatter(X[row_ix, 0], X[row_ix, 1])

# mostrare il grafico
pyplot.show()

L’esecuzione dell’esempio adatta il modello al dataset di allenamento e predice un cluster per ogni esempio nel dataset. Viene quindi creato uno scatter plot con punti colorati in base al cluster assegnato.

In questo caso, viene trovato un raggruppamento ragionevole, anche se la varianza disuguale in ogni dimensione rende il metodo meno adatto a questo dataset.

6) Mini-Batch K-Means

Mini-Batch K-Means è una versione modificata di k-means che aggiorna i centroidi dei cluster usando dei piccoli batch dei campioni invece dell’intero set di dati.

Un’operazione che elimina il rumore e che accorcia di netto i tempo sui grandi dataset.

È implementato tramite la classe MiniBatchKMeans e la configurazione principale è l’iperparametro “n_clusters” impostato sul numero stimato di cluster nei dati.

L’esempio completo è elencato di seguito:

# clustering k-means mini-batch
from numpy import unique
from numpy import where
from sklearn.datasets import make_classification
from sklearn.cluster import MiniBatchKMeans
from matplotlib import pyplot

# definire il set di dati
X, _ = make_classification(n_samples=1000, n_features=2, n_informative=2, n_redundant=0, n_clusters_per_class=1, random_state=4)

# definire il modello
modello = MiniBatchKMeans(n_cluster=2)

# adattare il modello
model.fit(X)

# assegnare un cluster ad ogni esempio
yhat = model.predict(X)

# recuperare i cluster unici
cluster = unico(yhat)

# creare uno scatter plot per i campioni di ogni cluster
for cluster in clusters:

	# ottenere gli indici di riga per i campioni con questo cluster
	row_ix = where(yhat == cluster)

	# creare lo scatter plot di questi campioni
	pyplot.scatter(X[row_ix, 0], X[row_ix, 1])

# mostrare il grafico
pyplot.show()

L’esecuzione dell’esempio adatta il modello al dataset di allenamento e predice un cluster per ogni esempio nel dataset. Viene quindi creato un plot di dispersione con punti colorati in base al cluster assegnato.

In questo caso, si ottiene un risultato equivalente all’algoritmo k-means standard.

7) Spostamento medio

Il clustering dello spostamento medio (Mean shift) è in grado di cercare e adattare i centroidi in base alla densità degli esempi nello spazio delle caratteristiche.

È utilissimo per rilevare le varie modalità di densità per i dati discreti, perché attua uno spostamento medio ricorsivo al punto stazionario più vicino all’interno di una funzione di densità.

È implementato tramite la classe MeanShift e la configurazione principale da regolare è l’iperparametro “bandwidth”.

Ecco un esempio completo:

# clustering mean shift
from numpy import unique
from numpy import where
from sklearn.datasets import make_classification
from sklearn.cluster import MeanShift
from matplotlib import pyplot

# definire il set di dati
X, _ = make_classification(n_samples=1000, n_features=2, n_informative=2, n_redundant=0, n_clusters_per_class=1, random_state=4)

# definire il modello
model = MeanShift()

# adattare il modello e predire i cluster
yhat = model.fit_predict(X)

# recuperare i cluster unici
cluster = unique(yhat)

# creare un grafico di dispersione per i campioni di ogni cluster
for cluster in clusters:

	# ottenere gli indici di riga per i campioni con questo cluster
	row_ix = where(yhat == cluster)
	
# creare lo scatter plot di questi campioni
	pyplot.scatter(X[row_ix, 0], X[row_ix, 1])

# mostrare il grafico
pyplot.show()

L’esecuzione dell’esempio adatta il modello al dataset di allenamento e predice un cluster per ogni esempio nel dataset. Viene quindi creato uno scatter plot con punti colorati in base al cluster assegnato.

In questo caso, i cluster trovati sono sensati e in numero ragionevole.

8) OPTICS

Il clustering OPTICS (Ordering Points To Identify the Clustering Structure) è una versione modificata del DBSCAN di cui abbiamo parlato sopra.

Questo algoritmo per l’analisi dei cluster è un po’ diverso dai precedenti: infatti, non produce l’analisi di cluster di un set di dati, ma mostra piuttosto la struttura di clustering basata sulla densità di un database.

È implementata tramite la classe OPTICS e la configurazione principale prevede gli iperparametri “eps” e “min_samples”:

# clustering con optics
from numpy import unique
from numpy import where
from sklearn.datasets import make_classification
from sklearn.cluster import OPTICS
from matplotlib import pyplot

# definire un dataset
X, _ = make_classification(n_samples=1000, n_features=2, n_informative=2, n_redundant=0, n_clusters_per_class=1, random_state=4)

# definire il modello
model = OPTICS(eps=0.8, min_samples=10)

# adattare modello e predire i cluster
yhat = model.fit_predict(X)

# trovare cluster unici
clusters = unique(yhat)

# creare uno scatter plot per i campioni da ogni cluster
for cluster in clusters:

	# ottieni gli indici di riga per i campioni con questo cluster 
	row_ix = where(yhat == cluster)
	
# creare scatter plot da questi campioni 
	pyplot.scatter(X[row_ix, 0], X[row_ix, 1])

# mostrare il grafico
pyplot.show()

L’esecuzione dell’esempio adatta il modello al dataset di allenamento e predice un cluster per ogni esempio nel dataset. Viene quindi creato uno scatter plot con punti colorati in base al cluster assegnato. Se utilizzi questo dataset per fare le tue prove, ti anticipo che i risultati con questo set di dati non sono soddisfacenti.

9) Clustering di spettro

I metodi di clustering di spettro sono tratti dall’algebra lineare.

Questa tecnica prevede di usare i primi autovettori di una matrice derivata dalla distanza tra i punti.

Fondamentale è l’iperparametro “n_clusters”, usato per specificare il numero stimato di cluster nei dati:

# clustering di spettro

from numpy import unique
from numpy import where
from sklearn.datasets import make_classification
from sklearn.cluster import SpectralClustering
from matplotlib import pyplot

# definire dataset
X, _ = make_classification(n_samples=1000, n_features=2, n_informative=2, n_redundant=0, n_clusters_per_class=1, random_state=4)

# definire il modello
model = SpectralClustering(n_clusters=2)

# adattare il modello e predire cluster
yhat = model.fit_predict(X)

# trovare cluster unici
clusters = unique(yhat)

# creare uno scatter plot per i campioni di ogni cluster
for cluster in clusters:

	# ottenere gli indici di riga per i campioni con questo cluster
	row_ix = where(yhat == cluster)

	# crea lo scatter di questi campioni
	pyplot.scatter(X[row_ix, 0], X[row_ix, 1])

# mostra il grafico
pyplot.show()

L’esecuzione dell’esempio adatta il modello al dataset di allenamento e predice un cluster per ogni esempio nel dataset. Viene quindi creato uno scatter plot con punti colorati in base al cluster assegnato.

10) Modello di miscela gaussiana

Un modello a miscela gaussiana è in sostanza una funzione di densità di probabilità multivariata con una miscela di distribuzioni di probabilità gaussiane, come suggerisce il nome.

È implementato tramite la classe GaussianMixture e la configurazione principale da mettere a punto è l’iperparametro “n_clusters” utilizzato per specificare il numero stimato di cluster nei dati.

Ecco come ottenerlo:

# clustering a miscela gaussiana
from numpy import unique
from numpy import dove
from sklearn.datasets import make_classification
from sklearn.mixture import GaussianMixture
from matplotlib import pyplot

# definire il set di dati
X, _ = make_classification(n_samples=1000, n_features=2, n_informative=2, n_redundant=0, n_clusters_per_class=1, random_state=4)

# definire il modello
model = GaussianMixture(n_components=2)

# adattare il modello
model.fit(X)

# assegnare un cluster ad ogni esempio
yhat = model.predict(X)

# recuperare i cluster unici
cluster = unique(yhat)

# crea uno scatter plot per i campioni di ogni cluster
for cluster in clusters:
	
# ottenere gli indici di riga per i campioni con questo cluster
	row_ix = where(yhat == cluster)
	
# creare lo scatter di questi campioni
	pyplot.scatter(X[row_ix, 0], X[row_ix, 1])

# mostrare il grafico
pyplot.show()

In questo modo è possibile adattare il modello al dataset di allenamento e predire un cluster per ogni esempio nel dataset. Viene quindi creato un plot di dispersione con punti colorati in base al cluster assegnato.

In questo caso, possiamo vedere che i cluster sono stati identificati perfettamente.

Conclusione

Sul clustering ci sono diversi articoli e paper interessanti e molto completi. Non ho l’ambizione di riassumere tutto lo scibile in merito, ma spero di averti dato delle indicazioni utili per poter poi approfondire per conto tuo!

 

Lascia un commento

Il tuo indirizzo email non sarà pubblicato.

Newsletter Mensile

Iscriviti alla nostra newsletter mensile per restare sempre aggiornato e in contatto con noi.

Puoi sempre cancellare la tua email quando lo desideri, ma siamo davvero molto discreti (abbiamo poco tempo).

Link Privacy Policy