Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Aprenentatge No Supervisat

Imagina que tens milions de clients però cap etiqueta que et digui qui són. O que gestiones una fàbrica i vols detectar peces defectuoses sense haver vist mai abans cap defecte. O que vols visualitzar dades amb 50 variables en un simple gràfic 2D.

L’aprenentatge no supervisat resol aquests problemes: descobreix patrons en dades sense necessitat d’etiquetes prèvies. Mentre que l’aprenentatge supervisat aprèn d’exemples etiquetats (spam/no spam, gat/gos), l’aprenentatge no supervisat explora les dades per trobar estructures ocultes pel seu compte.

Tipologia

L’aprenentatge no supervisat treballa amb dades sense etiquetes, buscant patrons o estructures ocultes en les dades.

Aquests són alguns tipus d’aprenentatge no supervisat:

  • Clustering (Agrupació)

    • Objectiu: Agrupar dades en dos o més grups segons similituds
    • Exemple: Segmentar clients segons el seu comportament de compra
  • Detecció d’anomalies

    • Objectiu: Identificar esdeveniments o transaccions inusuals
    • Exemple: Detectar frau en transaccions bancàries
  • Reducció de dimensionalitat

    • Objectiu: Comprimir dades utilitzant menys variables
    • Exemple: Reduir la complexitat d’imatges mantenint la informació essencial

Agrupament (clustering)

Un algorisme d’agrupament analitza un conjunt de punts de dades i troba automàticament aquells que són semblants o relacionats entre si.

Vegem què significa això, tot contrastant l’agrupament —que és un mètode d’aprenentatge no supervisat— amb l’aprenentatge supervisat que ja havíem vist en la classificació binària.

Supervisat vs. No supervisat

Imaginem un conjunt de dades amb dues característiques, x1 i x2.

  • Aprenentatge supervisat: Disposem d’un conjunt d’entrenament amb les entrades x i les etiquetes corresponents y. Podem representar aquestes dades i ajustar-hi, per exemple, una regressió logística o una xarxa neuronal que aprengui una frontera de decisió entre les classes.

    En aquest cas, el conjunt de dades conté (x,y):

    −4−20246811.522.533.544.5
    Classe 1Classe 2Frontera de decisióAprenentatge supervisat: classes i frontera de decisióx₁x₂
  • Aprenentatge no supervisat:
    Només tenim les entrades x, però no les etiquetes y.

    Quan representem el conjunt de dades, només veiem punts (●), sense colors ni símbols que ens indiquin quina classe correspon a cada punt.

    Com que no tenim les etiquetes y, no podem dir a l’algorisme quina és la resposta correcta. En comptes d’això, demanem a l’algorisme que trobi estructura interessant en les dades.

    L’algorisme pot identificar grups de punts similars i calcular el seu centroide: el punt central que representa la posició mitjana de tots els punts d’un grup.

22.533.5422.533.54
Clúster 1Clúster 2Centroid 1Centroid 2Exemple d’agrupament no supervisatx₁x₂

Agrupament: trobar estructura

El primer algorisme d’aprenentatge no supervisat que s’acostuma a estudiar és l’agrupament (clustering).
Aquest mètode busca si el conjunt de dades pot ser dividit en grups (clústers) de punts que siguin semblants entre si.

Per exemple, un algorisme d’agrupament podria descobrir que les dades provenen de dos clústers diferenciats.

Aplicacions de l’agrupament

L’agrupament és àmpliament utilitzat en camps molt diversos:

  • Processament de textos i notícies:
    Agrupar articles similars per temàtica (p. ex. notícies sobre pandes o sobre mercats financers).

  • Segmentació de mercat:
    Classificar els usuaris en grups segons objectius comuns: millorar competències, desenvolupar carrera professional, o estar al dia en IA.

  • Biologia i genètica:
    Analitzar dades d’expressió genètica i agrupar persones amb trets similars.

  • Astronomia:
    Agrupar cossos celestes per identificar galàxies o estructures coherents a l’espai.

En definitiva, l’agrupament ajuda a descobrir patrons ocults en dades sense necessitat de tenir les etiquetes.

Agrupació amb K-means

K-means és el mètode d’agrupament molt utilitzat. Explorarem com funciona i per què és tan comú en aplicacions pràctiques.

Suposem que tenim un conjunt de dades amb 30 exemples d’entrenament no etiquetats (30 punts en un gràfic). El que volem fer és executar K-means sobre aquest conjunt de dades.

El primer que fa K-means és escollir aleatòriament la posició inicial dels centroides dels clústers.

En aquest exemple demanarem a l’algorisme que trobi dos clústers.
Per tant, inicialment col·loca dues creus (una vermella i una blava) en posicions qualsevol.

Aquestes primeres posicions són només suposicions inicials i no tenen per què ser bones. Però serveixen com a punt de partida.

Una idea fonamental és que K-means repeteix dues operacions fins a convergir:

  1. Assignació de punts als centroides

    Per a cada punt del conjunt de dades, l’algorisme comprova si està més a prop del centroide vermell o del centroide blau i l’assigna al clúster corresponent.

  2. Actualització dels centroides

    Un cop cada punt està assignat a un clúster, K-means calcula la mitjana de les posicions dels punts de cada clúster:

    • El centroide vermell es mou a la posició mitjana de tots els punts vermells.
    • El centroide blau es mou a la posició mitjana de tots els punts blaus.

    D’aquesta manera, els centroides es recol·loquen en posicions més representatives.

Aquest procés es repeteix fins que els punts ja no canvien de clúster i els centroides deixen de moure’s. Quan això passa, diem que K-means ha convergit.

Algorisme K-means

