A 04-05, en estudiar K-NN, va quedar anotada una amenaça amb nom propi: la maledicció de la dimensionalitat. I en aquest mòdul l'amenaça és directa, perquè clustering vol dir distàncies, i les distàncies es degraden quan les dimensions es multipliquen. L'Anàlisi de Components Principals (PCA) és la resposta clàssica: una tècnica no supervisada que comprimeix moltes features en pocs components nous, conservant el màxim possible de la variància —és a dir, de la informació— original. En aquesta lliçó entendràs el problema que resol, la intuïció geomètrica de "girar els eixos cap on són les dades", els conceptes de variància explicada i acumulada, la seva connexió amb la matriu de covariància de 02-03, i el seu ús pràctic a MercaFresh: visualitzar en 2D els segments de 05-01 i interpretar què significa cada component a través dels seus loadings.

Contingut

  1. La maledicció de la dimensionalitat
  2. Intuïció geomètrica: girar els eixos cap a la màxima variància
  3. Components principals, variància explicada i scree plot
  4. La connexió amb la covariància (02-03) i per què estandarditzar abans (03-05)
  5. PCA amb scikit-learn sobre els clients MercaFresh
  6. Visualització 2D dels segments de K-means
  7. Interpretar components: els loadings
  8. PCA com a pas previ a models
  9. Limitacions, i PCA vs. selecció de features (03-06)

La maledicció de la dimensionalitat

Què passa quan les features passen de 4 a 40 o a 400? Tres mals es combinen:

  • L'espai es buida. Per cobrir un interval 1D amb 10 punts ben repartits en calen 10; per cobrir amb la mateixa densitat un cub de 10 dimensions caldrien $10^{10}$. Amb dimensions de sobres, tot dataset és un pessic de pols en un espai desert: els punts són lluny de tot.
  • Les distàncies perden contrast. En alta dimensió, la distància al veí més proper i al més llunyà tendeixen a assemblar-se. I si "a prop" i "lluny" amb prou feines es distingeixen, K-NN (04-05), K-means (05-01) i el jeràrquic (05-02) —tots construïts sobre distàncies— perden la seva matèria primera.
  • Soroll acumulat. Cada feature irrellevant afegeix el seu soroll a la distància euclidiana; amb moltes, el soroll ofega el senyal de les poques que importen.

La sortida òbvia seria treure les features irrellevants (els filtres de selecció de 03-06). Però, i si moltes features són rellevants però redundants entre si — com despesa_total i num_comandes, correlacionades a 02-03? Aquí no vols eliminar columnes: vols fusionar la informació en menys dimensions. Això és reducció de dimensionalitat, i PCA n'és la tècnica reina.

Intuïció geomètrica: girar els eixos cap a la màxima variància

Imagina l'scatter de dues features correlacionades de MercaFresh: despesa_total enfront de num_comandes (estandarditzades). El núvol de punts és una el·lipse inclinada: qui fa més comandes, gasta més en total. Observa dues coses:

  • La direcció diagonal de l'el·lipse concentra gairebé tota la variació entre clients: és l'eix "mida del client" (molt/poc de totes dues coses alhora).
  • La direcció perpendicular amb prou feines varia: només recull el matís "gasta més/menys del que suggereix el seu nombre de comandes".

PCA formalitza exactament aquesta observació: troba eixos nous, girant els originals, de manera que el primer eix apunti cap on les dades més varien; el segon, perpendicular al primer, cap a la màxima variància restant; i així successivament.

flowchart LR
    A["Eixos originals:<br/>despesa_total, num_comandes<br/>(correlacionats, redundants)"] -->|"rotacio PCA"| B["Eixos nous:<br/>PC1 = mida del client (var. 95%)<br/>PC2 = matis residual (var. 5%)"]
    B --> C["Compressio: quedar-se<br/>nomes amb PC1 perd<br/>amb prou feines un 5% d'informacio"]

