Vai al contenuto principale

Introduzione al clustering k-means con scikit-learn in Python

In questo tutorial, scopri come applicare il clustering k-means con scikit-learn in Python
Aggiornato 3 giu 2026  · 8 min leggi

Introduzione

In questo tutorial imparerai il clustering k-means. Vedremo:

  • Come funziona l'algoritmo di clustering k-means
  • Come visualizzare i dati per capire se sono adatti al clustering
  • Un caso di studio di training e tuning di un modello di clustering k-means usando un dataset reale del mercato immobiliare della California. 

Nota: non confondere con k-nearest neighbors. Se cerchi quello, vai a k-Nearest Neighbors (KNN) Classification with scikit-learn in Python.

È utile saperlo perché il clustering k-means è un algoritmo molto diffuso che raggruppa bene dati di forma sferica in gruppi distinti. Questo è prezioso sia come strumento di analisi quando i raggruppamenti delle righe non sono chiari, sia come passaggio di feature engineering per migliorare modelli di apprendimento supervisionato. 

Per questo tutorial si presuppone una conoscenza di base di Python e la capacità di lavorare con i DataFrame di pandas. 

Panoramica del clustering k-means

I modelli di clustering mirano a raggruppare i dati in “cluster” o gruppi distinti. Questo può offrire una vista interessante in fase di analisi, oppure può diventare una feature in un algoritmo di apprendimento supervisionato. 

Immagina un contesto sociale con gruppi di persone che chiacchierano in diversi cerchi in una stanza. A un primo sguardo vedi solo un insieme di persone. Potresti iniziare mentalmente a piazzare dei punti al centro di ogni gruppo e assegnare a ciascun punto un identificatore univoco. A quel punto potresti riferirti a ogni gruppo con un nome distinto per descriverlo. In sostanza, è ciò che fa k-means con i dati. 

image7.png

Nella parte sinistra del diagramma sopra, vediamo due insiemi distinti di punti non etichettati e colorati come punti dati simili. Addestrare un modello k-means su questi dati (parte destra) può rivelare 2 gruppi distinti (rappresentati sia da cerchi distinti sia da colori). 

In due dimensioni, per gli esseri umani è facile separare questi cluster, ma con più dimensioni è necessario usare un modello.

Il dataset

In questo tutorial useremo dati immobiliari della California da Kaggle (qui). Useremo i dati di posizione (latitudine e longitudine) e il valore mediano delle case. Clusterizzeremo le case per posizione e osserveremo come i prezzi delle case variano in tutta la California. Salviamo il dataset come file csv chiamato ‘housing.csv’ nella nostra directory di lavoro e lo leggiamo con pandas.

import pandas as pd

home_data = pd.read_csv('housing.csv', usecols = ['longitude', 'latitude', 'median_house_value'])
home_data.head()

image4.png

I dati includono 3 variabili che abbiamo selezionato usando il parametro usecols:

  • longitude: Un valore che rappresenta quanto a ovest si trova una casa. Valori più alti indicano case più a ovest.
  • latitude: Un valore che rappresenta quanto a nord si trova una casa. Valori più alti indicano case più a nord.
  • median_house_value: Il prezzo mediano delle case all'interno di un isolato, misurato in USD. 

Workflow del clustering k-means

Come altri algoritmi di Machine Learning, il clustering k-means segue un workflow (consulta A Beginner's Guide to The Machine Learning Workflow per un'analisi più approfondita del workflow di Machine Learning).

In questo tutorial ci concentreremo sulla raccolta e lo split dei dati (nella preparazione dei dati) e sul tuning degli iperparametri, l'addestramento del modello e la valutazione delle prestazioni (nella fase di modellazione). Gran parte del lavoro negli algoritmi di apprendimento non supervisionato riguarda il tuning degli iperparametri e la valutazione delle performance per ottenere il meglio dal modello.

Visualizzare i dati

Iniziamo visualizzando i nostri dati immobiliari. Esaminiamo i dati di posizione con una mappa di dispersione colorata in base al prezzo mediano in un isolato. In questo tutorial useremo Seaborn per creare rapidamente i grafici (vedi il nostro corso Introduction to Data Visualization with Seaborn per capire meglio come vengono creati questi grafici).

import seaborn as sns

sns.scatterplot(data = home_data, x = 'longitude', y = 'latitude', hue = 'median_house_value')

image10.png

