A 05-03 vam entrenar un MLP i va empatar amb la regressió logística en el predictor de devolucions. No és una derrota de les xarxes: és el senyal que el seu terreny és un altre. Aquesta lliçó explica què és exactament el deep learning, per què va enlairar-se el 2012 i no abans, i quines són les arquitectures que incorporen l'estructura de les dades i per això veuen, senten i llegeixen allà on l'MLP i els models clàssics no arriben: les xarxes convolucionals per a imatges (amb una convolució calculada a mà i un miniexemple en PyTorch sobre fotos sintètiques de paquets danyats i correctes, el cas de les incidències de NovaMarket), les xarxes recurrents per a seqüències, els autoencoders per detectar anomalies i la transferència d'aprenentatge, la idea que ha canviat la pràctica professional: no entrenar des de zero. Tancarem amb el panorama d'aplicacions i amb els seus costos i límits. És important perquè és aquí on les xarxes justifiquen la seva complexitat, i on la Marta trobarà les eines per a les fotos d'incidencies.csv i, a la lliçó següent, per a les ressenyes.

Contingut

  1. Què fa "profund" el deep learning i per què va enlairar-se
  2. Aprenentatge de representacions jeràrquiques
  3. Xarxes convolucionals: convolució, filtres, pooling i mapes de característiques
  4. Codi: una CNN per a les fotos d'incidències de NovaMarket
  5. Xarxes recurrents: seqüències, estat ocult, LSTM i GRU
  6. Autoencoders i detecció d'anomalies
  7. Transferència d'aprenentatge i models preentrenats
  8. Panorama d'aplicacions
  9. Costos i límits
  10. Errors Comuns i Consells
  11. Exercicis
  12. Conclusió

  1. Què fa "profund" el deep learning i per què va enlairar-se