Els eixos nous són els components principals (PC1, PC2, ...). Tres propietats que convé gravar-se:

  • Cada component és una combinació lineal de les features originals (per exemple, PC1 ≈ 0,71·despesa + 0,71·comandes): no tria columnes, les barreja.
  • Els components són perpendiculars entre si i, per construcció, no correlacionats: PCA converteix features redundants en direccions independents.
  • Estan ordenats per variància: PC1 en captura més que PC2, que en captura més que PC3... Comprimir és simplement quedar-se amb els primers i descartar la resta.

En aquest sentit, "informació" per a PCA significa variància: les direccions on els clients difereixen molt entre si són les que permeten distingir-los; una direcció amb variància gairebé nul·la no diu gairebé res de ningú (el mateix argument del filtre de variància de 03-06).

Components principals, variància explicada i scree plot

Quants components conservar? El criteri és la variància explicada: quina fracció de la variància total captura cada component.

  • explained_variance_ratio_ a scikit-learn: per exemple [0.55, 0.25, 0.12, 0.05, 0.03] — PC1 explica el 55%, PC2 el 25%...
  • La variància acumulada suma en ordre: amb 2 components, 80%; amb 3, 92%. La regla pràctica més usada: conservar els components necessaris per acumular el 90-95%.
  • L'scree plot dibuixa la variància explicada per component. Igual que al colze de 05-01, es busca el punt on la corba s'aplana: els components després del colze aporten engrunes (sovint, soroll).
Eina Què mostra Decisió que dona suport
explained_variance_ratio_ % de variància de cada PC Val res la PC3?
Variància acumulada % total amb els k primers PCs Quants en conservo per al 90%?
Scree plot La corba de les dues anteriors Localitzar el colze visualment

La connexió amb la covariància (02-03) i per què estandarditzar abans (03-05)

D'on surten aquestes direccions màgiques? De la matriu de covariància que vas estudiar a 02-03: la taula que recull com covaria cada parell de features. PCA analitza aquesta matriu i n'extreu les seves direccions característiques — cada component principal és una d'aquestes direccions, i la seva variància explicada, la magnitud associada (en àlgebra lineal es diuen vectors propis i valors propis; no ens cal la derivació completa, només la conseqüència):

PCA és la matriu de covariància feta eixos. On el heatmap de correlacions de 02-03 et deia "despesa i comandes van juntes", PCA et dona l'eix concret que resumeix aquest anar-juntes.

D'aquí surt també la regla d'or pràctica: estandarditza abans de PCA (03-05, StandardScaler). La covariància depèn de les unitats: si despesa_total es mesura en euros (variància en milers) i comandes_per_mes en unitats (variància en desenes), la direcció de màxima variància serà "l'eix de la despesa" per pur accident d'unitats, i PC1 serà un eco de la columna més gran. Estandarditzar iguala totes les variàncies a 1, amb la qual cosa PCA treballa de fet sobre la matriu de correlació i les direccions reflecteixen estructura, no unitats. És el mateix argument que a K-means; a PCA és encara més crític perquè la variància no és només la mètrica interna sinó el criteri de construcció.

PCA amb scikit-learn sobre els clients MercaFresh

Ampliem la matriu de clients amb més features del mòdul 3 —RFM, ràtios i tendència— perquè la reducció tingui sentit:

from sklearn.preprocessing import StandardScaler
from sklearn.decomposition import PCA
import matplotlib.pyplot as plt
import numpy as np

features = ["recencia_dies", "comandes_per_mes", "despesa_mitjana_comanda",
            "despesa_total", "num_comandes", "ratio_inactivitat", "tendencia"]
X = rfm[features]

X_esc = StandardScaler().fit_transform(X)      # SEMPRE abans de PCA

pca = PCA()                                    # sense limit: tots els components
X_pca = pca.fit_transform(X_esc)