Vediamo che la maggior parte delle case costose si trova sulla costa ovest della California, con diverse aree che presentano cluster di case a prezzo medio. È prevedibile: in genere le proprietà sul lungomare valgono più delle case lontane dalla costa. 

I cluster spesso sono facili da individuare quando usi solo 2 o 3 feature. Diventa sempre più difficile o impossibile quando il

Normalizzare i dati

Quando si lavora con algoritmi basati sulla distanza, come il clustering k-means, è necessario normalizzare i dati. Se non normalizziamo, variabili con scale diverse verranno pesate diversamente nella formula di distanza ottimizzata durante il training. Per esempio, se includessimo il prezzo nel cluster oltre a latitudine e longitudine, il prezzo avrebbe un impatto eccessivo sulle ottimizzazioni perché la sua scala è significativamente più ampia rispetto alle variabili di posizione che sono limitate. 

Per prima cosa creiamo training e test split usando train_test_split da sklearn

from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = train_test_split(home_data[['latitude', 'longitude']], home_data[['median_house_value']], test_size=0.33, random_state=0)

Poi normalizziamo i dati di training e test usando il metodo preprocessing.normalize() di sklearn

from sklearn import preprocessing

X_train_norm = preprocessing.normalize(X_train)
X_test_norm = preprocessing.normalize(X_test)

Addestrare e valutare il modello

