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
- La maledicció de la dimensionalitat
- Intuïció geomètrica: girar els eixos cap a la màxima variància
- Components principals, variància explicada i scree plot
- La connexió amb la covariància (02-03) i per què estandarditzar abans (03-05)
- PCA amb scikit-learn sobre els clients MercaFresh
- Visualització 2D dels segments de K-means
- Interpretar components: els loadings
- PCA com a pas previ a models
- 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_transformprojecta cada client sobre els eixos nous:X_pcaté 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) oPCA(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.
StandardScalerprimer, 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
- Què és el Machine Learning?
- Història i evolució del Machine Learning
- Tipus de Machine Learning
- Aplicacions del Machine Learning
- El flux de treball d'un projecte de Machine Learning
Mòdul 2: Fonaments d'Estadística i Probabilitat
- Conceptes bàsics d'estadística
- Distribucions de probabilitat
- Correlació i covariància
- Inferència estadística
- Teorema de Bayes
Mòdul 3: Preprocessament de Dades
- Neteja de dades
- Gestió de dades mancants
- Transformació de dades
- Codificació de variables categòriques
- Normalització i estandardització
- Enginyeria de característiques
Mòdul 4: Algorismes de Machine Learning Supervisat
- Regressió lineal
- Regressió logística
- Arbres de decisió
- Màquines de suport vectorial (SVM)
- K veïns més propers (K-NN)
- Naive Bayes
- Xarxes neuronals
Mòdul 5: Algorismes de Machine Learning No Supervisat
- Clustering: K-means
- Clustering jeràrquic
- Anàlisi de components principals (PCA)
- Anàlisi d'agrupament DBSCAN
- Visualització de dades amb t-SNE i UMAP
Mòdul 6: Avaluació i Validació de Models
- Divisió de dades: entrenament, validació i prova
- Mètriques d'avaluació
- Validació creuada
- Corba ROC i AUC
- Overfitting i underfitting
Mòdul 7: Tècniques Avançades i Optimització
- Regularització: Ridge, Lasso i Elastic Net
- Ensemble Learning
- Gradient Boosting
- Xarxes neuronals profundes (Deep Learning)
- Optimització d'hiperparàmetres
Mòdul 8: Implementació i Desplegament de Models
- Frameworks i biblioteques populars
- Implementació de models en producció
- Manteniment i monitoratge de models
- Consideracions ètiques i de privadesa
Mòdul 9: Projectes Pràctics
- Projecte 1: Predicció de preus d'habitatges
- Projecte 2: Classificació d'imatges
- Projecte 3: Anàlisi de sentiments a les xarxes socials
- Projecte 4: Detecció de fraus
- Projecte 5: Segmentació de clients