print(pca.explained_variance_ratio_.round(3))
# p. ex.: [0.46  0.27  0.12  0.07  0.05  0.02  0.01]
print(np.cumsum(pca.explained_variance_ratio_).round(3))
# p. ex.: [0.46  0.73  0.85  0.92  0.97  0.99  1.00]

# Scree plot
plt.plot(range(1, 8), pca.explained_variance_ratio_, "o-")
plt.xlabel("Component principal")
plt.ylabel("Variància explicada")
plt.title("Scree plot — clients MercaFresh")
plt.show()

Lectura del resultat:

  • fit_transform projecta cada client sobre els eixos nous: X_pca té una columna per component, ordenades de major a menor variància.
  • Dos components acumulen un 73% i quatre un 92%: les 7 features originals eren en bona part redundants (despesa total, nombre de comandes i freqüència expliquen històries solapades — ho sabíem des del heatmap de 02-03).
  • Alternatives còmodes del constructor: PCA(n_components=2) (nombre fix) o PCA(n_components=0.90) (scikit-learn tria els necessaris per acumular el 90%).

Visualització 2D dels segments de K-means

L'ús més immediat de PCA: els nostres segments de 05-01 viuen en un espai que no podem dibuixar; projectats sobre PC1-PC2, sí.

pca2 = PCA(n_components=2)
X_2d = pca2.fit_transform(X_esc)

plt.scatter(X_2d[:, 0], X_2d[:, 1], c=rfm["segment"], cmap="tab10", s=15)
plt.xlabel(f"PC1 ({pca2.explained_variance_ratio_[0]:.0%} var.)")
plt.ylabel(f"PC2 ({pca2.explained_variance_ratio_[1]:.0%} var.)")
plt.title("Segments K-means de MercaFresh en el pla PCA")
plt.colorbar(label="segment")
plt.show()

Acolorim cada punt pel segment que K-means li va assignar (c=rfm["segment"]). Si els quatre colors apareixen en zones raonablement diferenciades del pla, tenim confirmació visual que els segments són regions reals de l'espai de clients. Amb un matís honest: el pla només mostra el 73% de la variància — dos clústers que se solapin al dibuix poden estar separats en la dimensió que el pla no mostra. La projecció és un mapa, no el territori.

Interpretar components: els loadings

PC1 i PC2 són barreges de features. Què signifiquen? La resposta és als loadings: els pesos amb què cada feature original entra en cada component, disponibles a pca.components_.

import pandas as pd
loadings = pd.DataFrame(pca2.components_.T,
                        columns=["PC1", "PC2"], index=features).round(2)
print(loadings)
Feature PC1 PC2
recencia_dies 0,45 0,21
comandes_per_mes −0,44 0,25
despesa_mitjana_comanda −0,12 0,62
despesa_total −0,41 0,48
num_comandes −0,43 0,18
ratio_inactivitat 0,47 0,15
tendencia −0,11 −0,50

Com es llegeixen (signes i valors són il·lustratius):

  • PC1 enfronta recència i ràtio d'inactivitat (pesos positius) contra freqüència i volum (negatius): és un eix d'activitat, de "client viu" (PC1 molt negatiu) a "client apagat" (PC1 molt positiu). No sorprèn que els segments "VIP" i "adormits" de 05-01 ocupin extrems oposats d'aquest eix.
  • PC2 carrega sobre despesa mitjana i total amb signe positiu i tendència amb negatiu: un eix de valor del tiquet, que separa els habituals de tiquet alt dels ocasionals barats.
  • El signe global d'un component és arbitrari (l'eix pot apuntar cap a qualsevol dels seus dos sentits); l'interpretable són els signes relatius entre features i la magnitud dels pesos.

Amb els loadings, els eixos de l'scatter deixen de ser abstractes: el mapa de clients té un eix horitzontal "activitat" i un de vertical "valor" — vocabulari que negoci entén.

PCA com a pas previ a models

