K-means (05-01) et va obligar a decidir K abans de veure ni un sol resultat. El clustering jeràrquic inverteix l'ordre: primer construeix totes les agrupacions possibles —des de cada client aïllat fins a un únic grup amb tothom— i després tu tries a quin nivell tallar. El resultat és una estructura en arbre, el dendrograma, que mostra quins clients s'assemblen més, en quin ordre es fusionen els grups i a quina "distància" ocorre cada fusió. En aquesta lliçó aprendràs la mecànica aglomerativa pas a pas (amb un exemple a mà), les mesures d'enllaç que determinen la forma dels clústers, com construir i llegir un dendrograma amb scipy, com aplicar AgglomerativeClustering als clients de MercaFresh i comparar els seus segments amb els de K-means, i quan el preu computacional del jeràrquic val la pena.

Contingut

  1. Aglomeratiu vs. divisiu
  2. Mesures d'enllaç: com es mesura la distància entre grups
  3. Exemple a mà: les primeres fusions
  4. El dendrograma: construcció i lectura
  5. Tallar l'arbre: de jerarquia a segments
  6. Clients MercaFresh amb AgglomerativeClustering
  7. Comparació amb els segments de K-means
  8. Avantatges, cost computacional i quan preferir-lo

Aglomeratiu vs. divisiu

Hi ha dues maneres de construir una jerarquia de grups:

Estratègia Direcció Idea Ús a la pràctica
Aglomerativa (bottom-up) De $n$ clústers a 1 Cada punt comença sol; a cada pas es fusionen els dos clústers més propers L'estàndard: és la que implementen scipy i scikit-learn
Divisiva (top-down) D'1 clúster a $n$ Tots els punts comencen junts; a cada pas es parteix el clúster més heterogeni Rara: decidir la millor partició d'un grup és molt més costós que la millor fusió

Ens centrarem en l'aglomerativa. El seu algorisme és d'una simplicitat notable:

  1. Comença amb $n$ clústers d'un punt cadascun.
  2. Calcula la distància entre tots els parells de clústers.
  3. Fusiona els dos clústers més propers.
  4. Repeteix 2-3 fins que quedi un únic clúster.

Cada fusió queda registrada amb la seva distància, i aquesta seqüència de fusions és la jerarquia. Sense inicialització aleatòria, sense iterar fins a convergir: el resultat és determinista (a igualtat de dades i paràmetres, sempre surt el mateix — a diferència de K-means i el seu random_state).

Mesures d'enllaç: com es mesura la distància entre grups

El pas 2 amaga l'única decisió de disseny important: la distància entre dos punts és l'euclidiana de sempre (04-05), però què és la distància entre dos grups de punts? Cada resposta és una mesura d'enllaç (linkage), i canvia el caràcter del clustering:

Enllaç Distància entre clústers A i B Tendència Risc típic
Single La mínima entre un punt d'A i un de B Clústers allargats, en cadena; detecta formes irregulars Chaining: uneix grups diferents a través d'un pont de punts intermedis
Complete La màxima entre un punt d'A i un de B Clústers compactes i de diàmetre similar Molt sensible a outliers (un punt llunyà infla la distància màxima)
Average La mitjana de totes les distàncies punt a punt entre A i B Compromís entre single i complete Menys interpretable geomètricament
Ward L'increment de variància interna que causaria la fusió Clústers esfèrics i equilibrats, molt semblants a K-means Només té sentit amb distància euclidiana

Dos apunts pràctics:

  • Ward és el valor per defecte assenyat per a segmentació de clients: minimitza a cada fusió el mateix tipus de criteri (variància intraclúster) que K-means minimitza globalment amb la inèrcia, així que produeix grups comparables i estables.
  • Single linkage és el diferent de la família: on Ward i complete veuen esferes, single segueix cadenes de veïns i pot recuperar formes serpentejants. Aquesta idea de "connectar per proximitat local" reapareixerà, portada a l'extrem i ben resolta, a DBSCAN (05-04).

Com que tots els enllaços es basen en distàncies, la regla de 03-05 continua vigent: escala les features abans o les unitats decidiran per tu.

Exemple a mà: les primeres fusions

Prenguem 5 clients de MercaFresh amb una sola feature, recencia_dies, i enllaç single (el més còmode de calcular a mà):

A=3, B=5, C=8, D=40, E=45

Pas 1. Distàncies entre parells: AB=2, AC=5, BC=3, DE=5, CD=32, i la resta majors. La mínima és AB=2 → fusionem {A,B} a distància 2.

Pas 2. Distàncies amb el clúster nou (single = mínim): d({A,B}, C) = min(5, 3) = 3; d({A,B}, D) = 35; DE = 5. La mínima és 3 → fusionem {A,B,C}.