L’algorisme K-means es pot resumir així:

  1. Inicialització: Col·locar aleatòriament K centroides (μ1,μ2,,μK). Cada centroide té la mateixa dimensió que les dades.

  2. Repetir fins a convergència:

    • Assignació: Cada punt s’assigna al centroide més proper (usant distància euclidiana).
    • Actualització: Cada centroide es mou a la mitjana dels punts que té assignats.

Exemple numèric pas a pas

Dades: 4 punts en 2D amb K=2 clústers: A=(1,1), B=(2,1), C=(4,3), D=(5,4).

Inicialització: Escollim aleatòriament μ1=(1,1) i μ2=(2,1) com a centroides inicials.

Iteració 1:

Assignació — Calculem la distància euclidiana de cada punt als dos centroides:

PuntDist. a μ1Dist. a μ2Assignació
A(1,1)01Clúster 1
B(2,1)10Clúster 2
C(4,3)3.62.8Clúster 2
D(5,4)5.04.2Clúster 2

Actualització — Recalculem els centroides com la mitjana dels punts assignats:

  • μ1=A=(1,1)
  • μ2=B+C+D3=(2,1)+(4,3)+(5,4)3=(3.67,2.67)

Iteració 2:

Assignació — Amb els nous centroides μ1=(1,1) i μ2=(3.67,2.67):

PuntDist. a μ1Dist. a μ2Assignació
A(1,1)03.1Clúster 1
B(2,1)12.4Clúster 1
C(4,3)3.60.5Clúster 2
D(5,4)5.01.9Clúster 2

Actualització — Recalculem els centroides:

  • μ1=A+B2=(1,1)+(2,1)2=(1.5,1)
  • μ2=C+D2=(4,3)+(5,4)2=(4.5,3.5)

Convergència: Si executem una tercera iteració, els punts no canvien de clúster. L’algorisme ha convergit amb resultat: A,B i C,D.

Casos especials

Si un cluster no té cap punt assignat, la mitjana no està definida.
Les opcions habituals són:

  1. Eliminar el cluster i treballar amb K1 clusters.
  2. Reinicialitzar aleatòriament el centroide i esperar que rebi punts en la següent iteració.

Aplicació pràctica

K-means s’aplica sovint a dades que no estan clarament separades.
Exemple: disseny de samarretes petites, mitjanes i grans segons alçada i pes dels clients.

  • Els punts poden variar contínuament sense clústers evidents.
  • K-means amb K = 3 pot agrupar els punts en tres clústers representatius.
  • Els centroides resultants indiquen les mesures més representatives per a cada talla.

K-means intenta optimitzar una funció de cost específica, i aquesta és la raó per la qual convergeix després de diverses iteracions.

Funció de Cost

K-means optimitza una funció de cost anomenada funció de distorsió:

J=1mmi=1|xiμCi|2

Aquesta fórmula mesura la mitjana de la distància al quadrat entre cada punt i el centroide del seu clúster. Com més petita sigui J, més compactes són els clústers.

Per què funciona K-means?

  • El pas d’assignació minimitza J respecte a les assignacions (cada punt va al centroide més proper).
  • El pas d’actualització minimitza J respecte a les posicions dels centroides (la mitjana minimitza la suma de distàncies al quadrat).

Com que cada pas redueix o manté J, l’algoritme sempre convergeix.

Inicialització i mínims locals

Inicialització de centroides

El primer pas de K-means és escollir ubicacions inicials μ1,,μK.
La manera més comuna és seleccionar aleatòriament (K) exemples del training set.

Important: Km, on m és el nombre d’exemples.

Problema de mínims locals

Diferents inicialitzacions poden produir clústers molt diferents, atrapats en mínims locals de la funció de cost J. La solució és executar múltiples inicialitzacions:

  1. Repetir K-means N vegades amb inicialitzacions aleatòries.
  2. Calcular la funció de cost J per cada execució.
  3. Seleccionar els centroides amb el menor cost.

Normalment N[50,1000]. Això millora l’agrupament i minimitza la distorsió.

Resumint:

  • Escollir centroides inicials és crucial.
  • Múltiples inicialitzacions redueixen el risc de mínims locals.
  • Escollir el conjunt amb menor distorsió ((J)) dona un millor resultat final.

Selecció de K

L’algorisme K-means requereix com a entrada un paràmetre K, el nombre de clusters que volem identificar. Decidir el valor correcte de K és sovint ambigu, ja que diferents observadors poden interpretar les mateixes dades de manera diferent.

Mètode del colze

Una tècnica habitual és el mètode del colze:

  1. Executar K-means amb diversos valors de K (per exemple, de 1 a 10).
  2. Plotar la inèrcia J (eix Y) en funció de K (eix X).

A mesura que K augmenta, J disminueix (més centroides → punts més a prop del seu centroide). El colze és el punt on la corba deixa de baixar ràpidament i s’aplana. Minimitzar J directament no funciona, ja que J disminueix amb més clusters.

Selecció pràctica de K

La millor manera de triar K és segons l’ús final dels clusters.

Exemples:

  • Talles de samarretes: K=3 → S, M, L; K=5 → XS, S, M, L, XL. La decisió depèn del trade-off entre ajust i costos de producció.
  • Compressió d’imatges: K determina qualitat vs espai ocupat.

Resumint:

  • Escollir K depèn del propòsit i no sempre té una resposta única.
  • El mètode del colze és útil però no infal·lible.
  • Comparar diferents K segons la utilitat dels clusters és la millor estratègia.

Implementació amb scikit-learn

from sklearn.cluster import KMeans # Entrenar el model kmeans = KMeans(n_clusters=3, random_state=42, n_init=10) kmeans.fit(X) # Resultats labels = kmeans.labels_ # Assignació de cada punt centers = kmeans.cluster_centers_ # Posició dels centroides inertia = kmeans.inertia_ # Valor de J (funció de cost), també anomenat "inèrcia" # Predir clúster per a noves dades new_labels = kmeans.predict(X_new)

