Come usare gli Alberi Decisionali per classificare i dati

Quando analizziamo un dataset con molte variabili e vogliamo prevedere una categoria — se un utente convertirà o no, se una pagina andrà in top 10, se una keyword è ad alta o bassa competizione — il primo problema è capire quali variabili contano davvero e come combinarle.
Gli alberi decisionali affrontano questo problema nel modo più naturale che ci sia: una sequenza di domande sì/no che, passo dopo passo, separano i dati in gruppi sempre più omogenei.

L’idea generale

Un albero decisionale è una struttura che prende decisioni in sequenza. Ogni nodo interno dell’albero pone una domanda (per esempio: “la lunghezza del petalo è maggiore di 2.45 cm?”), e in base alla risposta segue un ramo verso il nodo successivo. Si arriva così a una foglia, che assegna la classe di appartenenza.

La potenza dell’idea è che il risultato è intrinsecamente interpretabile: si può capire perché l’albero ha preso una certa decisione, semplicemente seguendo il percorso dalle radici alla foglia. Nessuna scatola nera.

Impurity e criteri di divisione

Come decide l’albero quale domanda fare per prima? L’obiettivo è trovare la divisione che separa i dati nel modo più “pulito” possibile. Il concetto centrale è l’impurità (impurity): una suddivisione perfetta è quella in cui tutti gli elementi di un gruppo appartengono alla stessa classe.

La misura più comune è l’indice di Gini. Per un nodo con \( K \) classi, dove \( p_k \) è la proporzione di elementi della classe \( k \), si definisce:

\( G = \sum_{k=1}^{K} p_k (1 – p_k) \\ \)

L’indice vale 0 quando il nodo è puro (tutti gli elementi della stessa classe), e raggiunge il massimo quando le classi sono uniformemente distribuite.
L’albero prova tutte le possibili divisioni su tutte le variabili e sceglie quella che riduce di più l’impurità media ponderata dei due nodi figli.

Esistono anche altre misure, come l’entropia (usata per costruire alberi C4.5), ma l’idea è la stessa: minimizzare l’incertezza.

Un albero decisionale in R sui dati iris

Costruiamo un albero decisionale con R usando il dataset iris, che contiene 150 fiori con le misure di sepali e petali di tre specie. Il nostro obiettivo è classificare la specie in base alle misure.

Prepariamo i dati:

data(iris)
library(rpart)

set.seed(123)
train_idx <- sample(1:nrow(iris), 0.8 * nrow(iris))
train <- iris[train_idx, ]
test  <- iris[-train_idx, ]

tree <- rpart(Species ~ ., data = train, method = "class")

Visualizziamo l’albero:

library(rpart.plot)
rpart.plot(tree, type = 2, extra = 104)
Albero decisionale: classificazione delle specie di iris
Albero decisionale: classificazione delle specie di iris

L’albero è semplicissimo. Parte dalla radice con una domanda sulla lunghezza del petalo. Se è minore di 2.45 cm, abbiamo la certezza che si tratta di setosa (tutti i 41 casi del training set finiscono lì). Se è maggiore, entriamo nel ramo successivo, che separa versicolor da virginica basandosi ancora sulla lunghezza del petalo, questa volta con soglia 4.75 cm.

La cosa notevole è che l’albero non ha usato affatto le misure dei sepali: le ha trovate irrilevanti per la classificazione, e le ha ignorate automaticamente. Questa è una forma implicita di selezione delle variabili: l’albero sceglie da solo quali metriche contano, e in che ordine.

Un esempio SEO: prevedere le pagine in top 10

Iris va bene per capire il meccanismo, ma proviamo qualcosa di più vicino al nostro lavoro quotidiano. Generiamo dati sintetici di 200 pagine web con metriche SEO reali — parole, leggibilità, velocità, backlink, immagini, keyword nel title, lunghezza della meta descrizione — e costruiamo un albero che preveda se una pagina arriverà in top 10.

set.seed(2026)