Pas 3. d({A,B,C}, D) = 32; d({A,B,C}, E) = 37; DE = 5. La mínima és 5 → fusionem {D,E}.

Pas 4. Només queden {A,B,C} i {D,E}: es fusionen a distància min(32, 37) = 32.

La seqüència completa — (A,B) a 2, (+C) a 3, (D,E) a 5, (tot) a 32 — explica la història sencera: hi ha dos grups naturals, un de clients recents i un altre de freds, i l'enorme distància de l'última fusió (32 enfront de 5) n'és l'evidència. Aquesta història és exactament el que el dendrograma dibuixa.

El dendrograma: construcció i lectura

Un dendrograma és l'arbre de fusions: les fulles són els punts, cada unió en forma de pont representa una fusió, i l'alçada del pont és la distància a la qual va ocórrer. Amb scipy:

import numpy as np
import matplotlib.pyplot as plt
from scipy.cluster.hierarchy import linkage, dendrogram

X = np.array([[3], [5], [8], [40], [45]])          # l'exemple a ma
Z = linkage(X, method="single")                     # matriu de fusions
dendrogram(Z, labels=["A", "B", "C", "D", "E"])
plt.ylabel("Distància de fusió")
plt.show()

Què fa cada peça:

  • linkage(X, method=...) executa l'algorisme aglomeratiu complet i retorna Z, una matriu amb una fila per fusió: quins dos clústers es van unir, a quina distància i quants punts suma el resultat. Per al nostre exemple, les seves distàncies són exactament les que hem calculat a mà: 2, 3, 5, 32.
  • dendrogram(Z) dibuixa l'arbre. method accepta "single", "complete", "average" i "ward".