Per què “inèrcia”? El terme prové de la física: el moment d’inèrcia mesura com la massa es distribueix al voltant d’un eix de rotació. De manera anàloga, la inèrcia de K-means mesura com els punts es distribueixen al voltant dels seus centroides. Com més compactes són els clústers, menor és la inèrcia.

Paràmetres principals:

  • n_clusters: El nombre de clústers K que volem trobar.
  • n_init: Nombre d’inicialitzacions aleatòries. L’algorisme s’executa n_init vegades amb diferents centroides inicials i retorna el millor resultat (el que té menor J). Valors típics: 10-100 per problemes petits, fins a 1000 per problemes crítics.
  • random_state: Llavor per reproduïbilitat dels resultats.

Resum K-means: Agrupa dades en K clústers basant-se en distàncies. Itera entre assignar punts i moure centroides fins convergir. Executa múltiples vegades amb inicialitzacions diferents. Utilitza el mètode del colze o el context del problema per escollir K.

Detecció d’anomalies (Anomaly Detection)

La detecció d’anomalies és una tècnica d’aprenentatge automàtic no supervisat que permet identificar observacions que difereixen significativament del comportament normal esperat. A diferència dels algoritmes supervisats, no necessitem grans quantitats d’exemples anòmals etiquetats per entrenar el model.

Per què és important?

En moltes aplicacions del món real, les anomalies són rares però crítiques:

  • Fabricació de motors d’avió: Un motor defectuós pot tenir conseqüències catastròfiques. Necessitem detectar qualsevol comportament anòmal abans que l’avió voli.
  • Detecció de frau financer: Les transaccions fraudulentes són poc freqüents (menys del 0.1% en targetes de crèdit), però cada frau no detectat representa pèrdues econòmiques.
  • Monitoratge de servidors: Un servidor compromès o amb una fallada pot mostrar patrons de comportament inusuals en memòria, CPU o xarxa.

En tots aquests casos, tenim moltes dades de funcionament normal, però molt poques (o cap) mostra d’anomalies. Això fa que els mètodes tradicionals supervisats no siguin aplicables.

Aplicacions habituals

ÀmbitCaracterístiques analitzadesObjectiu
Frau financerImport, ubicació, freqüència, hora, tipus de producteDetectar transaccions sospitoses
FabricacióTemperatura, vibracions, pressió, toleràncies dimensionalsIdentificar unitats defectuoses
CiberseguretatTràfic de xarxa, inicis de sessió, accés a fitxersDetectar intrusions o comportaments maliciosos
SalutConstants vitals, patrons d’activitat, valors analítiquesAlertar de situacions d’emergència

Isolation Forest

Isolation Forest és l’algoritme més utilitzat actualment per a detecció d’anomalies en aplicacions reals. La seva idea central és molt intuïtiva: les anomalies són més fàcils d’aïllar que les observacions normals.

Imaginem que tenim un conjunt de punts en un espai 2D. La majoria estan agrupats en una regió densa, però alguns punts estan molt allunyats d’aquest cluster principal.

Si volem “aïllar” un punt normal (dins del cluster), necessitarem fer moltes divisions per separar-lo de la resta. En canvi, si volem aïllar un punt anòmal (lluny del cluster), amb poques divisions ja l’haurem separat completament.

Aquesta és exactament la lògica que utilitza Isolation Forest:

  1. Construeix múltiples arbres de decisió aleatoris
  2. Cada arbre intenta aïllar punts mitjançant divisions aleatòries
  3. Mesura la longitud del camí necessària per aïllar cada punt
  4. Camins curts → probable anomalia
  5. Camins llargs → probable observació normal

Com funciona l’algoritme

Isolation Forest crea un “bosc” d’arbres d’aïllament. Cada arbre es construeix així:

  1. Selecciona aleatòriament una característica xj del conjunt de dades
  2. Selecciona aleatòriament un valor de tall entre el mínim i el màxim de xj
  3. Divideix les dades en dos grups segons aquest tall
  4. Repeteix recursivament per a cada subgrup fins que cada punt quedi aïllat

Exemple visual (arbre simplified):

[200 punts] | x1 < 5.2? (tall aleatori) / \ [180 punts] [20 punts] ← Grup petit (sospitós!) | | x2 < 3.1? x2 < 8.5? / \ / \ [120] [60] [18] [2] ← Aïllat ràpidament! | | | | ... ... ... ANOMALIA

Un punt anòmal queda aïllat amb menys divisions (camí curt a l’arbre). Un punt normal requereix més divisions (camí llarg).

Implementació amb scikit-learn

from sklearn.ensemble import IsolationForest import numpy as np # Generar dades sintètiques per demostració np.random.seed(42) X_normal = np.random.randn(200, 2) # 200 punts normals X_anomalies = np.random.uniform(low=-4, high=4, size=(10, 2)) # 10 anomalies X = np.vstack([X_normal, X_anomalies]) # Entrenar Isolation Forest clf = IsolationForest( contamination=0.05, # Esperem ~5% d'anomalies random_state=42, n_estimators=100 # Nombre d'arbres al bosc ) clf.fit(X) # Predir: 1 = normal, -1 = anomalia predictions = clf.predict(X) anomalies = X[predictions == -1] print(f"Anomalies detectades: {len(anomalies)}")

El paràmetre de contaminació

El paràmetre més important d’Isolation Forest és contamination, que indica la proporció esperada d’anomalies al conjunt de dades.

  • Valor per defecte: 0.1 (10%)
  • Valor típic: Entre 0.01 i 0.1, depenent del problema
  • Com ajustar-lo: Utilitzar un conjunt de validació amb algunes anomalies etiquetades (veure Avaluació i divisió de dades)

Trade-off important:

  • Contamination massa alt → Molts falsos positius (etiquetem normals com anòmals)
  • Contamination massa baix → Molts falsos negatius (perdem anomalies reals)

