A 05-01 vam veure que una neurona sola traça una recta i que apilar neurones en capes trenca aquest límit. Ara toca la pregunta pràctica que la Marta es fa davant del portàtil: quantes capes, quantes neurones, quina funció d'activació, quina sortida? Aquestes decisions són l'arquitectura de la xarxa, i són els hiperparàmetres més importants del deep learning. En aquesta lliçó desmuntem un perceptró multicapa (MLP) peça a peça: capes denses, amplada i profunditat, com comptar paràmetres a mà; les funcions d'activació modernes (ReLU i la seva família, softmax) i per què la sigmoide es va deixar d'usar a les capes ocultes (el gradient que s'esvaeix, a nivell intuïtiu); com triar la capa de sortida i la funció de pèrdua segons el problema; i com representar les entrades, amb els embeddings com a idea clau per a text i productes. Tancarem amb un mapa de les famílies d'arquitectures (convolucionals, recurrents, transformers, autoencoders) que 05-04 i 05-05 desenvolupen, i amb codi: construirem en PyTorch l'MLP del predictor de devolucions de NovaMarket sobre les 21 columnes preparades al mòdul 4, en comptarem els paràmetres i li farem una predicció sense entrenar. És important perquè l'arquitectura fixa el que la xarxa pot aprendre: una mala elecció no s'arregla amb més èpoques.

Contingut

  1. Anatomia d'un perceptró multicapa: capes denses, amplada i profunditat
  2. Comptar paràmetres a mà: 21 → 16 → 8 → 1
  3. Funcions d'activació: sigmoide, tanh, ReLU i variants, softmax
  4. El gradient que s'esvaeix (intuïció) i per què ReLU
  5. Capa de sortida i funció de pèrdua segons el problema
  6. Com representar les entrades: numèriques, categòriques i embeddings
  7. Panorama de famílies d'arquitectures
  8. Codi: l'MLP del predictor de devolucions en PyTorch
  9. Errors Comuns i Consells
  10. Exercicis
  11. Conclusió

  1. Anatomia d'un perceptró multicapa: capes denses, amplada i profunditat

Un perceptró multicapa (MLP, multilayer perceptron) és la xarxa de 05-01 generalitzada: una capa d'entrada, una o més capes ocultes denses (cada neurona connectada a totes les sortides de la capa anterior) i una capa de sortida. Cada capa densa calcula, per a totes les seves neurones alhora, h = f(W · x + b), on W és una matriu amb una fila per neurona i una columna per entrada, b un vector de biaixos i f l'activació aplicada element a element. És la mateixa neurona de 05-01, escrita en forma matricial perquè l'ordinador la calculi de cop.

Dues dimensions descriuen la forma d'un MLP:

  • Amplada: quantes neurones té cada capa. Més neurones = més "esglaons" per dibuixar la funció (l'aproximador universal de 05-01), i més paràmetres.
  • Profunditat: quantes capes ocultes hi ha. Cada capa reescriu la sortida de l'anterior, així que una xarxa profunda compon transformacions simples en una de complexa: la primera capa detecta trets elementals, la següent combinacions de trets, etc. Amb la mateixa quantitat de paràmetres, la profunditat sol ser més eficient que l'amplada per a funcions complexes; i és el que dona nom al deep learning (05-04).
Decisió Efecte d'apujar-la Efecte d'abaixar-la Regla pràctica de partida
Amplada (neurones per capa) Més capacitat, més paràmetres, més risc de sobreajust Pot subajustar Potències de 2 entre 8 i 512; decreixent cap a la sortida ("embut")
Profunditat (capes ocultes) Representacions més abstractes; més difícil d'entrenar (secció 4) Menys capacitat de composició 1-3 capes per a dades tabulars; desenes o centenars en visió i llenguatge
Paràmetres totals De l'ordre dels exemples d'entrenament o menys, llevat que hi hagi regularització forta (05-03)

Per al predictor de devolucions de NovaMarket (2.249 comandes d'entrenament, 21 columnes) farem servir un embut modest: 21 → 16 → 8 → 1.

  1. Comptar paràmetres a mà: 21 → 16 → 8 → 1

Cada capa densa amb n_in entrades i n_out neurones té n_in × n_out pesos més n_out biaixos. Comptem:

Capa Entrades Neurones Pesos Biaixos Paràmetres
Oculta 1 21 16 21 × 16 = 336 16 352
Oculta 2 16 8 16 × 8 = 128 8 136
Sortida 8 1 8 × 1 = 8 1 9
Total 497

Davant dels 22 paràmetres de la regressió logística (21 pesos + 1 biaix) són 22 vegades més, i tot i així és una xarxa diminuta: un model de visió típic en té desenes de milions i un gran model de llenguatge, milers de milions. Saber comptar paràmetres serveix per a tres coses: estimar la memòria (cada paràmetre és un nombre de 32 bits, 4 bytes: 497 paràmetres ocupen 2 KB; 7.000 milions, 28 GB), estimar el risc de sobreajust (497 paràmetres per a 2.249 exemples és raonable; 50.000 no ho seria sense molta regularització) i detectar errors en construir la xarxa (si PyTorch diu un nombre diferent del que has calculat, alguna cosa no està connectada com et penses).

  1. Funcions d'activació: sigmoide, tanh, ReLU i variants, softmax

L'activació de les capes ocultes és el que aporta la no linealitat (sense ella, 05-01, la xarxa col·lapsa en un model lineal). Les opcions principals:

Funció Fórmula Rang Valors a z = −3, −1, 0, 1, 3 Ús avui
Sigmoide 1 / (1 + e^(−z)) (0, 1) 0,047; 0,269; 0,5; 0,731; 0,953 Només a la sortida de classificació binària
Tanh (e^z − e^(−z)) / (e^z + e^(−z)) (−1, 1) −0,995; −0,762; 0; 0,762; 0,995 Recurrents (05-04); centrada a 0, millor que la sigmoide a les ocultes
ReLU max(0, z) [0, ∞) 0; 0; 0; 1; 3 Per defecte a les capes ocultes
Leaky ReLU z si z > 0; 0,01·z altrament (−∞, ∞) −0,03; −0,01; 0; 1; 3 Quan moltes ReLU "moren" (secció 4)
ELU / GELU / SiLU Variants suaus de ReLU ≈ (−1, ∞) GELU és l'habitual als transformers (05-05)
Softmax e^(zᵢ) / Σⱼ e^(zⱼ) (sobre un vector) Cada sortida a (0, 1), sumen 1 Vegeu l'exemple Sortida de classificació multiclasse

Observacions:

  • La sigmoide i la tanh se saturen: per a |z| > 3 la sortida ja gairebé no canvia (0,953 → 0,999...). Això les fa dolentes per a capes ocultes, com veurem a la secció 4.
  • La ReLU (rectified linear unit) és d'una simplicitat gairebé ofensiva: deixa passar els positius i anul·la els negatius. És barata de calcular, no se satura per la dreta i el seu pendent és exactament 1 per a z > 0. Des del 2012 és l'activació per defecte de les capes ocultes.
  • La softmax no és una activació per neurona sinó sobre un vector: converteix k nombres qualssevol (anomenats logits) en k probabilitats que sumen 1, exagerant les diferències. Exemple amb tres classes i z = (2, 1, −1): les exponencials són e² = 7,389, e¹ = 2,718, e⁻¹ = 0,368, que sumen 10,475; dividint, softmax = (0,705; 0,259; 0,035). La classe amb el logit més gran s'endú la probabilitat més alta; si sumes una constant a tots els logits el resultat no canvia. Amb dues classes, la softmax equival a la sigmoide.

  1. El gradient que s'esvaeix (intuïció) i per què ReLU

A 05-03 veurem que la xarxa aprèn calculant el pendent de la pèrdua respecte de cada pes, i que aquest pendent s'obté multiplicant, capa a capa des de la sortida cap enrere, els pendents de cada funció que travessa el senyal. Aquí n'hi ha prou amb la intuïció numèrica:

  • El pendent de la sigmoide és σ(z)·(1 − σ(z)), que val com a màxim 0,25 (a z = 0) i cau ràpidament: a z = 2 és 0,105 i a z = 5, 0,0066. En una xarxa de 10 capes amb sigmoide, en el millor dels casos el pendent que arriba a la primera capa s'ha multiplicat per 0,25¹⁰ ≈ 0,000001; a la pràctica, molt menys, perquè gairebé cap neurona és a z = 0. Les primeres capes reben un senyal de correcció gairebé nul: no aprenen. És el problema del gradient que s'esvaeix (vanishing gradient), i és una de les raons per les quals als anys 90 les xarxes es quedaven en dues o tres capes.
  • El pendent de la ReLU és 1 per a z > 0 i 0 per a z < 0. Multiplicar uns no redueix res: el senyal arriba intacte a les capes profundes pels camins actius. Això, juntament amb més dades i GPU, és el que va permetre entrenar xarxes de desenes de capes a partir del 2012 (05-04).

La ReLU té el seu propi risc: una neurona amb z negativa per a tots els exemples retorna sempre 0 i el seu pendent també és 0, així que no es torna a actualitzar mai més ("ReLU morta"). Sol passar amb taxes d'aprenentatge massa altes; Leaky ReLU i ELU ho eviten deixant passar un petit pendent en els negatius. Regla pràctica: ReLU a les ocultes; si veus moltes neurones sempre a zero, prova Leaky ReLU o abaixa la taxa d'aprenentatge.

  1. Capa de sortida i funció de pèrdua segons el problema

La capa de sortida i la funció de pèrdua (04-01: el nombre que l'entrenament minimitza) van sempre en parella i les dicta el tipus de problema:

Problema Neurones de sortida Activació de sortida Pèrdua Exemple NovaMarket
Classificació binària 1 Sigmoide Entropia creuada binària (BCE, la pèrdua logarítmica de 04-01) Retornat / no retornat; ressenya positiva / negativa; foto de paquet danyat / correcte
Classificació multiclasse (una sola classe correcta) k (una per classe) Softmax Entropia creuada (categòrica) Motiu de devolució (4 classes); categoria d'una incidència
Classificació multietiqueta (diverses alhora) k Sigmoide a cadascuna BCE per sortida Etiquetes d'una ressenya: "preu", "enviament", "qualitat"
Regressió 1 (o diverses) Cap (lineal) Error quadràtic mitjà (MSE) o MAE Unitats del NovaClean la setmana vinent; dies fins al lliurament

L'entropia creuada binària per a un exemple amb etiqueta y i probabilitat predita p és −[y·log(p) + (1 − y)·log(1 − p)]. Si la comanda es va retornar (y = 1) i la xarxa va dir p = 0,9, la pèrdua és −log(0,9) = 0,105; si va dir p = 0,5, 0,693; si va dir p = 0,1, 2,303. Castiga molt la confiança equivocada, exactament com a la regressió logística. Un detall d'implementació que veuràs a 05-03: PyTorch ofereix nn.BCEWithLogitsLoss, que ajunta la sigmoide i la BCE en una operació numèricament més estable; amb ella la capa de sortida es deixa sense sigmoide i s'aplica després només per llegir probabilitats. En aquesta lliçó, perquè la sortida sigui llegible, mantenim la sigmoide explícita.

  1. Com representar les entrades: numèriques, categòriques i embeddings

Una xarxa només menja nombres en un rang raonable, així que la preparació de 04-03 continua vigent i és fins i tot més crítica:

  • Numèriques: estandarditzades (mitjana 0, desviació 1) o escalades a [0, 1]. Sense escalar, les columnes grans dominen les sumes ponderades i l'entrenament es torna inestable (ho vam veure amb distancia a 05-01). Reutilitzarem tal qual el ColumnTransformer del mòdul 4.
  • Binàries: 0/1 tal qual.
  • Categòriques amb poques categories: one-hot (una columna per categoria), com categoria o metode_pagament al mòdul 4.
  • Categòriques amb moltes categories (els 12.000 productes de NovaMarket, les paraules d'una llengua, els codis postals): el one-hot és inviable (12.000 columnes gairebé totes a zero) i, a més, tracta totes les categories com si fossin igual de diferents entre si. La solució del deep learning és l'embedding: assignar a cada categoria un vector dens de poques dimensions (per exemple 8 o 64) els valors del qual són paràmetres que la xarxa aprèn juntament amb la resta. Després de l'entrenament, categories que es comporten de manera semblant acaben amb vectors semblants: el NovaClean i un altre robot aspirador quedaran a prop; "excel·lent" i "genial" també.
import torch, torch.nn as nn

taula = nn.Embedding(num_embeddings=12000, embedding_dim=8)   # 12.000 productes -> vectors de 8
print(taula.weight.shape)                                       # torch.Size([12000, 8]): 96.000 parametres
ids = torch.tensor([3, 4587])                                   # dos productes pel seu index
print(taula(ids).shape)                                         # torch.Size([2, 8]): el seu vector cadascun

nn.Embedding és literalment una taula de consulta: fila i = vector del producte i. Al principi és aleatòria; l'entrenament la va movent. La idea és central en recomanació (cas d'ús 1: client i producte com a embeddings el producte escalar dels quals prediu l'afinitat, 05-04) i en llenguatge (cada paraula o token és un embedding; és la primera capa de qualsevol transformer, 05-05).

  1. Panorama de famílies d'arquitectures

L'MLP és l'arquitectura "genèrica". Per a cada tipus de dada ha sorgit una família que incorpora supòsits sobre l'estructura de les dades i per això aprèn amb molts menys paràmetres i exemples:

flowchart TD
    RN["Xarxes neuronals"] --> MLP["MLP / denses<br/>dades tabulars<br/>(aquesta lliçó i 05-03)"]
    RN --> CNN["Convolucionals (CNN)<br/>imatges, senyals<br/>fotos d'incidències (05-04)"]
    RN --> RNN["Recurrents (RNN, LSTM, GRU)<br/>seqüències, sèries temporals<br/>demanda setmanal (05-04)"]
    RN --> AE["Autoencoders<br/>compressió, anomalies<br/>frau (05-04)"]
    RN --> TR["Transformers<br/>text, i avui gairebé tot<br/>ressenyes, assistent (05-05)"]
Família Supòsit que incorpora Dada típica Lliçó
MLP (densa) Cap: cada entrada és independent Taula de columnes 05-02, 05-03
Convolucional Els patrons són locals i es repeteixen a qualsevol posició Imatges, àudio, sèries 05-04
Recurrent L'ordre importa; hi ha un estat que s'arrossega Sèries temporals, text (històric) 05-04
Autoencoder Les dades viuen en un espai de menys dimensions Qualsevol (sense etiquetes) 05-04
Transformer Cada element ha de "mirar" tots els altres (atenció) Text, imatges, àudio, codi 05-05

Totes comparteixen els ingredients d'aquesta lliçó: capes de neurones, activacions ReLU o similars, una capa de sortida amb la seva pèrdua i embeddings per al que és categòric. Canvien en com es connecten les neurones.

  1. Codi: l'MLP del predictor de devolucions en PyTorch

Reutilitzem la preparació del mòdul 4 (generar_comandes_ml, embrutar_comandes, preparar_comandes i crear_preparacio de novamarket_ml.py, que produeixen les 21 columnes) i construïm la xarxa 21 → 16 → 8 → 1.

import numpy as np
import torch
import torch.nn as nn
from sklearn.model_selection import train_test_split
from novamarket_ml import generar_comandes_ml, embrutar_comandes, preparar_comandes, crear_preparacio

# 1. Dades: la mateixa divisio de 04-05 (750 comandes de test)
X, y = preparar_comandes(embrutar_comandes(generar_comandes_ml(3000, 42), 42))
Xtr, Xte, ytr, yte = train_test_split(X, y, test_size=0.25, random_state=42, stratify=y)
prep = crear_preparacio().fit(Xtr)                  # ajusta imputacio, escalat i one-hot NOMES amb train
Xtr_m = prep.transform(Xtr).astype(np.float32)      # matriu numpy 2249 x 21, en float32 (el que fa servir PyTorch)
Xte_m = prep.transform(Xte).astype(np.float32)
print(Xtr_m.shape, Xte_m.shape)

# 2. Arquitectura
torch.manual_seed(42)                                # els pesos inicials son aleatoris: fixem la llavor
xarxa = nn.Sequential(
    nn.Linear(21, 16), nn.ReLU(),                    # capa oculta 1: 21 entrades -> 16 neurones, ReLU
    nn.Linear(16, 8),  nn.ReLU(),                    # capa oculta 2: 16 -> 8, ReLU
    nn.Linear(8, 1),   nn.Sigmoid())                 # sortida: 8 -> 1 probabilitat de devolucio
print(xarxa)

# 3. Parametres
for nom, p in xarxa.named_parameters():
    print(f"{nom:10s} {str(tuple(p.shape)):10s} {p.numel():4d}")
print("Total:", sum(p.numel() for p in xarxa.parameters()))

Sortida:

(2249, 21) (750, 21)
Sequential(
  (0): Linear(in_features=21, out_features=16, bias=True)
  (1): ReLU()
  (2): Linear(in_features=16, out_features=8, bias=True)
  (3): ReLU()
  (4): Linear(in_features=8, out_features=1, bias=True)
  (5): Sigmoid()
)
0.weight   (16, 21)    336
0.bias     (16,)        16
2.weight   (8, 16)     128
2.bias     (8,)          8
4.weight   (1, 8)        8
4.bias     (1,)          1
Total: 497

Explicació: nn.Linear(21, 16) crea la matriu W de 16 × 21 (PyTorch desa una fila per neurona) i el vector b de 16; named_parameters() recorre tots els tensors entrenables, i el compte coincideix amb la taula de la secció 2 (497). Els índexs 0, 2, 4 són les posicions dins del Sequential (les activacions ocupen 1, 3, 5 i no tenen paràmetres).

Una funció petita que imprimeix l'arquitectura amb el seu recompte (útil per revisar qualsevol Sequential):

def resum(xarxa):
    print(f"{'capa':<10}{'entrada':>8}{'sortida':>8}{'parametres':>12}")
    total = 0
    for i, capa in enumerate(xarxa):
        if isinstance(capa, nn.Linear):
            n = capa.in_features * capa.out_features + capa.out_features
            total += n
            print(f"Linear {i:<3}{capa.in_features:>8}{capa.out_features:>8}{n:>12}")
        else:
            print(f"{capa.__class__.__name__:<10}{'':>8}{'':>8}{0:>12}")
    print(f"{'TOTAL':<10}{'':>8}{'':>8}{total:>12}")

resum(xarxa)

Sortida:

capa       entrada sortida  parametres
Linear 0        21      16         352
ReLU                                 0
Linear 2        16       8         136
ReLU                                 0
Linear 4         8       1           9
Sigmoid                              0
TOTAL                              497

Ara el pas cap endavant (forward): passem cinc comandes de test per la xarxa sense haver-la entrenat:

from sklearn.metrics import roc_auc_score

X_t = torch.tensor(Xte_m[:5])                        # numpy -> tensor de PyTorch (5 x 21)
with torch.no_grad():                                # encara no necessitem pendents
    prob = xarxa(X_t)                                # forward: aplica les 6 peces en ordre
print("Probabilitats:", prob.numpy().ravel().round(3), " reals:", yte.values[:5])

with torch.no_grad():
    totes = xarxa(torch.tensor(Xte_m)).numpy().ravel()
print("Mitjana:", totes.mean().round(3), " min:", totes.min().round(3), " max:", totes.max().round(3))
print("AUC sense entrenar:", round(roc_auc_score(yte, totes), 3))

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

Probabilitats: [0.546 0.547 0.54  0.558 0.549]  reals: [0 1 0 0 1]
Mitjana: 0.551  min: 0.531  max: 0.605
AUC sense entrenar: 0.517

Lectura: la xarxa no sap res. Amb pesos aleatoris petits, totes les z de sortida ronden el 0 i la sigmoide retorna ≈ 0,55 per a totes les comandes; l'AUC de 0,517 és el d'una moneda (0,5). Podem mirar a dins per veure el flux d'una comanda:

with torch.no_grad():
    z1 = xarxa[0](X_t[:1])          # suma ponderada de la capa 1 (16 valors)
    h1 = xarxa[1](z1)               # despres de ReLU: els negatius s'anul·len
    h2 = xarxa[3](xarxa[2](h1))     # capa 2 + ReLU (8 valors)
    z3 = xarxa[4](h2)               # logit de sortida
print("z1:", z1.numpy().round(2))
print("h1:", h1.numpy().round(2))
print("h2:", h2.numpy().round(2))
print("z3:", z3.numpy().round(3), " sigmoide:", torch.sigmoid(z3).numpy().round(3))

Sortida:

z1: [[-0.2   0.03  0.51 -0.63 -0.01 -0.71 -0.   -0.78 -0.31 -0.13 -0.34 -0.46  0.34 -0.64 -0.21  0.21]]
h1: [[0.   0.03 0.51 0.   0.   0.   0.   0.   0.   0.   0.   0.   0.34 0.    0.    0.21]]
h2: [[0.01 0.12 0.   0.11 0.   0.   0.07 0.  ]]
z3: [[0.187]]  sigmoide: [[0.546]]

Es veu la ReLU en acció: de les 16 sumes ponderades de la primera capa, 12 eren negatives i queden a 0; només 4 neurones "parlen" per a aquesta comanda. A la segona capa, 4 de 8. És normal (i desitjable: representacions disperses), sempre que no siguin sempre les mateixes neurones per a totes les comandes (ReLU mortes). Els pesos concrets (xarxa[0].weight[0, :5] dona una cosa com [0.167, 0.181, -0.051, 0.2, -0.048]) encara no signifiquen res: són el punt de partida aleatori del descens que farem a 05-03.

Errors Comuns i Consells

  • Sigmoide a les capes ocultes. És el reflex natural després del mòdul 4, però provoca el gradient que s'esvaeix. Reserva la sigmoide per a la sortida binària; ReLU (o Leaky ReLU/GELU) a les ocultes.
  • Softmax amb una sola neurona, o sigmoide amb diverses classes excloents. La softmax d'un sol valor és sempre 1; i per a "motiu de devolució" (una classe entre quatre) les sigmoides independents poden donar 0,9 a dues classes alhora. Respecta la taula de la secció 5.
  • Aparellar malament sortida i pèrdua. Sigmoide + MSE entrena malament (la pèrdua s'aplana a les zones saturades); fes servir BCE. I no apliquis la sigmoide dues vegades (una a la xarxa i una altra dins de BCEWithLogitsLoss).
  • Oblidar l'escalat. Amb entrades en escales dispars, ReLU i descens del gradient es comporten malament. Reutilitza el ColumnTransformer de 04-03 i ajusta'l només amb entrenament.
  • Sobredimensionar per defecte. 3 capes de 512 neurones per a 2.249 comandes són gairebé 400.000 paràmetres: memoritzarà l'entrenament. Comença petit (com 21 → 16 → 8 → 1) i creix només si la validació ho demana (04-06).
  • Refiar-se de la sortida abans d'entrenar. Com acabem de veure, la xarxa retorna ≈ 0,55 per a tot; una arquitectura correcta no és un model. Fins a 05-03 no hi ha predicció.

Exercicis

Exercici 1. Calcula a mà els paràmetres d'una xarxa 21 → 32 → 16 → 8 → 1 (totes denses, ReLU a les ocultes, sigmoide a la sortida). Construeix-la amb nn.Sequential, comprova la xifra amb resum i compara-la amb el nombre de comandes d'entrenament (2.249). Et sembla prudent sense regularització?

Exercici 2. Substitueix la sortida nn.Linear(8, 1), nn.Sigmoid() per nn.Linear(8, 2) seguida de torch.softmax(..., dim=1) (dues neurones: "no retornat" i "retornat"). Compta els paràmetres i comprova que les dues probabilitats sumen 1 per a qualsevol comanda. És una xarxa diferent de la binària amb sigmoide? Quina pèrdua li correspondria segons la taula de la secció 5?

Exercici 3. Per a cada problema de NovaMarket, indica el nombre de neurones de sortida, l'activació de sortida, la pèrdua i com representaries l'entrada principal: (a) predir la valoració d'1 a 5 estrelles d'una ressenya a partir del text; (b) predir les unitats setmanals del NovaClean a partir de les 8 setmanes anteriors; (c) predir el motiu de devolució (4 categories) a partir de les 21 columnes de la comanda més l'identificador del producte (12.000 valors).

Solucions

Solució 1. 21×32 + 32 = 704; 32×16 + 16 = 528; 16×8 + 8 = 136; 8×1 + 1 = 9; total 1.377, i resum ho confirma. Són 0,6 paràmetres per exemple d'entrenament: manejable, però ja de l'ordre en què convé fer servir aturada anticipada i dropout (05-03); amb la xarxa de 497 tenim marge i per això la vam triar.

Solució 2. La xarxa té 497 − 9 + (8×2 + 2) = 506 paràmetres. Amb torch.softmax(xarxa2(x), dim=1) obtens, per exemple, [[0.535 0.465]] per a una comanda: sumen 1. Matemàticament és equivalent a la binària amb sigmoide (la softmax de dos logits z₀, z₁ és la sigmoide de z₁ − z₀), només que amb un paràmetre redundant per entrada de l'última capa. Li correspondria l'entropia creuada categòrica (nn.CrossEntropyLoss, que en PyTorch inclou la softmax). A la pràctica, per a problemes binaris es fa servir la versió d'una neurona.

Solució 3. (a) 5 neurones, softmax, entropia creuada categòrica; l'entrada, el text, es representa com a seqüència d'embeddings de paraules (o, com a línia base, bossa de paraules: 05-05). Alternativa raonable: tractar-ho com a regressió d'1 a 5 amb sortida lineal + MSE, si importa "quant" s'equivoca (predir 4 quan era 5 és menys greu que predir 1). (b) 1 neurona, sortida lineal, MSE o MAE; entrada: les 8 unitats anteriors estandarditzades (un MLP de 8 entrades o, millor, una xarxa recurrent que respecti l'ordre, 05-04). (c) 4 neurones, softmax, entropia creuada; les 21 columnes del ColumnTransformer concatenades amb un nn.Embedding(12000, 8) del producte (8 dimensions apreses en lloc de 12.000 columnes one-hot).

Conclusió

Hem desmuntat l'arquitectura d'un perceptró multicapa: capes denses que calculen f(W·x + b), l'amplada i la profunditat com a decisions de disseny, i el recompte de paràmetres a mà (21 → 16 → 8 → 1 = 497, davant dels 22 de la logística). Hem comparat les funcions d'activació i entès per què la ReLU va substituir la sigmoide a les capes ocultes: la sigmoide se satura i el seu pendent màxim de 0,25 fa que el senyal de correcció s'esvaeixi en xarxes profundes, mentre que la ReLU el transmet intacte. Hem aparellat capa de sortida i pèrdua segons el problema (sigmoide + BCE, softmax + entropia creuada, lineal + MSE), repassat com representar les entrades i presentat els embeddings com la manera de donar vectors apresos a productes i paraules. I hem construït en PyTorch l'MLP del predictor de devolucions de NovaMarket sobre les 21 columnes del mòdul 4, n'hem comptat els paràmetres i hem inspeccionat un forward: amb pesos aleatoris, la xarxa diu ≈ 0,55 a tot i el seu AUC és 0,517. La xarxa no sap res encara.

A la lliçó següent, Com Aprèn una Xarxa: Descens del Gradient i Retropropagació, li ensenyarem: veurem la pèrdua com un paisatge del qual ara sí que coneixem el pendent, el descens del gradient pas a pas, la regla de la cadena que reparteix l'error cap enrere capa a capa, i escriurem el bucle d'entrenament complet en PyTorch (DataLoader, Adam, èpoques, aturada anticipada i dropout) per comprovar si aquesta xarxa de 497 paràmetres millora, o no, el 0,844 d'AUC de la regressió logística.

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