A més de visualitzar, PCA s'usa com a preprocessament: entrenar el model sobre els k primers components en lloc de les features originals. Beneficis: menys dimensions (alleuja la maledicció per a K-NN o K-means), sense colinealitat (els PCs no estan correlacionats) i menys soroll (els últims components solen ser soroll i es descarten). S'integra en el Pipeline que ja coneixes del mòdul 4:

from sklearn.pipeline import Pipeline
from sklearn.cluster import KMeans

pipe = Pipeline([
    ("escala", StandardScaler()),
    ("pca",    PCA(n_components=0.90)),   # PCs fins al 90% de la variancia
    ("kmeans", KMeans(n_clusters=4, random_state=42)),
])
etiquetes = pipe.fit_predict(X)

L'ordre importa i ja el pots justificar sencer: escalar (perquè PCA no hereti les unitats) → PCA (perquè K-means treballi amb poques dimensions informatives) → clustering. La contrapartida: els centroides queden expressats en components, i per perfilar-los en unitats de negoci cal desfer les dues transformacions (inverse_transform del PCA i de l'scaler, encadenats).

Limitacions, i PCA vs. selecció de features (03-06)

Limitacions de PCA:

  • És lineal. Només troba rotacions: si l'estructura de les dades és corba (una espiral, un manifold cargolat), cap rotació no la desplega. Per visualitzar estructura no lineal existeixen t-SNE i UMAP (05-05).
  • Interpretabilitat. "PC1 = 0,45·recència − 0,44·freqüència + ..." mai no serà tan transparent com una feature original. Els loadings ajuden, però explicar un model entrenat sobre PCs a un comitè de negoci costa més.
  • Variància ≠ rellevància. PCA conserva les direccions de major variància sense saber per a què usaràs les dades: en un problema supervisat, el senyal que separa les classes podria viure en un component de poca variància que has descartat. És no supervisat també en aquest sentit: ignora qualsevol y.
  • Hereta la sensibilitat a outliers de la variància (02-01): un client extrem pot torçar un component sencer. Neteja (03-01) o log (03-03) abans.

I una distinció conceptual important amb allò vist a 03-06:

Selecció de features (03-06) PCA (compressió)
Què fa Tria un subconjunt de columnes originals Crea columnes noves barrejant-les totes
Les descartades Desapareixen del model La seva informació pot sobreviure barrejada als PCs
Interpretabilitat Total: les columnes continuen sent recencia_dies, etc. Parcial: eixos abstractes, interpretats via loadings
Quan preferir Features irrellevants o interpretabilitat prioritària Features redundants/correlacionades entre si

No competeixen: sovint se seleccionen primer les features amb sentit i es comprimeix després la redundància restant.

Errors Comuns i Consells

  • PCA sense estandarditzar. La feature de major variància (per unitats) segresta PC1 i la reducció és un miratge. StandardScaler primer, sempre — llevat del cas rar de features ja en unitats comparables per naturalesa.
  • Quedar-se amb 2 components perquè l'scatter és bonic. Dos PCs són per visualitzar; per modelar, decideix amb la variància acumulada o l'scree plot. Visualització i compressió són usos diferents amb criteris diferents.
  • Interpretar el signe absolut d'un component. Reexecuta en una altra màquina i PC1 pot sortir amb tots els signes invertits: és el mateix eix. Interpreta pesos relatius.
  • Sobrellegir l'scatter 2D. Que dos segments es toquin al pla no prova que es toquin a l'espai complet: pot faltar justament la dimensió que els separa.
  • Consell: etiqueta sempre els eixos de l'scatter amb el seu % de variància (PC1 (46%)); t'hi obliga a tu i avisa el lector de quanta informació falta al dibuix.

Exercicis

Exercici 1. Sense codi: tens dues features estandarditzades amb correlació 0,95. (a) Quina fracció aproximada de la variància explicarà PC1 i per què? (b) I si la correlació fos 0? (c) Què implica cada cas per comprimir a 1 dimensió? Pista: amb dues variables estandarditzades, la variància explicada per PC1 és $(1+|r|)/2$.