Scores d’anomalia

A més de les prediccions binàries (-1 o 1), Isolation Forest proporciona un score continu per cada observació:

# Obtenir scores d'anomalia scores = clf.decision_function(X) # Valors més negatius = més anòmals # Valors més positius = més normals # Ordenar per score per veure els casos més sospitosos import pandas as pd df_scores = pd.DataFrame({ 'score': scores, 'prediction': predictions }) df_sorted = df_scores.sort_values('score') print(df_sorted.head(10)) # 10 casos més anòmals

Aquest score és útil per:

  • Prioritzar casos per revisió manual
  • Establir llindars personalitzats segons el context de negoci
  • Visualitzar la distribució d’anomalies detectades

Avantatges i limitacions

AvantatgesLimitacions
No assumeix cap distribució específica de les dadesCal ajustar el paràmetre contamination
Funciona bé en alta dimensionalitat (moltes features)Pot tenir problemes si hi ha múltiples clusters normals
Computacionalment eficient fins i tot amb grans datasetsNo proporciona probabilitats explícites com models generatius
No requereix normalització de dadesSensible a característiques irrellevants (cal feature engineering)

Avaluació i divisió de dades

Un dels aspectes més delicats de la detecció d’anomalies és com avaluar el model. Tot i que és una tècnica no supervisada, és molt útil disposar d’algunes anomalies etiquetades per poder mesurar el rendiment.

La divisió de dades en detecció d’anomalies és diferent de l’aprenentatge supervisat clàssic:

Regla clau: El conjunt d’entrenament ha de contenir només exemples normals (o una proporció molt alta de normals). Si s’escapa alguna anomalia al conjunt d’entrenament, normalment no passa res. L’algoritme és robust a una petita contaminació.

Però quantes normals usar per entrenar? Això depèn del context. Hi ha dues estratègies principals:

Estratègia 1: Split 60/20/20 (ajust d’hiperparàmetres)

Quan usar-la:

  • Necessites ajustar el paràmetre contamination experimentalment
  • Tens un nombre limitat d’exemples normals (milers, no centenars de milers)
  • Vols seguir les millors pràctiques de ML supervisat (separar train/val/test)
  • Pots permetre’t “perdre” dades d’entrenament per tenir validació

Exemple pràctic amb motors d’avió:

Suposem que una fàbrica ha recollit dades de 10.000 motors durant anys:

  • 10.000 motors normals (funcionen correctament)
  • 20 motors defectuosos (anomalies detectades posteriorment)

Divisió recomanada:

Entrenament: 6.000 motors normals (60%, només y=0) Validació: 2.000 motors normals + 10 defectuosos (20% + 50% anomalies) Test: 2.000 motors normals + 10 defectuosos (20% + 50% anomalies)

Si tenim molt poques anomalies (menys de 20), podem prescindir del conjunt de test:

Entrenament: 6.000 motors normals Validació: 4.000 motors normals + 20 defectuosos

Implementació de la divisió 60/20/20:

import numpy as np # Assumim que tenim 'X' (característiques) i 'y' (0=normal, 1=anomalia) # Separar normals i anomalies normal_indices = np.where(y == 0)[0] anomaly_indices = np.where(y == 1)[0] # Entrenament: 60% dels normals n_train = int(0.6 * len(normal_indices)) train_idx = normal_indices[:n_train] X_train = X[train_idx] # Validació: 20% normals + 50% anomalies val_normal_idx = normal_indices[n_train:n_train + int(0.2*len(normal_indices))] val_anomaly_idx = anomaly_indices[:len(anomaly_indices)//2] val_idx = np.concatenate([val_normal_idx, val_anomaly_idx]) X_val = X[val_idx] y_val = y[val_idx] # Test: Resta de dades test_normal_idx = normal_indices[n_train + int(0.2*len(normal_indices)):] test_anomaly_idx = anomaly_indices[len(anomaly_indices)//2:] test_idx = np.concatenate([test_normal_idx, test_anomaly_idx]) X_test = X[test_idx] y_test = y[test_idx] print(f"Train: {len(X_train)} normals") print(f"Val: {len(X_val)} total ({sum(y_val==1)} anomalies)") print(f"Test: {len(X_test)} total ({sum(y_test==1)} anomalies)")

Ajust del paràmetre contamination amb validació:

from sklearn.metrics import f1_score resultats = [] for c in [0.01, 0.02, 0.05, 0.1, 0.15]: clf = IsolationForest(contamination=c, random_state=42) clf.fit(X_train) # Només normals! y_pred = clf.predict(X_val) y_pred_binary = (y_pred == -1).astype(int) f1 = f1_score(y_val, y_pred_binary) resultats.append({'contamination': c, 'f1_score': f1}) print(f"Contaminació={c:.2f}, F1-score={f1:.3f}") # Seleccionar el valor amb millor F1-score best_c = max(resultats, key=lambda x: x['f1_score'])['contamination'] print(f"\nMillor contamination: {best_c}")

Estratègia 2: Usar TOTES les normals (producció)

Quan usar-la:

  • Tens moltes dades normals (centenars de milers o milions)
  • Les anomalies són molt rares (< 0.5% del total)
  • El paràmetre contamination es pot fixar segons coneixement del domini
  • Vols maximitzar l’aprenentatge del comportament normal
  • No necessites ajustar hiperparàmetres experimentalment

Exemple pràctic: Detecció de frau bancari:

  • 284.315 transaccions normals (abundants!)
  • 492 transaccions fraudulentes (0.173%, molt rares)
  • El contamination es fixa a 0.002 segons estadístiques del sector

Divisió recomanada:

Entrenament: 284.315 normals (100% de normals disponibles) Test: 284.807 total (totes les dades, incloent 492 fraus)

