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
- Què fa "profund" el deep learning i per què va enlairar-se
- Aprenentatge de representacions jeràrquiques
- Xarxes convolucionals: convolució, filtres, pooling i mapes de característiques
- Codi: una CNN per a les fotos d'incidències de NovaMarket
- Xarxes recurrents: seqüències, estat ocult, LSTM i GRU
- Autoencoders i detecció d'anomalies
- Transferència d'aprenentatge i models preentrenats
- Panorama d'aplicacions
- Costos i límits
- Errors Comuns i Consells
- Exercicis
- Conclusió
- 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.
- 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.
- 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):
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).
- 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).
- 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.
- 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.
- 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".
- 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.
- 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 ambbatch_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
- Conceptes Fonamentals: Agents, Entorns i Racionalitat
- Tipus d'Intel·ligència Artificial
- Les Dades com a Matèria Primera de la IA
- Ètica i Consideracions en IA
Mòdul 3: Algorismes en IA
- Introducció als Algorismes
- Algorismes de Cerca
- Cerca amb Adversari: Jocs i Minimax
- Algorismes d'Optimització
Mòdul 4: Aprenentatge Automàtic (Machine Learning)
- Conceptes Bàsics de Machine Learning
- Tipus d'Aprenentatge Automàtic
- Preparació de Dades i Característiques
- Algorismes de Machine Learning
- Avaluació i Validació de Models
- Sobreajust, Regularització i Ajust d'Hiperparàmetres
Mòdul 5: Xarxes Neuronals i Deep Learning
- Introducció a les Xarxes Neuronals
- Arquitectura de Xarxes Neuronals
- Com Aprèn una Xarxa: Descens del Gradient i Retropropagació
- Deep Learning i les seves Aplicacions
- Transformers, Grans Models de Llenguatge i IA Generativa
Mòdul 6: Lògica i Sistemes Experts
- Lògica en IA
- Sistemes Experts
- Raonament amb Incertesa: Probabilitat i Xarxes Bayesianes
- Aplicacions dels Sistemes Experts
Mòdul 7: Eines i Llenguatges de Programació en IA
- Llenguatges de Programació per a IA
- Python Científic: NumPy, pandas i Matplotlib
- Eines i Llibreries Populars
- Entorns de Desenvolupament
Mòdul 8: Projectes i Casos d'Estudi
Mòdul 9: Exercicis i Pràctiques
- Exercicis d'Algorismes
- Pràctiques de Machine Learning
- Projectes de Xarxes Neuronals
- Projecte Integrador: de la Idea al Prototip