n <- 200
word_count      <- round(runif(n, 300, 3000))
readability     <- round(runif(n, 20, 80), 1)
page_speed_ms   <- round(runif(n, 500, 8000))
backlinks       <- round(runif(n, 0, 150))
images          <- round(runif(n, 0, 20))
keyword_in_title <- rbinom(n, 1, 0.35)
meta_desc_len   <- round(runif(n, 0, 165))

# target simulato: top_10 basato su combinazione di fattori
score <- (
  (backlinks > 30) * 0.30 +
  (keyword_in_title == 1) * 0.20 +
  (readability > 45 & readability < 70) * 0.15 +
  (word_count > 800 & word_count < 2200) * 0.15 +
  (page_speed_ms < 3000) * 0.10 +
  (meta_desc_len > 110 & meta_desc_len < 155) * 0.10
)
score <- score + rnorm(n, 0, 0.12)
top_10 <- factor(ifelse(score > 0.50, "si", "no"))

seo_data <- data.frame(word_count, readability, page_speed_ms,
                       backlinks, images, keyword_in_title,
                       meta_desc_len, top_10)

La variabile target top_10 è stata costruita in modo che dipenda da tutti questi fattori, ciascuno con un peso diverso — i backlink sono i più influenti, seguiti dalla presenza della keyword nel title, da una leggibilità nella fascia giusta, e così via. Aggiungiamo anche una componente casuale per simulare ciò che non possiamo misurare.

Alleniamo l’albero:

library(rpart)
train_idx <- sample(1:n, 0.7 * n)
tree_seo <- rpart(top_10 ~ ., data = seo_data[train_idx, ],
                  method = "class", control = rpart.control(cp = 0.01))

Visualizziamo l’albero risultante:

library(rpart.plot)
rpart.plot(tree_seo, type = 2, extra = 104)
Albero decisionale: previsione pagine in top 10
Albero decisionale: previsione pagine in top 10

L’albero ci dice qualcosa di molto interessante. La prima domanda — la variabile più discriminante — riguarda i backlink: se sono pochi, la pagina difficilmente entra in top 10, indipendentemente dagli altri fattori. Solo le pagine con un numero sufficiente di backlink passano al ramo successivo, dove l’albero valuta la leggibilità e la presenza della keyword nel title. È esattamente il genere di gerarchia che ci aspetteremmo da un’analisi SEO seria: prima l’autorità (backlink), poi la qualità on-page.

La feature importance conferma questa gerarchia:

tree_seo$variable.importance
Importanza delle variabili SEO
Importanza delle variabili SEO

I backlink dominano, come previsto. Poi vengono leggibilità e keyword nel title, mentre la velocità e la lunghezza della meta descrizione contribuiscono meno. L’albero non ha selezionato il numero di immagini come rilevante — nei nostri dati sintetici non lo era, e l’albero lo ha ignorato.

n.b. Questi dati sono sintetici: in un progetto reale con dati reali, l’albero rivelerebbe la gerarchia effettiva delle variabili per il vostro specifico contesto. L’esempio serve a mostrare il tipo di risposta che si ottiene, non a stabilire verità universali.

Un’avvertenza importante: l’albero individua schemi ricorrenti nei dati osservati, non relazioni di causa-effetto. Una variabile può risultare molto utile per prevedere il comportamento di una pagina senza esserne la causa diretta. Per esempio, se l’albero seleziona il CTR come variabile discriminante, non significa che aumentare il CTR farà salire la pagina in top 10 — potrebbe essere che le pagine in top 10 tendono ad avere un CTR più alto perché sono già in top 10. L’albero ci dice cosa è correlato, non cosa è causale.

Valutare l’accuratezza

Verifichiamo come si comporta sui dati di test:

pred <- predict(tree, newdata = test, type = "class")
table(pred, test$Species)

La tabella di contingenza (matrice di confusione) mostra quante predizioni sono corrette e quante no. L’accuratezza si calcola come:

\( \text{accuratezza} = \frac{\text{predizioni corrette}}{\text{predizioni totali}} \\ \)