Per què usar TOTES les normals?

  1. Dades normals abundants: No cal “estalviar-ne” per validació
  2. Anomalies precioses: Amb només 492 fraus, dividir-les redueix el poder estadístic del test
  3. Contamination fix: El sector bancari sap que ~0.2% de transaccions són frau
  4. Maximitza aprenentatge: Més exemples normals → millor model del “comportament normal”

Implementació 100%/100%:

import numpy as np # Separar normals i anomalies normal_indices = np.where(y == 0)[0] X_train = X[normal_indices] # TOTES les normals # Test: totes les dades (manté desbalanceig natural) X_test = X y_test = y print(f"Train: {len(X_train)} normals (100%)") print(f"Test: {len(X_test)} total ({sum(y_test==1)} anomalies, {100*sum(y_test==1)/len(y_test):.3f}%)") # Entrenar amb totes les normals clf = IsolationForest(contamination=0.002, random_state=42, n_estimators=100) clf.fit(X_train) # Avaluar directament sobre totes les dades y_pred = clf.predict(X_test) y_pred_binary = (y_pred == -1).astype(int) from sklearn.metrics import precision_score, recall_score, f1_score precision = precision_score(y_test, y_pred_binary, zero_division=0) recall = recall_score(y_test, y_pred_binary) f1 = f1_score(y_test, y_pred_binary) print(f"\nResultats:") print(f" Precision: {precision:.3f}") print(f" Recall: {recall:.3f}") print(f" F1-Score: {f1:.3f}")

Taula comparativa

Criteri60/20/20 Split100% Normals
Dades normalsMilersCentenars de milers+
AnomaliesDesenesCentenars (però % baix)
ContaminationAjustat amb validacióFix (coneixement domini)
Cas d’úsDataset petit, tuning necessariProducció fraud/defectes
Exemple10K motors, 20 defectuosos284K transaccions, 492 fraus
ValidacióConjunt explícitDirectament al test

Mètriques d’avaluació

En detecció d’anomalies, la classe positiva (anomalia) és molt minoritària. Per això, la accuracy NO és una bona mètrica. Utilitzem precision, recall i F1-score (veure ml_metrics.md per més detalls).

En funció del context, prioritzarem diferents mètriques:

  • Detecció de frau bancari: Preferim alta recall (detectar tots els fraus), acceptant alguns falsos positius que es poden revisar manualment.
  • Alertes mèdiques crítiques: Necessitem alta recall (no podem perdre cap cas greu), encara que generi falses alarmes.
  • Control de qualitat manufacturera: Equilibri entre precision i recall per no descartar massa productes bons.

Detecció d’anomalies vs aprenentatge supervisat

Quan disposem d’algunes anomalies etiquetades, sorgeix una pregunta natural: per què no utilitzar aprenentatge supervisat en lloc de detecció d’anomalies?

La resposta depèn de diversos factors. Vegem-ne les diferències clau:

Taula comparativa

CriteriDetecció d’anomaliesAprenentatge supervisat
Exemples positiusMolt pocs (0-50)Molts (centenars o milers)
Tipus d’anomaliesNoves i variadesConegudes i repetitives
Què aprènCom és el “normal”Com són positius i negatius
Futurs positiusPoden ser molt diferentsSimilars als entrenats
AssumpcionsAnomalies futures seran “estranyes”Patrons coneguts es repetiran

Quan usar detecció d’anomalies

Usa anomaly detection quan:

  1. Tens menys de 50 exemples d’anomalies
  2. Les anomalies futures poden ser de tipus nous (diferents de les observades)
  3. El cost de no detectar una anomalia nova és molt alt
  4. Les anomalies són diverses i canvien amb el temps

Exemples:

  • Frau financer: Els defraudadors constantment inventen noves tècniques. Un frau detectat avui pot ser molt diferent dels fraus del mes passat.
  • Ciberseguretat: Els atacs informàtics evolucionen. Un sistema supervisat només detectaria atacs coneguts, mentre que anomaly detection pot alertar de patrons nous i sospitosos.
  • Detecció de defectes nous: En una línia de producció, poden aparèixer tipus de defectes mai vistos abans a causa de nous materials, màquines o processos.

📘 Per a més detalls, consulta l’apèndix: quan usar aprenentatge supervisat i enginyeria de característiques.

Anàlisi de components principals

PCA (Principal Components Analysis) és un algoritme d’aprenentatge no supervisat que s’utilitza sovint per a la visualització i reducció de la dimensionalitat de dades. Si teniu un conjunt de dades amb moltes característiques —per exemple 10, 50 o fins i tot milers—, no és possible representar-lo directament en un gràfic.

El PCA busca noves característiques (anomenades components principals) que capturen la màxima variabilitat de les dades i redueixen el nombre de dimensions a dues o tres, fent possible la seva visualització i una millor comprensió.

Com es construeixen els components? Cada component principal és una combinació lineal de les característiques originals:

z1=w11x1+w12x2++w1nxn

Els pesos w es calculen de manera que z1 capturi la màxima variància possible, z2 la màxima variància restant (i sigui ortogonal a z1), i així successivament. A més, es restringeix que la norma dels pesos sigui 1 (w211+w212+=1): sense aquesta restricció, podríem augmentar la variància indefinidament simplement escalant els pesos. Amb norma 1, PCA busca una direcció en l’espai de característiques, no una magnitud.

Això significa que les noves característiques no són cap de les originals, sinó mescles de totes elles, cosa que pot fer-les difícils d’interpretar.

La maledicció de la dimensionalitat

Una motivació important per usar PCA és evitar la maledicció de la dimensionalitat (curse of dimensionality).

