martedì 17 giugno 2025

Corso sulla Struttura dell’Intelligenza Artificiale: Architetture complesse: dai layer alla logica modulare


Architetture complesse: dai layer alla logica modulare

Perché “architetture complesse”?

Quando i problemi crescono di difficoltà (linguaggio naturale, visione, serie temporali multivariate), non basta una rete “piatta”. Serve costruire modelli componibili, con blocchi riutilizzabili, che separano le responsabilità: estrazione di feature, memorie a lungo raggio, ragionamento sequenziale, generazione. Questo modulo insegna come passare dai singoli layer a moduli più ricchi – e come assemblarli in pipeline robuste.


1) Layer base: mattoni fondamentali

I layer sono le unità minime di calcolo. Conoscerne comportamenti e limiti è cruciale per non “abusare” della profondità o scegliere attivazioni/normalizzazioni inadatte.

  • Dense (fully connected): proiezioni lineari con attivazione non lineare (ReLU, GELU, SiLU). Ottimi come head finali o per integrare feature eterogenee.
  • Convolutional (Conv): estraggono pattern locali con condivisione dei pesi. Varianti utili: depthwise separable, dilated, residual. Nati per immagini, efficaci anche su sequenze 1D.
  • Ricorrenti (LSTM/GRU): gestiscono dipendenze temporali. Le LSTM eccellono su contesti lunghi; le GRU sono più leggere con prestazioni simili.
  • Transformer block: stack di Multi-Head Self-Attention (MHSA) + Feed-Forward Network (FFN), con residual + LayerNorm. Cattura dipendenze lunghe in parallelo.
<!-- Esempio di “blocco” astratto -->
Input → [Normalizzazione] → [Operazione principale] → [Dropout] → (+ Residual) → Output

Nota pratica: Normalizzazione prima del blocco (pre-norm) tende a stabilizzare il training di modelli molto profondi; il residuo riduce il rischio di vanishing gradient.


2) Dalla collezione di layer alla logica modulare

Un’architettura complessa non è solo “più layer”: è composizione. Si definiscono moduli con un’API chiara e testabile, che possono essere riutilizzati in punti diversi della rete.

  • Blocchi ripetibili: es. “ConvBlock(k, s)” con Conv → Norm → Attivazione → Dropout; “TransformerBlock(h, d)” con MHSA → FFN → Residual/Norm.
  • Percorsi paralleli (inception-like): più rami con kernel/attività diverse, poi concatenazione: migliore copertura di scale differenti.
  • Skip/Residual multi-scala: collegamenti tra livelli lontani per preservare dettagli (U-Net in segmentazione, encoder–decoder in NLP).
  • Conditioning: iniezione di segnali esterni (classe/tempo/contesto) nei blocchi tramite concatenazione, gating o attenzione condizionata.
<!-- Pseudocodice di un modulo riutilizzabile -->
def TransformerBlock(x):
x_norm = LayerNorm(x)
x_attn = MultiHeadAttention(x_norm, x_norm)
x = x + Dropout(x_attn) # residual
y_norm = LayerNorm(x)
y_ffn = FFN(y_norm)
y = x + Dropout(y_ffn) # residual
return y

3) Strutture moderne: encoder–decoder, attention, embedding

  • Embedding: mappa token/ID in vettori densi. Fondamentali in NLP; analoghi per categorie in tabellari. Si può includere positional encoding (sinusoidale o learnable) per preservare l’ordine.
  • Attention/MHSA: meccanismo che assegna pesi Query–Key–Value alle relazioni tra elementi. Multi-head = sotto-spazi diversi in parallelo.
  • Encoder–Decoder:
    • Encoder: comprime l’input in rappresentazioni contestualizzate (BERT-like).
    • Decoder: genera output condizionato all’encoder (traduzione, riassunto) o in modo autoregressivo (GPT-like).
    • Cross-attention: il decoder “guarda” l’encoder per ogni passo di generazione.

Scelte progettuali chiave

  • Maschere di attenzione: causale (no “sbirciare” il futuro) per generazione; bidirezionale per comprensione.
  • Label smoothing: regolarizza la classificazione su vocabolari grandi.
  • Ottimizzazione: AdamW + scheduler con warmup lineare spesso accelera la convergenza.

4) Dataset sequenziali e input testuali

Il successo di un’architettura complessa dipende dalla corretta preparazione del dato.

  • Tokenizzazione: BPE/WordPiece alleviano out-of-vocabulary e mantengono compattezza. Conservare special tokens (PAD, BOS, EOS, SEP).
  • Padding & masking: batch di lunghezze uniformi, con maschere per ignorare il padding nell’attenzione e nella loss.
  • Bilanciamento: shuffling, pesi di classe, sampling per evitare bias di frequenza.
  • Serie temporali: finestre scorrevoli, lookback/horizon, normalizzazione per feature (z-score/min-max), gestione di “missing” (imputazione, maschere).
  • Data leakage: attenti a non usare informazioni future in addestramento (split temporale rigoroso).