Il nostro albero sbaglia pochissimo: è un modello semplice e i dati iris sono ben separabili. Nel mondo reale, però, le cose sono quasi sempre più complesse.

Overfitting e potatura

Qui arriviamo al punto delicato. Un albero decisionale può continuare a suddividersi finché ogni foglia contiene un solo elemento. In quel caso, l’accuratezza sul training set sarà del 100%. Ma l’albero avrà semplicemente memorizzato il dataset di addestramento invece di impararne le regolarità.

Questo fenomeno si chiama overfitting: il modello si adatta troppo ai dati di addestramento, catturando rumore e dettagli specifici che non si ripresenteranno sui dati nuovi.

L’overfitting è il problema principale degli alberi decisionali. Un albero troppo profondo memorizza il training set ma fallisce sui dati nuovi; uno troppo superficiale non coglie le strutture reali dei dati. Il punto giusto si trova con tecniche di validazione incrociata e potatura (pruning): si costruisce un albero volutamente grande e poi si tagliano i rami che non migliorano l’errore di previsione.

In R, si può potare l’albero con rpart usando il parametro cp (complexity parameter), che impedisce all’albero di fare divisioni che non riducono l’errore di almeno una certa soglia. La funzione printcp(tree) mostra l’errore di validazione incrociata per diverse dimensioni dell’albero, aiutando a scegliere il punto di taglio.

Importanza delle variabili

Uno dei sottoprodotti più utili di un albero decisionale è la feature importance: la misura di quanto ogni variabile contribuisce alla riduzione dell’impurità complessiva. In rpart si ottiene con:

tree$variable.importance

Questo ci dice, per esempio, che la lunghezza del petalo è di gran lunga la variabile più discriminante per l’iris — e le misure dei sepali contano poco o nulla.
Nel web marketing, un’analisi analoga si può fare per capire quali metriche separano davvero le pagine ad alte prestazioni da quelle a basse prestazioni.

Dai singoli alberi alle foreste: la Random Forest

Un singolo albero decisionale è instabile: un piccolo cambiamento nei dati di partenza può produrre un albero completamente diverso. Per ridurre questo problema, le Random Forest (foreste casuali) costruiscono centinaia di alberi su versioni leggermente diverse dei dati (campionamento con reinserimento) e ne mediano le previsioni. Il risultato è molto più stabile e accurato di un singolo albero, pur mantenendo gran parte dell’interpretabilità.

Se un singolo albero è come chiedere il parere di un esperto, una Random Forest è come consultare centinaia di esperti indipendenti e prendere la decisione per maggioranza.

Ne parleremo in un prossimo articolo.

FAQ

Quando usare un albero decisionale invece di una regressione logistica?
Quando i dati hanno interazioni complesse tra variabili (per esempio, l’effetto dell’età sulla conversione cambia a seconda del canale di acquisizione) e quando la priorità è l’interpretabilità.

L’albero può gestire variabili numeriche e categoriche insieme?
Sì, rpart gestisce naturalmente entrambi i tipi. Le variabili categoriche vengono convertite internamente in split binari.

Quanto deve essere profondo un albero?
Dipende dai dati. La regola pratica: usare la validazione incrociata (il plotcp() di rpart) per trovare la profondità che minimizza l’errore di previsione su dati non visti.

L’albero decisionale funziona anche per problemi di regressione?
Sì. Con method = "anova" invece di "class", l’albero prevede valori numerici (per esempio, il tempo sulla pagina atteso).

Perché l’albero ha usato solo la lunghezza del petalo?
Perché nei dati iris è la variabile più discriminante: da sola basta per separare una delle tre specie (setosa) e quasi separa le altre due. L’albero, essendo un algoritmo greedy, sceglie la variabile che dà la miglior divisione immediata.


Tra gli alberi decisionali, la discesa del gradiente e la riduzione delle dimensioni c’è un filo che li unisce: tutti risolvono il problema di dare struttura a dati complessi, ciascuno con il proprio approccio. La prossima tappa di questo percorso è la discesa del gradiente, il motore che fa funzionare buona parte del machine learning moderno.