Imagina que vols trobar el veí més proper d’un punt. En 2D, els punts estan relativament a prop i és fàcil identificar quins són similars. Però si afegeixes més dimensions, l’espai creix exponencialment: passa d’una línia a un quadrat, després a un cub, i així successivament. En aquest espai immens, les dades es tornen tan disperses que tots els punts acaben “igual de lluny” entre si. Algoritmes com K-NN o K-means, que depenen de distàncies, deixen de funcionar bé.

A més, per cobrir adequadament un espai amb moltes dimensions necessitem exponencialment més dades. I si no en tenim prou, els models troben patrons espuris que no generalitzen (sobreajust).

PCA ajuda comprimint les dades en un espai més petit i manejable, on les distàncies tornen a ser significatives.

Exemple senzill: cotxes

Suposem que tenim un conjunt de dades de cotxes de passatgers, amb moltes característiques: longitud, amplada, diàmetre de les rodes, alçada, etc.
Si volem reduir el nombre de característiques per a visualització, podem aplicar PCA.

Exemple 1: dues característiques

Suposem que tenim només dues característiques:

  • x1 = longitud del cotxe
  • x2 = amplada del cotxe

A la majoria de països, l’amplada dels cotxes varia poc perquè han de cabre a les carreteres de carril únic. Per exemple, als Estats Units, la majoria de cotxes tenen aproximadament 1,8 m d’amplada.

Si representem gràficament la longitud i l’amplada dels cotxes, trobarem que:

  • x1 varia molt (hi ha cotxes curts i llargs)
  • x2 varia poc

En aquest cas, el PCA automàticament decidiria prioritzar x1, ja que conté la major part de la informació rellevant.

Exemple 2: longitud i diàmetre de rodes

Ara x1 és la longitud del cotxe i x2 és el diàmetre de les rodes.
Encara que x2 variï una mica, PCA probablement decidirà que x1 és suficient per representar la variació principal.

Exemple 3: longitud i alçada

Ara x1 = longitud i x2 = alçada del cotxe.
Ambdues característiques varien força i contenen informació útil.

En lloc de triar només x1 o només x2, PCA crea un nou eix combinat, que anomenarem z.
Aquest eix z és una combinació lineal de x1 i x2 que captura la major part de la variació de les dades:

z=w1x1+w2x2

La coordenada d’un cotxe sobre l’eix z resumeix aproximadament la “grandària total” del cotxe, sense perdre informació rellevant.

Exemple amb més dimensions

Suposem que tenim un conjunt de dades tridimensional amb x1,x2,x3.
Encara que les dades estiguin en 3D, sovint viuen sobre una superfície gairebé bidimensional.
PCA permet reduir de 3 característiques a 2 noves coordenades z1,z2 per a visualitzar les dades en un gràfic 2D.

Exemple amb països

Si tenim dades de molts països amb característiques com:

  • x1 = PIB total
  • x2 = PIB per càpita
  • x3 = Índex de Desenvolupament Humà
  • …fins a 50 característiques

No podem representar-ho directament en un gràfic.
PCA redueix aquestes 50 característiques a dues o tres:

Z1,Z2=PCA(X1,X2,,X50)

Per exemple:

  • Z1 podria correspondre aproximadament a la grandària del país o PIB total
  • Z2 podria correspondre a la riqueza per persona

Això permet visualitzar països grans i petits, amb PIB alt o baix, en un gràfic 2D fàcil d’interpretar.

PCA amb scikit-learn

from sklearn.decomposition import PCA from sklearn.preprocessing import StandardScaler # Normalitzar dades (important per PCA!) scaler = StandardScaler() X_scaled = scaler.fit_transform(X) # Reduir a 2 dimensions pca = PCA(n_components=2) X_reduced = pca.fit_transform(X_scaled) # Variància explicada per cada component print(pca.explained_variance_ratio_) # Ex: [0.72, 0.15] # Això vol dir: PC1 captura 72%, PC2 captura 15% de la variància

Selecció del nombre de components

Un dels aspectes clau de PCA és decidir quants components conservar. Menys components significa un model més simple, però també implica perdre informació. La clau per prendre aquesta decisió és la variància explicada.

Variància explicada (explained variance ratio)

Cada component principal captura una part de la variabilitat total de les dades. L’atribut explained_variance_ratio_ retorna un array on cada valor indica la proporció de variància capturada per aquell component:

  • Els valors estan ordenats de major a menor (PC1 sempre captura més que PC2)
  • La suma de tots els valors és 1.0 (100% de la variància)

Exemple:

explained_variance_ratio_ = [0.72, 0.15, 0.08, 0.03, 0.02] → PC1 sol: 72% de la informació → PC1 + PC2: 87% de la informació → PC1 + PC2 + PC3: 95% de la informació

Si amb 2 components ja capturem el 87% de la variància, les altres 48 característiques originals eren probablement redundants o molt correlacionades entre si.

Variància retinguda

Quan reduïm de n característiques a k components, “perdem” part de la informació. La variància retinguda és la suma acumulada dels primers k valors de explained_variance_ratio_, i és la mètrica clau per decidir quants components conservar.

Per què descartem les direccions amb poca variància?

La intuïció clau és que variància alta = informació útil. Si una característica (o direcció en l’espai de dades) varia molt poc, aporta poca capacitat per distingir entre observacions:

  • Una característica on tots els valors són gairebé iguals no ajuda a diferenciar res
  • En canvi, una característica amb molta variació permet separar o agrupar les dades

PCA ordena les direccions de més a menys variància. Quan descartem els últims components (els de baixa variància), estem eliminant:

  • Soroll: fluctuacions aleatòries que no aporten informació real
  • Redundància: informació ja capturada pels primers components
  • Detalls irrellevants: variacions mínimes que no afecten l’anàlisi

Per això, descartar components de baixa variància sovint millora els models: eliminem soroll sense perdre el senyal important.

Hi ha un compromís:

  • Més components → més variància retinguda → model més complex
  • Menys components → menys variància retinguda → model més simple però pot perdre patrons importants