Per la prima iterazione, scegliamo arbitrariamente un numero di cluster (indicato con k) pari a 3. Creare e addestrare modelli in sklearn è molto semplice. Creeremo un'istanza di KMeans, definiremo il numero di cluster con l'attributo n_clusters, imposteremo n_init (il numero di esecuzioni dell'algoritmo con seed dei centroidi diversi) su “auto” e imposteremo random_state a 0 per ottenere lo stesso risultato a ogni esecuzione. Possiamo quindi adattare il modello ai dati di training normalizzati con il metodo fit().

from sklearn import KMeans

kmeans = KMeans(n_clusters = 3, random_state = 0, n_init='auto')
kmeans.fit(X_train_norm)

Una volta adattati i dati, possiamo accedere alle etichette dall'attributo labels_. Qui sotto visualizziamo i dati appena adattati. 

sns.scatterplot(data = X_train, x = 'longitude', y = 'latitude', hue = kmeans.labels_)

image1.png

Vediamo che i dati sono ora nettamente suddivisi in 3 gruppi distinti (California del Nord, Centrale e del Sud). Possiamo anche osservare la distribuzione dei prezzi mediani in questi 3 gruppi con un boxplot. 

sns.boxplot(x = kmeans.labels_, y = y_train['median_house_value'])

image3.png

Si vede chiaramente che i cluster del Nord e del Sud hanno distribuzioni simili dei valori mediani delle case (cluster 0 e 2) che sono più alte rispetto ai prezzi del cluster centrale (cluster 1). 

Possiamo valutare le prestazioni dell'algoritmo di clustering usando lo silhouette score, parte di sklearn.metrics, dove un punteggio più basso rappresenta un fit migliore.

from sklearn.metrics import silhouette_score

silhouette_score(X_train_norm, kmeans.labels_, metric='euclidean')

Dato che non abbiamo ancora confrontato la bontà di diversi numeri di cluster, non sappiamo quanto sia valido il modello con k = 3. Nella sezione successiva esploreremo diversi cluster e confronteremo le performance per decidere i valori migliori degli iperparametri del nostro modello.

Scegliere il numero migliore di cluster

La debolezza del clustering k-means è che non sappiamo quanti cluster servano semplicemente eseguendo il modello. Dobbiamo testare intervalli di valori e scegliere il valore migliore di k. In genere si usa il metodo del gomito (Elbow) per determinare il numero ottimale di cluster, in modo da non sovra-adattare i dati con troppi cluster né sotto-adattarli con troppo pochi. 

Creiamo il ciclo qui sotto per testare e memorizzare diversi risultati del modello, così da poter decidere il numero migliore di cluster.

K = range(2, 8)
fits = []
score = []


for k in K:
    # train the model for current value of k on training data
    model = KMeans(n_clusters = k, random_state = 0, n_init='auto').fit(X_train_norm)
    
    # append the model to fits
    fits.append(model)
    
    # Append the silhouette score to scores
    score.append(silhouette_score(X_train_norm, model.labels_, metric='euclidean'))

Possiamo quindi osservare visivamente alcuni valori diversi di k. 

Per prima cosa guardiamo k = 2.

sns.scatterplot(data = X_train, x = 'longitude', y = 'latitude', hue = fits[0].labels_)

image11.png

Il modello fa un lavoro discreto nel dividere lo stato in due metà, ma probabilmente non coglie abbastanza sfumature del mercato immobiliare californiano. 

Poi guardiamo k = 4. 

sns.scatterplot(data = X_train, x = 'longitude', y = 'latitude', hue = fits[2].labels_)

image13.png

Vediamo che questo grafico raggruppa la California in cluster più logici in base a quanto a nord o a sud si trovano le case nello stato. Questo modello probabilmente cattura più sfumature del mercato man mano che ci si sposta. 

Infine, guardiamo k = 7.

sns.scatterplot(data = X_train, x = 'longitude', y = 'latitude', hue = fits[2].labels_)

image2.png

Il grafico sopra sembra avere troppi cluster. Abbiamo sacrificato la facilità d'interpretazione dei cluster per un risultato di geo-clustering apparentemente “più accurato”. 

Di solito, aumentando K vediamo miglioramenti nei cluster e in ciò che rappresentano fino a un certo punto. Poi iniziamo ad avere rendimenti decrescenti o prestazioni peggiori. Possiamo visualizzarlo per aiutare la decisione sul valore di k con un elbow plot dove l'asse y è una misura della bontà di adattamento e l'asse x è il valore di k. 

sns.lineplot(x = K, y = score)

image12.png

In genere scegliamo il punto in cui i miglioramenti nelle performance iniziano ad appiattirsi o a peggiorare. Vediamo che k = 5 è probabilmente il meglio che possiamo ottenere senza overfitting. 

Possiamo anche vedere che i cluster suddividono abbastanza bene la California in gruppi distinti e che questi cluster si mappano in modo coerente a diverse fasce di prezzo, come si vede sotto. 

sns.scatterplot(data = X_train, x = 'longitude', y = 'latitude', hue = fits[3].labels_)

image6.png

sns.boxplot(x = fits[3].labels_, y = y_train['median_house_value'])

image8.png

Quando fallisce l'analisi di cluster k-means?

Il clustering k-means dà il meglio con dati sferici. Per dati sferici intendiamo dati che si raggruppano nello spazio in stretta prossimità tra loro. Questo è più facile da visualizzare in 2 o 3 dimensioni. Dati che non sono sferici, o non dovrebbero esserlo, non funzionano bene con k-means. Per esempio, k-means non funzionerebbe bene sui dati qui sotto: non riusciremmo a trovare centroidi distinti per clusterizzare in modo diverso i due cerchi o archi, nonostante siano chiaramente due forme distinte che andrebbero etichettate come tali. 

image5.png

Fonte immagine 

Esistono molti altri algoritmi di clustering che funzionano bene con dati non sferici, trattati in Clustering in Machine Learning: 5 Essential Clustering Algorithms.

Dovresti dividere i dati in training e test?

La decisione di dividere i dati dipende dagli obiettivi del clustering. Se l'obiettivo è clusterizzare i dati come punto finale dell'analisi, non è necessario. Se invece userai i cluster come feature in un modello supervisionato o per la previsione (come facciamo nel tutorial Scikit-Learn Tutorial: Baseball Analytics Pt 1), allora dovrai dividere i dati prima del clustering per assicurarti di seguire le best practice del workflow di apprendimento supervisionato. 

Fai un passo oltre

Ora che abbiamo coperto le basi del clustering k-means in Python, puoi dare un'occhiata al corso Unsupervised Learning in Python per una buona introduzione a k-means e ad altri algoritmi non supervisionati. Il nostro corso più avanzato, Cluster Analysis in Python, offre una panoramica più approfondita degli algoritmi di clustering e di come costruirli e affinarli in Python. Infine, puoi anche consultare il tutorial An Introduction to Hierarchical Clustering in Python per un approccio alternativo che crea gerarchie dai dati.

I migliori corsi di Machine Learning

Cluster Analysis in Python

BeginnerSkill Level
4 h
64.9K learners
In questo corso verrai introdotto all'apprendimento non supervisionato tramite tecniche come il clustering gerarchico e k-means usando la libreria SciPy.
See DetailsRight Arrow
Argomenti

Approfondisci il Machine Learning

Corso

Image Modeling with Keras

4 h
39.8K
Impara a fare analisi delle immagini usando Keras con Python creando, addestrando e valutando reti neurali convoluzionali.
Vedi dettagliRight Arrow
Inizia il corso
Mostra altroRight Arrow