Per approfondire

Se vuoi approfondire gli alberi decisionali, An Introduction to Statistical Learning di James, Witten, Hastie e Tibshirani è il punto di riferimento: spiega alberi, Random Forest e criteri di divisione con il giusto equilibrio tra intuizione e formalismo. I laboratori R sono liberamente disponibili online.

L’algoritmo di Discesa del Gradiente spiegato in modo chiaro: dall’intuizione alla pratica

Una persona bendata su una montagna

Immagina di trovarti su un terreno montagnoso, completamente bendato. Il tuo obiettivo: raggiungere il punto più basso della valle. Non puoi vedere nulla, ma puoi sentire la pendenza del terreno sotto i piedi. Cosa fai? Ti muovi nella direzione in cui il terreno scende, un passo alla volta. Se scende più ripidamente a sinistra, vai a sinistra. Se scende di più a destra, vai a destra. Ad ogni passo, senti di nuovo la pendenza e cambi direzione.

Questa strategia, così semplice e naturale, è esattamente quella che le reti neurali usano per imparare. Ogni volta che un modello di intelligenza artificiale migliora — che impari a riconoscere un volto, tradurre una frase, o generare un testo — lo fa scendendo lungo un paesaggio matematico, un passo alla volta, seguendo la pendenza.

Si chiama discesa del gradiente (gradient descent), ed è probabilmente l’algoritmo più importante del machine learning moderno.

Infografica: la metafora dell'esploratore bendato che cerca il fondo della valle, con i tre passaggi Sensore, Azione, Ciclo
Leggi tutto “L’algoritmo di Discesa del Gradiente spiegato in modo chiaro: dall’intuizione alla pratica”

La Discesa del Gradiente: un nuovo studio mette in discussione un assunto base sull’ottimizzazione

Nel 1847, il matematico francese Augustin-Louis Cauchy stava lavorando su calcoli astronomici, quando ideò un metodo comune di ottimizzazione ora noto come discesa del gradiente. Oggi la maggior parte dei programmi di machine learning si basa su questa tecnica, e anche altri campi la usano per analizzare dati e risolvere problemi ingegneristici.

Leggi tutto “La Discesa del Gradiente: un nuovo studio mette in discussione un assunto base sull’ottimizzazione”

La distribuzione ipergeometrica

Abbiamo visto che la distribuzione binomiale si basa sull’ipotesi di una popolazione infinita N, condizione che si può realizzare in pratica campionando da una popolazione finita con reintroduzione.

Se ciò non avviene, cioè se operiamo campionando da una popolazione senza reintroduzione dobbiamo avvalerci della distribuzione ipergeometrica. (In realtà, se N è grande la funzione di probabilità di densità ipergeometrica tende alla binomiale).

La distribuzione ipergeometrica si usa per calcolare la probabilità di ottenere un certo numero di successi in una serie di tentativi binari (sì o no), dipendenti e con una probabilità di successo variabile.

La distribuzione ipergeometrica ci consente di rispondere a quesiti del tipo:

Se prendo un campione di dimensione N, in cui M elementi soddisfano determinati requisiti, qual è la probabilità di estrarre x elementi che soddisfano quei requisiti?

Leggi tutto “La distribuzione ipergeometrica”

La distribuzione binomiale negativa (o distribuzione di Pascal)

La distribuzione binomiale negativa descrive il numero di prove necessarie per ottenere un certo numero di successi in una serie di prove indipendenti. Ad esempio, potrebbe essere utilizzata per calcolare la probabilità di ottenere tre teste lanciando una moneta 5 volte, supponendo che la moneta sia bilanciata e quindi che a ogni lancio la probabilità di ottenere una testa sia del 50%.

La distribuzione binomiale negativa è utile in molti campi, tra cui la statistica, l’economia, la biologia e la fisica. E anche nella “nostra” SEO.

Leggi tutto “La distribuzione binomiale negativa (o distribuzione di Pascal)”