Els llindars habituals són 90%, 95% o 99%, depenent de l’aplicació.

Criteris segons el propòsit

PropòsitComponents recomanatsRaonament
Visualització2-3Permet representar les dades en un gràfic 2D o 3D
Compressió90-99% variànciaReté la informació essencial amb menys espai
Preprocessat per MLValidació creuadaTrobar el punt òptim entre retenir senyal i descartar soroll

PCA com a tècnica de regularització:

PCA no només serveix per reduir dimensions o visualitzar. També pot millorar el rendiment d’un model predictiu. Com? Els components de baixa variància sovint contenen més soroll que senyal. En descartar-los:

  • Reduïm el sobreajust (overfitting): el model no aprèn patrons espuris del soroll
  • Millorem la generalització: el model es concentra en les característiques realment informatives
  • Accelerem l’entrenament: menys dimensions significa menys càlcul

En alguns casos, retenir menys del 90% de la variància pot donar millors resultats que usar totes les característiques originals. L’única manera de saber-ho és validar experimentalment amb cross-validation.

Selecció automàtica amb scikit-learn

import numpy as np from sklearn.decomposition import PCA from sklearn.preprocessing import StandardScaler # Normalitzar dades scaler = StandardScaler() X_scaled = scaler.fit_transform(X) # Opció 1: Selecció automàtica per llindar de variància pca = PCA(n_components=0.95) # Retenir 95% de la variància X_reduced = pca.fit_transform(X_scaled) print(f"Components seleccionats: {pca.n_components_}") # Ex: "Components seleccionats: 10" (de 50 originals) # Opció 2: Explorar variància acumulada manualment pca_full = PCA() pca_full.fit(X_scaled) variancia_acumulada = np.cumsum(pca_full.explained_variance_ratio_) print(variancia_acumulada) # Ex: [0.72, 0.87, 0.95, 0.98, 1.0] # → Amb 3 components ja tenim el 95%

Consells pràctics

  • Per defecte, comença amb un llindar del 95% de variància retinguda
  • Per visualització, utilitza sempre 2 o 3 components
  • Per models predictius, valida amb cross-validation sobre la tasca final: a vegades menys components (que eliminen soroll) milloren el rendiment

Resum

PCA és un algoritme potent per reduir la dimensionalitat:

  • Pren dades amb moltes característiques (alta dimensionalitat)
  • Les redueix a 2 o 3 característiques principals
  • Permet visualitzar i entendre millor les dades

És especialment útil per explorar conjunts de dades complexos, detectar patrons i anomalies, i preparar les dades per altres algorismes d’aprenentatge automàtic.

Errors comuns a evitar

Aquests són alguns errors freqüents quan s’apliquen tècniques d’aprenentatge no supervisat:

K-means:

  • Escollir K arbitràriament sense usar el mètode del colze o considerar el context
  • No normalitzar les característiques (les variables amb escales grans dominaran)
  • Executar l’algoritme només una vegada (pot quedar atrapat en mínims locals)

Detecció d’anomalies:

  • Configurar malament el paràmetre de contaminació (massa falsos positius o falsos negatius)
  • No escalar o preparar adequadament les característiques quan tenen escales molt diferents
  • Interpretar l’anomaly score com una probabilitat

PCA:

  • Oblidar normalitzar les dades abans d’aplicar PCA (imprescindible!)
  • Reduir a massa poques dimensions i perdre informació important
  • Interpretar els components principals com si fossin les variables originals

Apèndix: Detecció d’anomalies (ampliació)

Aquesta secció conté material addicional sobre detecció d’anomalies per a qui vulgui aprofundir en el tema.

Quan usar aprenentatge supervisat

Usa supervised learning quan:

  1. Tens centenars o milers d’exemples positius
  2. Les anomalies futures seran similars a les passades
  3. Els patrons són repetitius i estables
  4. Necessites alta precisió en casos coneguts

Exemples:

  • Classificació de correu brossa: Els correus spam tendeixen a repetir patrons similars (ofertes, enllaços sospitosos, majúscules excessives). Els futurs spams seran similars als passats.
  • Diagnòstic mèdic de malalties conegudes: Els símptomes d’una pneumònia o diabetis són estables i ben documentats.
  • Detecció de defectes coneguts: Si una fàbrica de smartphones sap que el 2% de pantalles tenen un ratllat específic per una màquina defectuosa, pot entrenar un classificador per detectar aquest defecte concret.

Taula d’exemples aplicats

AplicacióRecomanacióRaó
Frau amb targeta de crèditAnomaly detectionNoves tècniques de frau emergeixen constantment
Classificació de correu brossaSupervised learningPatrons de spam són repetitius i coneguts
Defectes nous en fabricacióAnomaly detectionTipus de defecte imprevisibles i canviants
Diagnòstic de grip vs pneumòniaSupervised learningSímptomes ben establerts i documentats
Detecció d’intrusions a xarxesAnomaly detectionAtacs nous i sofisticats apareixen regularment
Predicció meteorològicaSupervised learningNomés hi ha uns quants tipus de temps coneguts

Enfocament híbrid

En alguns casos, es poden combinar ambdues tècniques:

  1. Fase 1: Usar anomaly detection per identificar casos sospitosos
  2. Fase 2: Revisió manual i etiquetatge d’aquests casos
  3. Fase 3: Quan s’acumulin prou exemples (>100), entrenar un model supervisat per als patrons coneguts
  4. Fase 4: Mantenir anomaly detection per detectar nous tipus no coberts pel supervisat

Aquest enfocament aprofita el millor de cada món: eficiència per patrons coneguts i capacitat de detectar anomalies noves.

Enginyeria de característiques