5) Pattern di addestramento stabili

  • Inizializzazione & attivazioni: He (ReLU/SiLU), Xavier (tanh); evitare saturazioni; LayerNorm/BatchNorm dove appropriato.
  • Regolarizzazione: dropout (attenzione e FFN), weight decay, early stopping, stochastic depth in reti profonde.
  • Gradiente: clip del gradiente su RNN/Transformer (specie con sequenze lunghe); mixed precision per velocità/memoria.
  • Curriculum & teacher forcing: per modelli autoregressivi; scheduled sampling per ridurre esposizione a distribuzioni diverse tra train/test.

6) Valutazione e metriche

  • Classificazione: accuracy, F1 (macro/micro), AUC; matrici di confusione per classi sbilanciate.
  • Generazione testo: perplexity, BLEU/ROUGE/METEOR; analisi qualitativa (allucinazioni, ripetizioni, coerenza).
  • Serie temporali: MAE/MSE/RMSE, MAPE; backtesting a più orizzonti (rolling window).

7) Laboratorio: Progettare un piccolo encoder–decoder per generazione frasi

Obiettivo: costruire un modello che generi frasi di risposta data un’istruzione breve (mini traduzione o dialogo toy).

Dataset suggeriti

  • Tatoeba o coppie frase–frase semplificate (es. “it → en” ridotto) oppure un dataset custom di prompt–risposta (1000–5000 esempi bastano per il prototipo).

Passi operativi

  1. Preprocessing: tokenizzazione subword (BPE/WordPiece), definizione vocabolario, aggiunta di BOS/EOS, padding/truncation; split train/val/test.
  2. Embedding & Positional Encoding: dimensione embed 128–256; posizionale sinusoidale o learnable.
  3. Encoder: 2–4 TransformerBlock con 4–8 teste, FFN 2–4× dimensione embed, dropout 0.1–0.2.
  4. Decoder: 2–4 blocchi con masked self-attention + cross-attention verso l’encoder; tie embeddings opzionale.
  5. Loss & training: cross-entropy con label smoothing 0.1; AdamW (lr 3e−4) + warmup; early stopping via perdita di validazione.
  6. Decoding: greedy per debug; poi beam search (k=3–5) o top-k/top-p per qualità/varietà.
  7. Valutazione: BLEU/ROUGE su test; rassegna qualitativa di buone/cattive generazioni per guidare i miglioramenti.
<!-- Pseudocodice di montaggio (stile Keras/PyTorch-agnostico) -->
src = Input(shape=(T_src,))
tgt = Input(shape=(T_tgt,))
src_emb = TokenEmbedding(V, d)(src) + PositionalEncoding(T_src, d)
tgt_emb = TokenEmbedding(V, d)(tgt) + PositionalEncoding(T_tgt, d)
enc = src_emb
for _ in range(N_enc):
enc = TransformerBlock(d, heads=H, ffn=4*d, dropout=0.1)(enc)
dec = tgt_emb
for _ in range(N_dec):
dec = MaskedSelfAttentionBlock(d, heads=H, dropout=0.1)(dec)
dec = CrossAttentionBlock(d, heads=H, context=enc, dropout=0.1)(dec)
dec = FeedForwardBlock(d, ffn=4*d, dropout=0.1)(dec)
logits = Dense(V)(dec) # head linguistica
model = Model([src, tgt], logits)

Estensioni opzionali: weight tying embedding/output, shared encoder per multi-task, riduzione complessità con local attention per sequenze lunghe.


8) Errori comuni & best practice

  • Maschere mancanti: senza causal mask il decoder “vede il futuro” e impara scorciatoie.
  • Padding non mascherato: il modello impara a “predire” zeri: sempre applicare la mask del padding in attenzione e loss.
  • Learning rate inadeguato: troppo alto → divergenza; usare warmup e scheduler.
  • Overfitting precoce: aumentare dropout/weight decay, usare early stopping, più dati/augment.
  • Leakage temporale: nei dati sequenziali rispettare la cronologia nei split e nelle finestre.

9) Checklist rapida di design

  • Definisci chiaramente input/output e loro natura (immagini, testo, serie).
  • Scegli i moduli (Conv/RNN/Transformer) in base a località vs lunga dipendenza.
  • Applica normalizzazione, residual, dropout in ogni blocco profondo.
  • Stabilisci metriche coerenti con il task (F1/BLEU/MAE) e un protocollo di validazione.
  • Automatizza il training (checkpoint, early stopping, logging) e prova più semi.

Nessun commento:

Posta un commento

Corso Fondamenti di Informatica e Reti: 6 Reti di computer e Internet

Reti di computer e Internet Introduzione Prova a pensare alla vita quotidiana senza reti informatiche: niente messaggi WhatsApp, niente m...