El deep learning és aprenentatge automàtic amb xarxes neuronals de moltes capes (d'unes poques a centenars). El "profund" no és només un nombre: és que la xarxa aprèn una jerarquia de representacions (secció 2) en lloc de rebre característiques dissenyades a mà. Al mòdul 4 la Marta va crear import_per_article o taxa_devolucio_previa amb el seu coneixement del negoci; una xarxa profunda inventa les seves pròpies "columnes" a partir de píxels o paraules.

La teoria existia des dels anys 80 (retropropagació, 05-03) i les convolucionals des del 1989 (LeNet de LeCun, per llegir codis postals). Per què l'enlairament el 2012? Hi van confluir quatre coses:

Ingredient Abans Des de ~2010 Per què importa
Dades Milers d'exemples ImageNet: 1,2 milions d'imatges etiquetades en 1.000 classes; tota la web per a text Les xarxes profundes tenen milions de paràmetres; sense dades, sobreajusten (04-06)
Còmput CPU GPU (targetes gràfiques): milers de nuclis que multipliquen matrius en paral·lel Entrenar en dies el que costaria mesos; les capes denses i convolucionals són multiplicacions de matrius
Algorismes Sigmoide, xarxes de 2-3 capes ReLU (05-02), millors inicialitzacions, dropout, normalització per lots (05-03) Sense ReLU el gradient s'esvaeix i les capes profundes no aprenen
Programari Codi a mà Frameworks amb diferenciació automàtica (Theano, després TensorFlow i PyTorch; 07-03) backward() de franc; experimentar és qüestió d'hores

El moment simbòlic és ImageNet 2012 (01-01): AlexNet, una convolucional de 8 capes i 60 milions de paràmetres entrenada en dues GPU, va abaixar l'error de classificació del 26 % al 16 % de cop, quan les millores anuals eren d'un punt. Des d'aleshores, cada domini (visió, veu, text) va anar caient davant la mateixa recepta: xarxa profunda, moltes dades, GPU.

  1. Aprenentatge de representacions jeràrquiques

La idea central: cada capa transforma la sortida de l'anterior en una cosa més abstracta. En una xarxa que reconeix fotos de paquets:

flowchart LR
    P["Píxels<br/>(valors 0-1)"] --> C1["Capa 1<br/>vores, taques,<br/>canvis de brillantor"]
    C1 --> C2["Capa 2<br/>cantonades, línies,<br/>textures"]
    C2 --> C3["Capa 3<br/>parts: solapa,<br/>cinta, esquerda"]
    C3 --> C4["Capa 4<br/>objecte: caixa<br/>intacta / danyada"]
    C4 --> S["Sortida<br/>probabilitat"]

Ningú no programa un "detector d'esquerdes": apareix perquè és útil per minimitzar la pèrdua. El mateix passa amb el text (lletres → paraules → frases → sentit) i amb l'àudio (ones → fonemes → paraules). Aquesta és la resposta a la pregunta de 05-01: per què les xarxes poden llegir i mirar. Aprenen la conversió de dades brutes a característiques, la part que al mòdul 4 feia la Marta a mà i que, per a píxels i paraules, ningú no sap fer bé a mà. I explica també per què la profunditat rendeix més que l'amplada (05-02): compondre transformacions simples és més eficient que aproximar la funció de cop.

  1. Xarxes convolucionals: convolució, filtres, pooling i mapes de característiques

Un MLP sobre una imatge de 16×16 l'aplana en 256 nombres sense saber que el píxel 17 és a sota de l'1. Les xarxes convolucionals (CNN) incorporen dos supòsits certs per a les imatges: els patrons són locals (una esquerda ocupa uns pocs píxels veïns) i es poden donar en qualsevol posició (l'esquerda pot ser a dalt o a baix). Ho aconsegueixen amb tres peces:

3.1 La convolució i els filtres

Un filtre (o kernel) és una matriu petita de pesos, típicament 3×3. La convolució llisca el filtre sobre la imatge i, en cada posició, multiplica element a element i suma. El resultat és un mapa de característiques que diu "quant s'assembla aquest tros d'imatge al patró del filtre". Exemple a mà: imatge 5×5 amb un quadrat clar (valor 9) sobre fons 0, i un filtre que detecta vores verticals (columna esquerra −1, centre 0, dreta +1):

Imatge (5×5)          Filtre (3×3)
0 0 0 0 0             -1  0  1
0 9 9 9 0             -1  0  1
0 9 9 9 0             -1  0  1
0 9 9 9 0
0 0 0 0 0

Col·loquem el filtre a la cantonada superior esquerra (files 0-2, columnes 0-2 de la imatge): (0·−1 + 0·0 + 0·1) + (0·−1 + 9·0 + 9·1) + (0·−1 + 9·0 + 9·1) = 18. El desplacem una columna cap a la dreta (columnes 1-3): (0 + 0 + 0) + (−9 + 0 + 9) + (−9 + 0 + 9) = 0. Una més (columnes 2-4): (0 + 0 + 0) + (−9 + 0 + 0) + (−9 + 0 + 0) = −18. Repetint-ho a les 3 × 3 posicions possibles:

Posició (fila, col) Càlcul Sortida
(0, 0) 0 + 9 + 9 18
(0, 1) 0 + (−9+9) + (−9+9) 0
(0, 2) 0 − 9 − 9 −18
(1, 0) 9 + 9 + 9 27
(1, 1) 0 0
(1, 2) −27 −27
(2, 0) 18 18
(2, 1) 0 0
(2, 2) −18 −18

Mapa de característiques resultant (3×3): la columna esquerra "s'encén" (vora esquerra del quadrat, pas fosc→clar), la dreta s'encén en negatiu (clar→fosc) i el centre, sense canvis horitzontals, queda a 0. El filtre transposat (files −1, 0, +1) detecta vores horitzontals i dona [[18, 27, 18], [0, 0, 0], [−18, −27, −18]]. Detalls: la sortida s'encongeix (5×5 → 3×3) llevat que s'hi afegeixi una vora de zeros (padding), i el filtre pot saltar de 2 en 2 (stride). L'essencial: els 9 pesos del filtre s'aprenen per retropropagació, igual que els d'una capa densa, i una capa convolucional té molts filtres (8, 16, 64...) que produeixen altres tants mapes. Amb 9 pesos per filtre i els mateixos pesos a tota la imatge, una capa convolucional té moltíssims menys paràmetres que una densa equivalent i detecta el patró sigui on sigui.

3.2 Pooling

El pooling redueix la mida dels mapes quedant-se amb un resum de cada bloc, gairebé sempre el màxim (max pooling) de blocs 2×2. Sobre [[1, 3, 2, 0], [4, 6, 1, 1], [0, 2, 7, 5], [3, 1, 8, 2]] dona [[6, 2], [3, 8]]. Aporta invariància a petits desplaçaments (si l'esquerda es mou un píxel, el màxim del bloc no canvia) i divideix el còmput per quatre a cada nivell.

3.3 Arquitectura típica

Blocs convolució → ReLU → pooling repetits (cadascun amb més filtres i mapes més petits: la jerarquia de la secció 2), seguits de Flatten i una o dues capes denses que classifiquen. És l'estructura de LeNet (1989), AlexNet (2012) i, amb dreceres residuals per arribar a centenars de capes, de les ResNet (2015).

  1. Codi: una CNN per a les fotos d'incidències de NovaMarket

Les fotos reals d'incidencies.csv no les tenim, així que generem amb numpy imatges sintètiques de 16×16 en escala de grisos: una caixa clara sobre fons fosc, i a la meitat un dany (una esquerda diagonal o una bonyada fosca). L'objectiu és veure la CNN funcionar i comparar-la amb un MLP; a 09-03 es farà un projecte complet amb imatges reals.

import numpy as np, torch, torch.nn as nn

def generar_fotos(n=600, llavor=42, mida=16):
    """Fotos sintètiques 16x16: caixa clara sobre fons fosc. 1 = danyada, 0 = correcta."""
    rng = np.random.default_rng(llavor)
    X = np.zeros((n, 1, mida, mida), dtype=np.float32)        # (n, canals, alt, ample)
    y = np.zeros(n, dtype=np.int64)
    for i in range(n):
        img = rng.normal(0.1, 0.05, (mida, mida))              # fons fosc amb soroll
        x0, y0 = rng.integers(1, 5, size=2)                    # cantonada superior esquerra de la caixa
        x1, y1 = rng.integers(mida - 5, mida - 1, size=2)      # cantonada inferior dreta
        img[y0:y1, x0:x1] = rng.normal(0.7, 0.05, (y1 - y0, x1 - x0))   # la caixa, clara
        if rng.random() < 0.5:                                 # la meitat, danyades
            y[i] = 1
            if rng.random() < 0.5:                             # esquerda: diagonal fosca
                r0 = rng.integers(y0, y1 - 4); c0 = rng.integers(x0, x1 - 4)
                llargada = rng.integers(4, min(y1 - r0, x1 - c0) + 1)
                for k in range(llargada):
                    img[r0 + k, c0 + k] = 0.05
            else:                                              # bonyada: quadrat fosc
                r0 = rng.integers(y0, y1 - 3); c0 = rng.integers(x0, x1 - 3)
                costat = rng.integers(2, 4)
                img[r0:r0 + costat, c0:c0 + costat] = rng.normal(0.15, 0.05, (costat, costat))
        X[i, 0] = np.clip(img, 0, 1)
    return X, y

X, y = generar_fotos()
print(X.shape, " danyades:", y.mean())
np.set_printoptions(linewidth=120)
print((X[1, 0] * 9).astype(int))        # una foto, amb els valors 0-1 escalats a 0-9 per veure-la
print("etiqueta:", y[1])

Sortida (retallada):

(600, 1, 16, 16)  danyades: 0.51
[[1 0 1 1 1 0 1 1 1 1 1 0 0 0 1 1]
 [0 0 1 0 0 0 1 0 1 1 1 1 1 0 0 1]
 [0 0 1 0 0 0 0 1 1 1 0 0 0 0 1 1]
 [0 6 6 6 5 6 5 6 5 6 5 5 6 0 0 0]
 [0 6 6 6 6 6 6 6 6 6 6 6 5 0 0 1]
 [1 5 7 7 6 5 6 6 6 5 6 6 5 0 1 1]
 [1 6 7 6 6 6 6 5 6 6 7 6 7 1 0 1]
 [0 5 6 6 5 0 6 6 5 6 5 6 6 0 0 1]
 [0 5 5 6 6 5 0 6 5 5 6 6 7 0 1 1]
 [1 6 6 6 6 6 6 0 6 6 6 6 6 0 0 1]
 [1 6 6 6 6 5 5 5 0 5 5 6 6 0 0 1]
 [0 6 5 6 6 5 5 6 6 0 6 6 5 0 1 0]
 ...
etiqueta: 1

S'hi veu la caixa (valors 5-7) i l'esquerda diagonal de zeros que baixa de la fila 7 a l'11. Ara la CNN, un MLP per comparar, i l'entrenament (el bucle és el de 05-03, amb CrossEntropyLoss perquè tenim 2 logits de sortida):

Xtr, ytr, Xte, yte = X[:450], y[:450], X[450:], y[450:]         # 450 per entrenar, 150 per a test
Xtr_t, ytr_t = torch.tensor(Xtr), torch.tensor(ytr)
Xte_t, yte_t = torch.tensor(Xte), torch.tensor(yte)

torch.manual_seed(0)
cnn = nn.Sequential(
    nn.Conv2d(1, 8, kernel_size=3, padding=1), nn.ReLU(), nn.MaxPool2d(2),    # 1x16x16 -> 8x16x16 -> 8x8x8
    nn.Conv2d(8, 16, kernel_size=3, padding=1), nn.ReLU(), nn.MaxPool2d(2),   # 8x8x8 -> 16x8x8 -> 16x4x4
    nn.Flatten(),                                                              # 16*4*4 = 256 valors
    nn.Linear(256, 32), nn.ReLU(),
    nn.Linear(32, 2))                                                          # 2 logits: correcta / danyada
mlp = nn.Sequential(nn.Flatten(), nn.Linear(256, 64), nn.ReLU(), nn.Linear(64, 2))
print("Paràmetres CNN:", sum(p.numel() for p in cnn.parameters()), " MLP:", sum(p.numel() for p in mlp.parameters()))

def entrenar(xarxa, epoques=15, taxa=0.003, lot=32):
    opt = torch.optim.Adam(xarxa.parameters(), lr=taxa)
    perdua_fn = nn.CrossEntropyLoss()                 # softmax + entropia creuada (05-02)
    for ep in range(1, epoques + 1):
        xarxa.train()
        perm = torch.randperm(len(Xtr_t))             # barrejar els índexs
        for i in range(0, len(perm), lot):            # minilots de 32
            idx = perm[i:i + lot]
            opt.zero_grad()
            L = perdua_fn(xarxa(Xtr_t[idx]), ytr_t[idx])
            L.backward()
            opt.step()
        xarxa.eval()
        with torch.no_grad():
            acc_tr = (xarxa(Xtr_t).argmax(1) == ytr_t).float().mean().item()   # argmax: classe amb el logit més alt
            acc_te = (xarxa(Xte_t).argmax(1) == yte_t).float().mean().item()
        if ep in (1, 3, 5, 10, 15):
            print(f"època {ep:2d}  encert train {acc_tr:.3f}  test {acc_te:.3f}")

print("CNN:"); torch.manual_seed(0); entrenar(cnn)
print("MLP:"); torch.manual_seed(0); entrenar(mlp)

Sortida (varia amb la llavor i la versió):

Paràmetres CNN: 9538  MLP: 16578
CNN:
època  1  encert train 0.578  test 0.567
època  3  encert train 0.680  test 0.680
època  5  encert train 0.962  test 0.960
època 10  encert train 0.991  test 0.973
època 15  encert train 0.998  test 0.987
MLP:
època  1  encert train 0.553  test 0.480
època  3  encert train 0.616  test 0.533
època  5  encert train 0.531  test 0.540
època 10  encert train 0.547  test 0.513
època 15  encert train 0.613  test 0.567

Lectura, línia a línia del model: nn.Conv2d(1, 8, kernel_size=3, padding=1) aprèn 8 filtres de 3×3 sobre 1 canal (72 pesos + 8 biaixos) i, gràcies al padding, manté la mida 16×16; MaxPool2d(2) l'abaixa a 8×8; la segona convolució produeix 16 mapes de 8×8 amb filtres que miren els 8 mapes anteriors (16 × 8 × 3 × 3 = 1.152 pesos); després del segon pooling queden 16 mapes de 4×4, és a dir 256 valors que Flatten converteix en vector per a les denses. El resultat és contundent: la CNN encerta el 98,7 % de les fotos de test (matriu de confusió: 75 correctes ben classificades, 73 danyades detectades, 2 danyades que s'escapen) amb menys paràmetres (9.538) que l'MLP (16.578), que es queda en un 57 %, poc millor que l'atzar, perquè per a ell cada píxel és una columna independent i la mateixa esquerda en una altra posició és un patró nou. Els mapes de la primera capa (cnn[1](cnn[0](Xte_t[:1])) té forma [1, 8, 16, 16]) són 8 versions "filtrades" de la foto; els pesos apresos (cnn[0].weight[0, 0]) formen detectors de vores semblants al de la secció 3.1, sense que ningú els hagi dissenyat. Per al Diego: amb 450 fotos etiquetades i un minut de CPU tenim un classificador de paquets danyats que funciona; amb fotos reals caldrien més dades, augment de dades (exercici 2) i probablement transferència d'aprenentatge (secció 7).

  1. Xarxes recurrents: seqüències, estat ocult, LSTM i GRU

Les sèries temporals (la demanda setmanal del NovaClean, 04-04) i el text són seqüències en què l'ordre importa i la longitud varia. Una xarxa recurrent (RNN) processa la seqüència element a element mantenint un estat ocult h, un vector que resumeix el que ha vist fins ara: a cada pas, h_t = f(W·x_t + U·h_{t−1} + b), és a dir, la mateixa neurona de sempre però alimentada també amb el seu propi estat anterior. Els mateixos pesos W i U s'apliquen a tots els passos (com el filtre de la CNN s'aplica a totes les posicions), i l'estat final, o la seqüència d'estats, es passa a una capa de sortida.

flowchart LR
    x1["x₁ (setm. 1)"] --> H1["h₁"]
    x2["x₂ (setm. 2)"] --> H2["h₂"]
    x3["x₃ (setm. 3)"] --> H3["h₃"]
    x4["x₄ (setm. 4)"] --> H4["h₄"]
    H1 --> H2 --> H3 --> H4
    H4 --> Y["ŷ (setm. 5)"]

El problema de la RNN simple és que, en entrenar-la, el gradient travessa tants passos com elements tingui la seqüència, multiplicant-se a cadascun: el gradient que s'esvaeix (05-02) en versió temporal. A la pràctica, oblida el que va passar fa més d'unes desenes de passos. Les LSTM (long short-term memory, 1997) i les GRU (gated recurrent unit, 2014) ho resolen amb comportes: petites neurones sigmoides que decideixen, a cada pas, quina part de l'estat s'oblida, quina part de l'entrada s'escriu i què es llegeix per a la sortida. Una "cinta transportadora" de memòria per la qual la informació i el gradient viatgen sense degradar-se. No cal memoritzar les equacions; sí saber que nn.LSTM i nn.GRU de PyTorch (per exemple, nn.GRU(input_size=1, hidden_size=8, batch_first=True), amb 264 paràmetres, retorna per a una seqüència de 12 setmanes 12 estats de 8 valors) són l'eina quan la dependència és llarga. Aplicacions: previsió de demanda amb les 8-12 setmanes anteriors (davant de l'MLP de la solució 3 de 05-02, la GRU respecta l'ordre), classificació de text paraula a paraula, reconeixement de veu. En text, des del 2018 els transformers (05-05) han substituït les recurrents; en sèries temporals continuen sent competitives. 09-03 inclou un projecte guiat amb una xarxa recurrent sobre la demanda del NovaClean.

  1. Autoencoders i detecció d'anomalies

Un autoencoder és una xarxa entrenada per reproduir la seva entrada: un codificador comprimeix les dades a un vector petit (el "coll d'ampolla" o representació latent) i un descodificador intenta reconstruir l'original; la pèrdua és l'error de reconstrucció (MSE). Sembla inútil (per a què copiar?), però en passar pel coll d'ampolla la xarxa es veu obligada a aprendre l'essencial de les dades, sense etiquetes: és aprenentatge no supervisat (04-02).

Ús estrella a NovaMarket: detecció d'anomalies (cas 3, frau). S'entrena l'autoencoder només amb comandes normals; les comandes rares, com que no s'assemblen a res del que ha après, es reconstrueixen malament. Amb un autoencoder mínim (nn.Sequential(nn.Linear(4, 2), nn.Tanh(), nn.Linear(2, 4)), coll de 2) sobre les columnes estandarditzades import_comanda, num_articles, dies_lliurament i client_nou de les 3.000 comandes, 200 èpoques d'Adam deixen l'error mitjà de reconstrucció en 0,51. Si generem 30 comandes anòmales (import altíssim, molts articles, lliurament en un dia, client nou), el seu error mitjà és 8,0; fixant el llindar al percentil 99 de les comandes normals (2,61) es detecten les 30 anòmales amb un 1 % de falses alarmes. Altres aplicacions: reducció de dimensió per visualitzar clients (alternativa no lineal a la PCA), eliminació de soroll en imatges, i la variant variacional (VAE), primer model generatiu d'imatges modern.

  1. Transferència d'aprenentatge i models preentrenats

La idea que més ha canviat la pràctica: no entrenar des de zero. Una CNN entrenada en ImageNet ha après a les primeres capes detectors de vores, textures i formes que serveixen per a qualsevol imatge, també per a fotos de paquets. La transferència d'aprenentatge consisteix a agafar aquest model preentrenat, treure-li la capa de sortida (que classificava 1.000 classes d'ImageNet), posar-ne una de nova per al nostre problema (2 classes) i entrenar només aquesta capa (extracció de característiques) o tota la xarxa amb una taxa d'aprenentatge petita (ajust fi, fine-tuning). Resultat: bons models amb centenars d'exemples en lloc de milions, i en minuts en lloc de dies.

Exemple il·lustratiu, no executable en aquest entorn (requereix torchvision i descarregar els pesos), del patró amb una ResNet-18:

# IL·LUSTRATIU: patró de transferència d'aprenentatge amb torchvision (no executat aquí)
import torchvision
model = torchvision.models.resnet18(weights="IMAGENET1K_V1")     # CNN preentrenada en ImageNet
for p in model.parameters():
    p.requires_grad = False                                       # congelar tot el que ha après
model.fc = nn.Linear(model.fc.in_features, 2)                     # nova sortida: correcta / danyada
# A partir d'aquí, el bucle d'entrenament de 05-03 amb les fotos reals d'incidències
# (redimensionades a 224x224 i normalitzades com espera la ResNet) entrena NOMÉS model.fc.

El mateix existeix per a text (BERT, GPT i companyia, 05-05), àudio (Whisper) i gairebé qualsevol domini, distribuït en repositoris com Hugging Face. La conseqüència estratègica per a NovaMarket la resumeix la Marta: "no entrenarem una xarxa de visió des de zero; adaptarem una que ja hi veu".

  1. Panorama d'aplicacions

Arquitectura Problema Exemple real Exemple NovaMarket
CNN Classificació i detecció en imatges Diagnòstic per imatge mèdica; inspecció visual a fàbriques; cotxes autònoms Fotos d'incidències (paquet danyat / correcte); cerca visual de productes
CNN / transformers Reconeixement de veu Assistents de veu, transcripció de trucades Transcriure les trucades d'atenció al client
RNN / transformers Sèries temporals Previsió de consum elèctric, trànsit Previsió de demanda del NovaClean (cas 2)
RNN / transformers Processament del llenguatge Traducció automàtica, resum, chatbots Sentiment de ressenyes (cas 4); assistent (cas 7), a 05-05
Embeddings + MLP Recomanació Netflix, Spotify, Amazon "Els clients que van comprar el NovaClean també..." (cas 1)
Autoencoder Anomalies, compressió Frau amb targeta, fallades en màquines Comandes anòmales (cas 3)
Xarxes profundes + reforç Jocs, control AlphaGo (01-01), robòtica, control de centres de dades Polítiques d'assignació de comandes a magatzems (cas 6), a llarg termini
CNN / transformers Ciència AlphaFold (estructura de proteïnes), meteorologia, descobriment de materials (Fora del negoci)

En recomanació val la pena aturar-s'hi: cada client i cada producte reben un embedding (05-02) i una xarxa prediu l'afinitat a partir de tots dos; els 12.000 productes de NovaMarket queden en un espai on el NovaClean és a prop de les bosses d'aspiradora i lluny de les cafeteres, après només a partir de què es compra junt. I en aprenentatge per reforç profund, la xarxa aproxima el valor de cada acció (03-03, 04-02); AlphaGo va combinar una CNN que avaluava taulers amb cerca en arbre.

  1. Costos i límits

El Diego, que ha vist el 98,7 % de les fotos, pregunta quant costa i què pot sortir malament. Resposta honesta:

  • Dades etiquetades: la CNN va necessitar 450 fotos etiquetades; una de real, milers, o transferència d'aprenentatge. Etiquetar costa temps de persones i arrossega biaixos d'etiquetatge (02-03).
  • Còmput i energia: entrenar models grans costa de milers a milions d'euros en GPU i una petjada energètica considerable; la inferència també compta si s'executa milions de vegades al dia. Triar el model més petit que resol el problema és una decisió econòmica i ambiental.
  • Opacitat: no podem llegir els 9.538 pesos de la CNN com llegíem els coeficients de la logística. Hi ha tècniques d'explicació (mapes de saliència que ressalten quins píxels han pesat, SHAP), però són aproximades. Amb l'AI Act (02-04), un sistema que decideixi sobre persones necessita explicabilitat i supervisió humana; per classificar fotos de paquets el risc és baix, per denegar una devolució no.
  • Fragilitat: les xarxes s'equivoquen amb confiança davant de dades diferents de les d'entrenament (una foto amb una altra il·luminació, un altre tipus de caixa) i són vulnerables als exemples adversaris (pertorbacions imperceptibles que canvien la predicció). Cal monitorar en producció (08-01).
  • Biaix: aprenen el que hi ha a les dades, incloent-hi l'indesitjable (02-04). Una CNN de "producte en bon estat" entrenada només amb caixes marrons fallarà amb caixes blanques.
  • Deute de manteniment: versions de frameworks, GPU, reentrenaments. Cada model en producció és un sistema que envelleix.

Errors Comuns i Consells

  • Aplanar imatges per a un MLP. Es perd l'estructura espacial i el model necessita moltes més dades i paràmetres per a un resultat pitjor, com acabem de veure (57 % davant de 98,7 %). Per a imatges, convolucions (o un model preentrenat).
  • Entrenar des de zero per defecte. Amb poques dades, la transferència d'aprenentatge gairebé sempre guanya. Abans de dissenyar una xarxa, busca un model preentrenat del domini.
  • Oblidar l'ordre de les dimensions. PyTorch espera (lot, canals, alt, ample) a les CNN i (lot, temps, característiques) a les recurrents amb batch_first=True. Un error aquí no dona excepció: dona resultats absurds.
  • Confondre la forma de la sortida de la CNN. Abans de la primera capa densa cal saber quants valors surten de l'últim pooling (aquí 16 × 4 × 4 = 256); calcula-ho o imprimeix-ho amb un tensor de prova.
  • Sense augment de dades en imatges. Girar, retallar i canviar la brillantor és la regularització més barata en visió (exercici 2).
  • Vendre el deep learning com a màgia. Costa dades, GPU i manteniment, i és opac. Per a taules petites, la logística o el bosc del mòdul 4 continuen sent la primera opció, com vam comprovar a 05-03.

Exercicis

Exercici 1. Calcula a mà la convolució de la imatge 5×5 de la secció 3.1 amb el filtre [[1, 1, 1], [0, 0, 0], [−1, −1, −1]] (detector de vores horitzontals). Comprova el resultat amb la funció conv2d(img, k) que recorri les posicions amb dos bucles i (img[i:i+3, j:j+3] * k).sum(). Quina vora de la caixa s'encén en positiu i quina en negatiu?

Exercici 2. Augment de dades. Amb la CNN ja entrenada de la secció 4, avalua l'encert sobre el test reflectit horitzontalment (torch.flip(Xte_t, dims=[3])), on les esquerdes diagonals passen a tenir l'orientació contrària. Després reentrena una CNN nova afegint a l'entrenament les versions reflectides (torch.cat([Xtr_t, torch.flip(Xtr_t, dims=[3])]) i duplicant les etiquetes) i torna a mesurar sobre el test normal i el reflectit. Explica el resultat.

Exercici 3. A l'autoencoder de la secció 6, què passa amb les falses alarmes i amb la detecció de les 30 anòmales si el llindar es fixa al percentil 95 en lloc del 99? I si s'entrena l'autoencoder amb les comandes anòmales barrejades entre les normals? Raona-ho sense executar i, si vols, comprova-ho replicant el codi descrit.

Solucions

Solució 1. El resultat és [[−18, −27, −18], [0, 0, 0], [18, 27, 18]]. A la fila superior de sortida el filtre cau amb els pesos +1 sobre el fons (0) i amb els −1 sobre la caixa (9): la vora superior de la caixa s'encén en negatiu; la fila central dona 0 (dins de la caixa no hi ha canvi vertical); a la inferior els +1 cauen sobre la caixa i els −1 sobre el fons: la vora inferior s'encén en positiu. És el mapa del filtre transposat de la secció 3.1 amb el signe canviat (aquell tenia els −1 a dalt). Cada filtre "veu" una orientació i un sentit, i per això una capa té molts filtres.

Solució 2. A la nostra execució, la CNN entrenada sense reflexos baixa del 98,7 % al 96,0 % sobre el test reflectit (6 danyades s'escapen en lloc de 2): ha après en part "esquerda = diagonal que baixa cap a la dreta" i l'orientació contrària li resulta menys familiar. Amb els reflexos afegits a l'entrenament (900 imatges), la CNN nova arriba al 99,3 % en el test normal i al 98,7 % en el reflectit: l'augment de dades li ha ensenyat la invariància correcta (una esquerda és una esquerda en qualsevol orientació) sense necessitat d'etiquetar ni una foto més. En un cas real s'hi afegirien rotacions, retalls i canvis de brillantor, i s'aplicarien al vol a cada època en lloc de duplicar el conjunt.

Solució 3. Amb el percentil 95, el llindar baixa (per construcció, el 5 % de les comandes normals queda per sobre), així que les falses alarmes pugen de l'1 % al 5 % (unes 150 comandes de 3.000) i les 30 anòmales continuen detectant-se (el seu error, al voltant de 8, és molt per sobre de qualsevol dels dos llindars). És l'intercanvi precisió-recall de 04-05: el llindar es tria per cost, i aquí un 5 % de revisions manuals seria probablement excessiu per a un benefici nul. Si les anòmales es barregen a l'entrenament, l'autoencoder aprèn també a reconstruir-les (només són 30 entre 3.000, així que les reconstruirà una mica pitjor que les normals, però millor que si no les hagués vist mai): el seu error baixa, algunes cauen per sota del llindar i la detecció empitjora. Per això els autoencoders d'anomalies s'entrenen amb dades tan "netes" com sigui possible, o s'accepta que només detecten el que és molt rar.

Conclusió

Hem definit el deep learning com a xarxes de moltes capes que aprenen representacions jeràrquiques (vores → parts → objectes), i hem explicat el seu enlairament el 2012 per la confluència de dades (ImageNet), GPU, ReLU i frameworks. Hem obert les xarxes convolucionals: la convolució com a filtre lliscant (calculada a mà: el detector de vores verticals sobre la caixa de 5×5), el pooling i els mapes de característiques, i les hem vist guanyar a les fotos sintètiques d'incidències de NovaMarket (98,7 % d'encert amb 9.538 paràmetres, davant del 57 % d'un MLP amb més paràmetres). Hem presentat les recurrents amb el seu estat ocult i les comportes de LSTM/GRU per a seqüències llargues, els autoencoders que detecten comandes anòmales pel seu error de reconstrucció, i la transferència d'aprenentatge, la pràctica d'adaptar models preentrenats en lloc d'entrenar des de zero. El panorama d'aplicacions i la llista de costos i límits (dades etiquetades, còmput, opacitat, fragilitat, biaix) completen el quadre que la Marta necessita per decidir amb el Diego on val la pena una xarxa profunda.

Queda la dada més important per a NovaMarket, el text: les ressenyes de ressenyes.csv i l'assistent d'atenció al client. Les recurrents el llegien paraula a paraula i oblidaven; des del 2017 ho fa una arquitectura diferent, basada en l'atenció, que ha acabat dominant també imatges i àudio i ha donat lloc als grans models de llenguatge. És el tema de l'última lliçó del mòdul: Transformers, Grans Models de Llenguatge i IA Generativa.

Fonaments d'Intel·ligència Artificial (IA)

Mòdul 1: Introducció a la Intel·ligència Artificial

Mòdul 2: Principis Bàsics de la IA

Mòdul 3: Algorismes en IA

Mòdul 4: Aprenentatge Automàtic (Machine Learning)

Mòdul 5: Xarxes Neuronals i Deep Learning

Mòdul 6: Lògica i Sistemes Experts

Mòdul 7: Eines i Llenguatges de Programació en IA

Mòdul 8: Projectes i Casos d'Estudi

Mòdul 9: Exercicis i Pràctiques

Mòdul 10: Recursos Addicionals

© Copyright 2026. Tots els drets reservats