En detecció d’anomalies, l’elecció de bones característiques és crítica. A diferència de l’aprenentatge supervisat, on el model pot aprendre quines característiques ignorar, en anomaly detection no tenim senyal supervisada per guiar aquest procés.

Per què és tan important?

Isolation Forest (i altres mètodes no supervisats) no saben què fa que una observació sigui anòmala sense que nosaltres els hi indiquem a través de les característiques.

Exemple: En detecció de frau, tenir només “import de transacció” podria no ser suficient, perquè una transacció de 1.000€ pot ser normal per un client i anòmala per un altre. Però la característica import / mitjana_habitual_usuari és molt més informativa.

Creació de característiques rellevants

Principi general: Crear característiques que capturin desviacions del comportament normal.

A continuació es mostren alguns exemples per dominis.

Targetes de crèdit:

# Característiques bàsiques df['hour_of_day'] = df['timestamp'].dt.hour df['day_of_week'] = df['timestamp'].dt.dayofweek # Característiques relatives a l'usuari df['amount_vs_avg'] = df['amount'] / df.groupby('user_id')['amount'].transform('mean') df['time_since_last'] = df.groupby('user_id')['timestamp'].diff().dt.total_seconds() # Característiques de freqüència df['transactions_last_hour'] = df.groupby('user_id').rolling('1H', on='timestamp').count()

Monitoratge de servidors:

# Ràtios que capten comportaments anòmals df['cpu_per_network'] = df['cpu_load'] / (df['network_traffic'] + 1) # +1 evita divisió per 0 df['memory_growth_rate'] = df.groupby('server_id')['memory_used'].diff() df['disk_io_vs_cpu'] = df['disk_io'] / (df['cpu_load'] + 0.01)

Fabricació:

# Relacions entre variables físiques df['temp_vibration_ratio'] = df['temperature'] / (df['vibration'] + 0.001) df['pressure_deviation'] = np.abs(df['pressure'] - df['pressure'].rolling(10).mean())

Transformacions de distribucions

Moltes vegades, les característiques originals tenen distribucions molt esbiaixades (skewed). Aplicar transformacions pot ajudar els algoritmes a funcionar millor.

A continuació es mostren transformacions habituals:

TransformacióQuan usar-laExemple
log(X + c)Distribució molt esbiaixada a la dretaImports monetaris, freqüències
sqrt(X)Esbiaixament moderatComptadors, taxes
X^(1/3) o altres potènciesValors extrems molt gransVolums, poblacions
1/XRelació inversaTemps entre esdeveniments

⚠️ Important: Qualsevol transformació aplicada al conjunt d’entrenament s’ha d’aplicar també als conjunts de validació i test.

Anàlisi d’errors iteratiu

El procés de millorar un sistema de detecció d’anomalies és iteratiu:

Workflow recomanat:

  1. Entrenar model amb característiques actuals
  2. Avaluar sobre validation set (amb anomalies etiquetades)
  3. Identificar FALSOS NEGATIUS (anomalies no detectades)
  4. Analitzar què diferencia aquests casos dels normals
  5. Crear noves característiques que captin aquestes diferències
  6. Tornar a 1

Exemple pràctic:

Suposem que el nostre model no detecta un servidor compromès que està enviant dades a l’exterior.

Anàlisi:

  • CPU: Normal (3.2 GHz) ✓
  • Memòria: Normal (40% usat) ✓
  • Tràfic de xarxa: Alt però no extremadament (podria ser legítim) ⚠️

Solució: Crear una nova característica:

# Ràtio de tràfic de xarxa vs càrrega de CPU df['network_per_cpu'] = df['network_traffic'] / (df['cpu_load'] + 0.01)

Aquesta característica serà anormalment alta per un servidor que envia dades sense fer càlculs intensius, permetent detectar l’anomalia.

Normalització i escalat

Isolation Forest és relativament robust a escales diferents, però sovint és recomanable normalitzar les característiques:

from sklearn.preprocessing import StandardScaler # Normalitzar (mitjana=0, desviació estàndard=1) scaler = StandardScaler() X_train_scaled = scaler.fit_transform(X_train) X_val_scaled = scaler.transform(X_val) # Usar mateixos paràmetres! # Entrenar amb dades normalitzades clf = IsolationForest(contamination=0.05, random_state=42) clf.fit(X_train_scaled)

Això és especialment important si les característiques tenen unitats molt diferents (ex: temperatura en ºC vs pressió en Pa).

Consells pràctics i workflow complet

1. Context de negoci primer

L’algorisme més sofisticat no serveix de res sense coneixement del domini:

  • Parla amb experts del sector (enginyers, auditors, metges…)
  • Entén què fa que una observació sigui realment problemàtica
  • Defineix el cost dels falsos positius vs falsos negatius

Pregunta clau: És millor revisar 100 casos normals per no perdre 1 anomalia? O preferim perdre algunes anomalies per evitar sobrecàrrega de revisions?

2. Comença simple, itera ràpid

No intentis crear el model perfecte des del principi:

Iteració 1: 2-3 característiques bàsiques → Avalua → Identifica errors Iteració 2: Afegeix 1-2 característiques noves → Avalua → Millora? Iteració 3: Prova transformacions → Avalua → Ajusta contamination

Cada iteració hauria de durar minuts o hores, no dies.

3. Quan considerar aprenentatge supervisat

Si després d’uns mesos d’ús del sistema tens:

  • Més de 100 anomalies etiquetades → Planteja’t un model supervisat complementari
  • Patrons repetitius clars → Random Forest o XGBoost poden funcionar millor
  • Nous tipus d’anomalies emergeixen → Manté l’anomaly detection com a primera línia

Enfocament híbrid recomanat:

  1. Isolation Forest detecta casos sospitosos
  2. Revisió humana etiqueta aquests casos
  3. Model supervisat per patrons coneguts
  4. Isolation Forest per detectar patrons nous