Exercici 2. Aplica PCA a les 7 features de clients de la lliçó (o genera un dataset sintètic correlacionat). Dibuixa l'scree plot i la variància acumulada, i decideix quants components conservaries per a (a) visualitzar i (b) alimentar un K-means mantenint el 90% de la variància. Justifica totes dues respostes.

Exercici 3. Pren els loadings de PC1 de la teva execució de l'exercici 2 i redacta en una frase, en llenguatge de negoci de MercaFresh, què mesura aquest eix. Després calcula la correlació de Pearson (02-03) entre la projecció PC1 de cada client i la seva ratio_inactivitat, i explica el resultat.

Solucions

Exercici 1

(a) Amb $r = 0{,}95$: PC1 explica $(1+0{,}95)/2 = 97{,}5%$. El núvol és una el·lipse gairebé degenerada en una recta; gairebé tota la variació ocorre al llarg de la diagonal. (b) Amb $r = 0$: cada PC explica el 50% — el núvol és circular i no existeix cap direcció privilegiada; PCA no té res a comprimir. (c) En el primer cas, reduir a 1D perd un 2,5% d'informació: compressió excel·lent. En el segon, en perd la meitat: inacceptable. Moralitat: PCA comprimeix redundància; sense correlacions no hi ha compressió possible — per això el heatmap de 02-03 és un bon diagnòstic previ de si PCA valdrà la pena.

Exercici 2

pca = PCA().fit(X_esc)
var = pca.explained_variance_ratio_
plt.subplot(1, 2, 1); plt.plot(range(1, len(var)+1), var, "o-")
plt.xlabel("PC"); plt.ylabel("Variància explicada")
plt.subplot(1, 2, 2); plt.plot(range(1, len(var)+1), np.cumsum(var), "o-")
plt.axhline(0.90, ls="--", c="gray")
plt.xlabel("PCs acumulats"); plt.ylabel("Variància acumulada")
plt.show()

(a) Per visualitzar: 2 components, obligatòriament — un scatter té dos eixos; la pregunta rellevant és quanta variància acumulen (aquí ~73%: acceptable, amb la cautela de la lliçó). (b) Per a K-means: on l'acumulada creui 0,90 — típicament 4 components en aquest dataset. PCA(n_components=0.90) ho automatitza. Nota que les respostes difereixen: el criteri depèn de l'ús.

Exercici 3

Frase tipus: "PC1 mesura el grau d'apagament del client: valors alts = molt de temps sense comprar i alta inactivitat relativa; valors baixos = client freqüent i voluminós". La correlació entre PC1 i ratio_inactivitat surt fortament positiva (al voltant de +0,8/+0,9): és coherent, perquè ratio_inactivitat té un dels majors loadings positius de PC1, i la projecció de cada client sobre l'eix hereta aquesta relació. Comprovar els loadings contra correlacions simples és una manera ràpida de validar la teva lectura de l'eix.

Conclusió

Has afegit a l'arsenal l'eina que domestica la dimensionalitat: PCA gira els eixos cap a les direccions de màxima variància, converteix features correlacionades en components independents i ordenats per importància, i et deixa triar quants conservar-ne amb la variància explicada i l'scree plot. Saps per què exigeix estandarditzar (hereta les unitats via la covariància de 02-03), saps llegir loadings per donar nom de negoci a cada eix, i has vist els seus dos oficis a MercaFresh: mapa 2D dels segments de K-means i compressor previ al modelatge — sense confondre'l mai amb la selecció de features de 03-06, perquè PCA no tria columnes: les barreja.

Però PCA arrossega el seu límit de fàbrica: és una rotació, i les rotacions són lineals. A la lliçó següent coneixeràs un algorisme que no necessita que els grups siguin esferes ni que l'estructura sigui recta: DBSCAN agrupa per densitat, troba clústers amb qualsevol forma i —el que més interessa a MercaFresh— assenyala explícitament els punts que no encaixen enlloc: les comandes anòmales.

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