Com llegir un dendrograma (l'habilitat important):

  • Ponts baixos = fusions primerenques = punts molt similars. A i B són gairebé el mateix client.
  • Ponts alts = fusions forçades entre grups que s'assemblen poc. El salt de 5 a 32 crida "aquí hi ha dues poblacions diferents".
  • El nombre de clústers a una alçada donada = nombre de línies verticals que talla una horitzontal traçada a aquesta alçada. A alçada 10, la nostra horitzontal talla 2 línies: dos clústers.
flowchart TD
    R["Fusio final (dist. 32)"] --- G1["{A, B, C} (dist. 3)"]
    R --- G2["{D, E} (dist. 5)"]
    G1 --- AB["{A, B} (dist. 2)"]
    G1 --- C["C"]
    AB --- A["A"]
    AB --- B["B"]
    G2 --- D["D"]
    G2 --- E["E"]

Tallar l'arbre: de jerarquia a segments

La jerarquia completa és informativa, però per actuar necessites una partició concreta: s'obté tallant el dendrograma a una alçada. Criteris habituals:

  • Tallar on el salt de distàncies és més gran: just per sota del pont desproporcionadament alt. És l'equivalent jeràrquic del colze de 05-01.
  • Tallar per obtenir una K desitjada: si negoci vol 4 segments, es baixa l'horitzontal fins que talli 4 branques.
  • Un mateix arbre admet diversos talls útils: a gran alçada, "actius vs. adormits" (2 grups, per a un informe executiu); més avall, 4-5 segments operatius (per a campanyes). Aquesta multiescala és una cosa que K-means no ofereix: cada K exigeix reentrenar des de zero.

A scipy, fcluster(Z, t=10, criterion="distance") retorna les etiquetes del tall a alçada 10.

Clients MercaFresh amb AgglomerativeClustering

A scikit-learn l'estimador és AgglomerativeClustering. Reutilitzem la matriu X_esc de 05-01 (RFM + ratio_inactivitat, escalades amb StandardScaler):

from scipy.cluster.hierarchy import linkage, dendrogram
from sklearn.cluster import AgglomerativeClustering
import matplotlib.pyplot as plt

# 1. Dendrograma exploratori amb scipy (sobre dades ESCALADES)
Z = linkage(X_esc, method="ward")
plt.figure(figsize=(10, 4))
dendrogram(Z, truncate_mode="lastp", p=20)   # mostra nomes les 20 darreres fusions
plt.ylabel("Distància (Ward)")
plt.show()

# 2. Tall en 4 clusters amb scikit-learn
agg = AgglomerativeClustering(n_clusters=4, linkage="ward")
rfm["segment_jer"] = agg.fit_predict(X_esc)
print(rfm["segment_jer"].value_counts())

Explicació per a principiants:

  • Amb centenars de clients, un dendrograma complet és un garbuix de fulles il·legible; truncate_mode="lastp", p=20 dibuixa només les 20 fusions finals, que són les que informen la decisió de tall. Busquem el tram on els ponts fan l'estirada: si el salt gran ocorre en passar de 4 a 3 branques, 4 clústers és un tall natural.
  • AgglomerativeClustering demana o bé n_clusters (talla l'arbre per tu) o bé distance_threshold (talla a una alçada, deixant K lliure). linkage="ward" és el valor per defecte i el nostre consell per a aquest cas.
  • No hi ha random_state: el jeràrquic és determinista.
  • Un detall honest: encara que el dendrograma permet no fixar K a priori, al capdavall talles en algun lloc — la diferència és que decideixes veient tota l'estructura, no a cegues provant Ks.

Comparació amb els segments de K-means

Coincideixen els 4 segments jeràrquics amb els 4 de K-means de 05-01? Podem creuar-los amb una taula de contingència (pd.crosstab, que ja vas usar a 03-04):

import pandas as pd
print(pd.crosstab(rfm["segment"], rfm["segment_jer"],
                  rownames=["K-means"], colnames=["Jeràrquic"]))

Un resultat típic:

K-means \ Jeràrquic 0 1 2 3
0 (VIP) 171 9 0 0
1 (Habituals) 6 385 0 19
2 (Adormits) 0 0 148 2
3 (Ocasionals) 0 31 4 225

La lectura: cada fila concentra la seva massa en una columna — tots dos algorismes han descobert essencialment els mateixos quatre grups (recorda que els números de clúster són arbitraris; el que importa és la correspondència). No és casualitat: Ward i K-means optimitzen criteris de variància molt semblants. Els desacords (els ~70 clients fora de la diagonal) són punts fronterers entre segments — precisament els que tindrien un silhouette proper a 0 a 05-01. Quan dos algorismes diferents coincideixen així, la confiança que els segments són estructura real (i no un artefacte del mètode) puja molt; si discrepessin del tot, tocaria sospitar d'una estructura feble.

Avantatges, cost computacional i quan preferir-lo

Aspecte Clustering jeràrquic K-means
K a priori No: es decideix veient el dendrograma Sí, abans d'executar
Resultat Jerarquia completa multiescala Una partició per a aquesta K
Determinisme Total Depèn de la inicialització (n_init mitiga)
Formes de clúster Segons l'enllaç (single permet formes allargades) Esfèriques
Cost $O(n^2)$ memòria, $O(n^2)$–$O(n^3)$ temps $O(n \cdot K \cdot i)$: gairebé lineal
Escala pràctica Milers de punts Milions de punts

El cost mereix aturar-s'hi: el pas 2 de l'algorisme necessita la matriu de distàncies entre tots els parells de punts — amb $n$ clients són de l'ordre de $n^2/2$ distàncies. Amb els ~1.000 clients de MercaFresh, mig milió de distàncies: instantani. Amb 10 milions de clients d'una gran cadena, $5 \times 10^{13}$ parells: senzillament inviable, mentre que K-means continuaria funcionant.

Quan preferir el jeràrquic:

  • Dataset petit o mitjà (fins a desenes de milers de punts).
  • No tens ni idea de quants grups hi ha i vols veure l'estructura abans de decidir.
  • La jerarquia en si té valor de negoci: taxonomies de productes (begudes > refrescos > coles), grups dins de grups, informes a diferents nivells de detall.
  • Vols un resultat reproduïble sense llavors ni inicialitzacions.

Quan K-means: datasets grans, K raonablement clara, o quan necessites resegmentar sovint i ràpid.

Errors Comuns i Consells

  • Executar linkage sobre dades sense escalar. El mateix pecat capital de 05-01: el dendrograma resultant ordena per la feature de major magnitud. Escala sempre abans.
  • Dibuixar el dendrograma complet amb milers de punts. Il·legible i lent. Usa truncate_mode="lastp" amb p entre 15 i 30: les fusions finals són les que informen el tall.
  • Usar Ward amb distàncies no euclidianes. Ward està definit sobre variàncies, que pressuposen l'euclidiana. Si necessites una altra distància (Manhattan, cosinus), canvia a average o complete linkage.
  • Esperar que single linkage doni grups compactes. La seva especialitat són les cadenes; amb dades sorolloses sol produir un megaclúster i diversos punts solts. Per a segmentació de clients, Ward o complete.
  • Consell: valida el tall amb el silhouette de 05-01 (silhouette_score(X_esc, etiquetes) funciona amb qualsevol clustering, no només K-means) i compara dos o tres talls candidats.

Exercicis

Exercici 1. Repeteix a mà l'exemple de la lliçó (A=3, B=5, C=8, D=40, E=45) però amb enllaç complete. Escriu la seqüència de fusions amb les seves distàncies. Canvia l'ordre de les fusions respecte de single? Canvia l'estructura final de dos grups?

Exercici 2. Genera el dendrograma Ward dels clients MercaFresh (o d'un dataset sintètic amb make_blobs(n_samples=200, centers=4, random_state=7), escalat). Localitza visualment el salt de distàncies més gran i decideix un nombre de clústers. Després talla amb AgglomerativeClustering a aquesta K i calcula el silhouette. Coincideix el teu tall visual amb el millor silhouette entre K=2 i K=6?

Exercici 3. Sobre el mateix dataset, compara linkage="ward" i linkage="single" amb n_clusters=4: imprimeix el value_counts() de les etiquetes de cadascun. Quin patró de mides produeix cada enllaç i per què?

Solucions

Exercici 1

Amb complete (màxim en lloc de mínim):

  • Fusió 1: la mínima distància entre parells continua sent AB=2 → {A,B} a 2.
  • Fusió 2: d({A,B}, C) = max(5, 3) = 5; DE = 5. Empat a 5; scipy fusiona el primer que troba — diguem {A,B,C} a 5 (amb complete, l'ordre de l'empat és igual per al resultat final).
  • Fusió 3: {D,E} a 5.
  • Fusió 4: d({A,B,C}, {D,E}) = màxim de totes les distàncies creuades = d(A,E) = 42 → fusió final a 42.

L'ordre és essencialment el mateix i l'estructura final també ({A,B,C} vs. {D,E}): amb grups tan separats, tots els enllaços coincideixen. Les diferències entre enllaços afloren amb dades ambigües, ponts de punts intermedis o outliers — no amb illes netes. Nota com la fusió final puja de 32 (single, distància entre els punts més propers de tots dos grups) a 42 (complete, els més llunyans).

Exercici 2

from sklearn.datasets import make_blobs
from sklearn.preprocessing import StandardScaler
from sklearn.cluster import AgglomerativeClustering
from sklearn.metrics import silhouette_score
from scipy.cluster.hierarchy import linkage, dendrogram

X, _ = make_blobs(n_samples=200, centers=4, random_state=7)
X_esc = StandardScaler().fit_transform(X)

dendrogram(linkage(X_esc, method="ward"), truncate_mode="lastp", p=20)
plt.show()

for k in range(2, 7):
    lab = AgglomerativeClustering(n_clusters=k, linkage="ward").fit_predict(X_esc)
    print(f"K={k} | silhouette = {silhouette_score(X_esc, lab):.3f}")

Al dendrograma, el salt d'alçada més gran ocorre en passar de 4 branques a 3 (els quatre blobs són reals), i el silhouette màxim apareix també a K=4. Quan el criteri visual i el numèric coincideixen, la decisió està ben fonamentada; si discrepen, sol ser senyal de clústers de densitat o mida desiguals — val la pena mirar l'scatter.

Exercici 3

Ward produeix 4 grups de mides comparables (reparteix la variància de manera equilibrada). Single sol produir un patró molt diferent: un o dos clústers enormes i altres amb un grapat de punts (fins i tot 1), perquè l'encadenament va annexionant tot allò connectable per veïns propers i només deixa fora els punts veritablement aïllats. Aquest comportament, que aquí sembla un defecte, és gairebé una detecció d'outliers — una intuïció que DBSCAN (05-04) convertirà en virtut amb la noció explícita de soroll.

Conclusió

Ja domines la segona família del clustering: l'enfocament aglomeratiu que fusiona a cada pas els dos grups més propers, les quatre mesures d'enllaç i el seu efecte en la forma dels clústers (Ward com a parent de K-means, single com a rastrejador de cadenes), el dendrograma com a radiografia multiescala de l'estructura i el tall que el converteix en segments. Sobre MercaFresh vas comprovar a més una cosa valuosa: jeràrquic i K-means coincideixen en els mateixos quatre segments, senyal que l'estructura és real. I en coneixes el preu: $O(n^2)$ que el fa inviable a gran escala.

Fins ara hem agrupat els clients usant les seves 4 features RFM, i les hem pogut imaginar de dues en dues. Però el dataset final de 03-06 té moltes més columnes, i a 04-05 va quedar anotada una amenaça: la maledicció de la dimensionalitat, que degrada les distàncies — l'ingredient bàsic de tot el que hem fet en aquest mòdul. La lliçó següent ataca aquest problema de cara: PCA, la tècnica que comprimeix moltes dimensions en poques conservant el màxim d'informació, i que a més ens permetrà per fi dibuixar els nostres segments.

Curs de Machine Learning

Mòdul 1: Introducció al Machine Learning

Mòdul 2: Fonaments d'Estadística i Probabilitat

Mòdul 3: Preprocessament de Dades

Mòdul 4: Algorismes de Machine Learning Supervisat

Mòdul 5: Algorismes de Machine Learning No Supervisat

Mòdul 6: Avaluació i Validació de Models

Mòdul 7: Tècniques Avançades i Optimització

Mòdul 8: Implementació i Desplegament de Models

Mòdul 9: Projectes Pràctics

Mòdul 10: Recursos Addicionals

© Copyright 2026. Tots els drets reservats