Deep Learning
Tip
Impara e pratica il hacking AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica il hacking GCP:HackTricks Training GCP Red Team Expert (GRTE)
Impara e pratica il hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Supporta HackTricks
- Controlla i piani di abbonamento!
- Unisciti al đŹ gruppo Discord o al gruppo telegram o seguici su Twitter đŚ @hacktricks_live.
- Condividi trucchi di hacking inviando PR ai HackTricks e HackTricks Cloud repos github.
Deep Learning
Il deep learning è un sottoinsieme del machine learning che utilizza reti neurali con piÚ strati (reti neurali profonde) per modellare schemi complessi nei dati. Ha raggiunto un successo notevole in vari domini, tra cui visione artificiale, elaborazione del linguaggio naturale e riconoscimento vocale.
Neural Networks
Le reti neurali sono i mattoni fondamentali del deep learning. Sono costituite da nodi interconnessi (neuroni) organizzati in strati. Ogni neurone riceve input, applica una somma pesata e passa il risultato attraverso una funzione di attivazione per produrre un output. Gli strati possono essere categorizzati come segue:
- Input Layer: Il primo strato che riceve i dati di input.
- Hidden Layers: Strati intermedi che eseguono trasformazioni sui dati di input. Il numero di strati nascosti e neuroni in ciascuno strato può variare, portando a diverse architetture.
- Output Layer: Lâultimo strato che produce lâoutput della rete, come le probabilitĂ di classe nei compiti di classificazione.
Activation Functions
Quando uno strato di neuroni elabora i dati di input, ogni neurone applica un peso e un bias allâinput (z = w * x + b), dove w è il peso, x è lâinput e b è il bias. Lâoutput del neurone viene quindi passato attraverso una funzione di attivazione per introdurre non linearitĂ nel modello. Questa funzione di attivazione indica fondamentalmente se il neurone successivo âdovrebbe essere attivato e quantoâ. Questo consente alla rete di apprendere schemi e relazioni complesse nei dati, permettendole di approssimare qualsiasi funzione continua.
Pertanto, le funzioni di attivazione introducono non linearitĂ nella rete neurale, consentendole di apprendere relazioni complesse nei dati. Le funzioni di attivazione comuni includono:
- Sigmoid: Mappa i valori di input a un intervallo tra 0 e 1, spesso utilizzato nella classificazione binaria.
- ReLU (Rectified Linear Unit): Restituisce lâinput direttamente se è positivo; altrimenti, restituisce zero. Ă ampiamente utilizzato per la sua semplicitĂ ed efficacia nellâaddestramento di reti profonde.
- Tanh: Mappa i valori di input a un intervallo tra -1 e 1, spesso utilizzato negli strati nascosti.
- Softmax: Converte punteggi grezzi in probabilitĂ , spesso utilizzato nello strato di output per la classificazione multi-classe.
Backpropagation
La backpropagation è lâalgoritmo utilizzato per addestrare le reti neurali regolando i pesi delle connessioni tra i neuroni. Funziona calcolando il gradiente della funzione di perdita rispetto a ciascun peso e aggiornando i pesi nella direzione opposta del gradiente per minimizzare la perdita. I passaggi coinvolti nella backpropagation sono:
- Forward Pass: Calcola lâoutput della rete passando lâinput attraverso gli strati e applicando le funzioni di attivazione.
- Loss Calculation: Calcola la perdita (errore) tra lâoutput previsto e il vero obiettivo utilizzando una funzione di perdita (ad es., errore quadratico medio per la regressione, entropia incrociata per la classificazione).
- Backward Pass: Calcola i gradienti della perdita rispetto a ciascun peso utilizzando la regola della catena del calcolo.
- Weight Update: Aggiorna i pesi utilizzando un algoritmo di ottimizzazione (ad es., discesa del gradiente stocastica, Adam) per minimizzare la perdita.
Convolutional Neural Networks (CNNs)
Le Reti Neurali Convoluzionali (CNNs) sono un tipo specializzato di rete neurale progettata per elaborare dati a griglia, come le immagini. Sono particolarmente efficaci nei compiti di visione artificiale grazie alla loro capacitĂ di apprendere automaticamente gerarchie spaziali di caratteristiche.
I principali componenti delle CNN includono:
- Convolutional Layers: Applicano operazioni di convoluzione ai dati di input utilizzando filtri (kernel) apprendibili per estrarre caratteristiche locali. Ogni filtro scorre sullâinput e calcola un prodotto scalare, producendo una mappa delle caratteristiche.
- Pooling Layers: Ridimensionano le mappe delle caratteristiche per ridurre le loro dimensioni spaziali mantenendo caratteristiche importanti. Le operazioni di pooling comuni includono max pooling e average pooling.
- Fully Connected Layers: Collegano ogni neurone in uno strato a ogni neurone nello strato successivo, simile alle reti neurali tradizionali. Questi strati sono tipicamente utilizzati alla fine della rete per compiti di classificazione.
Allâinterno di una CNN Convolutional Layers, possiamo anche distinguere tra:
- Initial Convolutional Layer: Il primo strato convoluzionale che elabora i dati di input grezzi (ad es., unâimmagine) ed è utile per identificare caratteristiche di base come bordi e texture.
- Intermediate Convolutional Layers: Strati convoluzionali successivi che si basano sulle caratteristiche apprese dallo strato iniziale, consentendo alla rete di apprendere schemi e rappresentazioni piĂš complessi.
- Final Convolutional Layer: Gli ultimi strati convoluzionali prima degli strati completamente connessi, che catturano caratteristiche di alto livello e preparano i dati per la classificazione.
Tip
Le CNN sono particolarmente efficaci per la classificazione delle immagini, il rilevamento degli oggetti e i compiti di segmentazione delle immagini grazie alla loro capacitĂ di apprendere gerarchie spaziali di caratteristiche nei dati a griglia e ridurre il numero di parametri attraverso la condivisione dei pesi. Inoltre, funzionano meglio con dati che supportano il principio della localitĂ delle caratteristiche, dove i dati vicini (pixel) sono piĂš propensi a essere correlati rispetto ai pixel distanti, il che potrebbe non essere il caso per altri tipi di dati come il testo. Inoltre, nota come le CNN saranno in grado di identificare anche caratteristiche complesse ma non saranno in grado di applicare alcun contesto spaziale, il che significa che la stessa caratteristica trovata in diverse parti dellâimmagine sarĂ la stessa.
Example defining a CNN
Qui troverai una descrizione su come definire una Rete Neurale Convoluzionale (CNN) in PyTorch che inizia con un batch di immagini RGB come dataset di dimensione 48x48 e utilizza strati convoluzionali e maxpool per estrarre caratteristiche, seguiti da strati completamente connessi per la classificazione.
Questo è come puoi definire 1 strato convoluzionale in PyTorch: self.conv1 = nn.Conv2d(in_channels=3, out_channels=32, kernel_size=3, padding=1).
-
in_channels: Numero di canali di input. Nel caso di immagini RGB, questo è 3 (uno per ciascun canale di colore). Se stai lavorando con immagini in scala di grigi, questo sarebbe 1. -
out_channels: Numero di canali di output (filtri) che lo strato convoluzionale apprenderĂ . Questo è un iperparametro che puoi regolare in base allâarchitettura del tuo modello. -
kernel_size: Dimensione del filtro convoluzionale. Una scelta comune è 3x3, il che significa che il filtro coprirĂ unâarea di 3x3 dellâimmagine di input. Questo è come un timbro colorato 3Ă3Ă3 che viene utilizzato per generare gli out_channels dagli in_channels:
- Posiziona quel timbro 3Ă3Ă3 nellâangolo in alto a sinistra del cubo dellâimmagine.
- Moltiplica ogni peso per il pixel sottostante, somma tutto, aggiungi il bias â ottieni un numero.
- Scrivi quel numero in una mappa vuota nella posizione (0, 0).
- Scorri il timbro di un pixel a destra (stride = 1) e ripeti fino a riempire unâintera griglia 48Ă48.
padding: Numero di pixel aggiunti a ciascun lato dellâinput. Il padding aiuta a preservare le dimensioni spaziali dellâinput, consentendo un maggiore controllo sulla dimensione dellâoutput. Ad esempio, con un kernel 3x3 e un input di 48x48 pixel, un padding di 1 manterrĂ la dimensione dellâoutput la stessa (48x48) dopo lâoperazione di convoluzione. Questo perchĂŠ il padding aggiunge un bordo di 1 pixel attorno allâimmagine di input, consentendo al kernel di scorrere sui bordi senza ridurre le dimensioni spaziali.
Quindi, il numero di parametri addestrabili in questo strato è:
- (3x3x3 (dimensione del kernel) + 1 (bias)) x 32 (out_channels) = 896 parametri addestrabili.
Nota che un Bias (+1) è aggiunto per ogni kernel utilizzato perchĂŠ la funzione di ciascun strato convoluzionale è quella di apprendere una trasformazione lineare dellâinput, che è rappresentata dallâequazione:
Y = f(W * X + b)
dove W è la matrice dei pesi (i filtri appresi, 3x3x3 = 27 parametri), b è il vettore di bias che è +1 per ogni canale di output.
Nota che lâoutput di self.conv1 = nn.Conv2d(in_channels=3, out_channels=32, kernel_size=3, padding=1) sarĂ un tensore di forma (batch_size, 32, 48, 48), perchĂŠ 32 è il nuovo numero di canali generati di dimensione 48x48 pixel.
Poi, potremmo collegare questo strato convoluzionale a un altro strato convoluzionale come: self.conv2 = nn.Conv2d(in_channels=32, out_channels=64, kernel_size=3, padding=1).
Questo aggiungerĂ : (32x3x3 (dimensione del kernel) + 1 (bias)) x 64 (out_channels) = 18.496 parametri addestrabili e un output di forma (batch_size, 64, 48, 48).
Come puoi vedere, il numero di parametri cresce rapidamente con ogni ulteriore strato convoluzionale, specialmente man mano che aumenta il numero di canali di output.
Unâopzione per controllare la quantitĂ di dati utilizzati è usare max pooling dopo ogni strato convoluzionale. Il max pooling riduce le dimensioni spaziali delle mappe delle caratteristiche, il che aiuta a ridurre il numero di parametri e la complessitĂ computazionale mantenendo le caratteristiche importanti.
Può essere dichiarato come: self.pool1 = nn.MaxPool2d(kernel_size=2, stride=2). Questo indica fondamentalmente di utilizzare una griglia di 2x2 pixel e prendere il valore massimo da ciascuna griglia per ridurre la dimensione della mappa delle caratteristiche della metĂ . Inoltre, stride=2 significa che lâoperazione di pooling si sposterĂ di 2 pixel alla volta, in questo caso, prevenendo qualsiasi sovrapposizione tra le regioni di pooling.
Con questo strato di pooling, la forma dellâoutput dopo il primo strato convoluzionale sarebbe (batch_size, 64, 24, 24) dopo aver applicato self.pool1 allâoutput di self.conv2, riducendo la dimensione a 1/4 di quella del livello precedente.
Tip
Ă importante fare pooling dopo gli strati convoluzionali per ridurre le dimensioni spaziali delle mappe delle caratteristiche, il che aiuta a controllare il numero di parametri e la complessitĂ computazionale mentre si fa in modo che il parametro iniziale apprenda caratteristiche importanti. Puoi vedere le convoluzioni prima di uno strato di pooling come un modo per estrarre caratteristiche dai dati di input (come linee, bordi), queste informazioni saranno ancora presenti nellâoutput poolato, ma il successivo strato convoluzionale non sarĂ in grado di vedere i dati di input originali, solo lâoutput poolato, che è una versione ridotta del livello precedente con quelle informazioni. Nellâordine abituale:
Conv â ReLU â Poologni finestra di pooling 2Ă2 ora compete con le attivazioni delle caratteristiche (âbordo presente / assenteâ), non con le intensitĂ dei pixel grezzi. Mantenere lâattivazione piĂš forte mantiene davvero le prove piĂš salienti.
Poi, dopo aver aggiunto quanti piĂš strati convoluzionali e di pooling necessario, possiamo appiattire lâoutput per alimentarlo in strati completamente connessi. Questo viene fatto rimodellando il tensore in un vettore 1D per ogni campione nel batch:
x = x.view(-1, 64*24*24)
E con questo vettore 1D con tutti i parametri di addestramento generati dai precedenti strati convoluzionali e di pooling, possiamo definire uno strato completamente connesso come:
self.fc1 = nn.Linear(64 * 24 * 24, 512)
Che prenderĂ lâoutput appiattito dello strato precedente e lo mapperĂ a 512 unitĂ nascoste.
Nota come questo strato abbia aggiunto (64 * 24 * 24 + 1 (bias)) * 512 = 3,221,504 parametri addestrabili, che è un aumento significativo rispetto agli strati convoluzionali. Questo perchÊ gli strati completamente connessi collegano ogni neurone in uno strato a ogni neurone nello strato successivo, portando a un gran numero di parametri.
Infine, possiamo aggiungere uno strato di output per produrre i logit della classe finale:
self.fc2 = nn.Linear(512, num_classes)
Questo aggiungerà (512 + 1 (bias)) * num_classes parametri addestrabili, dove num_classes è il numero di classi nel compito di classificazione (ad esempio, 43 per il dataset GTSRB).
Una pratica comune è aggiungere uno strato di dropout prima degli strati completamente connessi per prevenire lâoverfitting. Questo può essere fatto con:
self.dropout = nn.Dropout(0.5)
Questo strato imposta casualmente una frazione delle unitĂ di input a zero durante lâaddestramento, il che aiuta a prevenire lâoverfitting riducendo la dipendenza da neuroni specifici.
Esempio di codice CNN
import torch
import torch.nn as nn
import torch.nn.functional as F
class MY_NET(nn.Module):
def __init__(self, num_classes=32):
super(MY_NET, self).__init__()
# Initial conv layer: 3 input channels (RGB), 32 output channels, 3x3 kernel, padding 1
# This layer will learn basic features like edges and textures
self.conv1 = nn.Conv2d(
in_channels=3, out_channels=32, kernel_size=3, padding=1
)
# Output: (Batch Size, 32, 48, 48)
# Conv Layer 2: 32 input channels, 64 output channels, 3x3 kernel, padding 1
# This layer will learn more complex features based on the output of conv1
self.conv2 = nn.Conv2d(
in_channels=32, out_channels=64, kernel_size=3, padding=1
)
# Output: (Batch Size, 64, 48, 48)
# Max Pooling 1: Kernel 2x2, Stride 2. Reduces spatial dimensions by half (1/4th of the previous layer).
self.pool1 = nn.MaxPool2d(kernel_size=2, stride=2)
# Output: (Batch Size, 64, 24, 24)
# Conv Layer 3: 64 input channels, 128 output channels, 3x3 kernel, padding 1
# This layer will learn even more complex features based on the output of conv2
# Note that the number of output channels can be adjusted based on the complexity of the task
self.conv3 = nn.Conv2d(
in_channels=64, out_channels=128, kernel_size=3, padding=1
)
# Output: (Batch Size, 128, 24, 24)
# Max Pooling 2: Kernel 2x2, Stride 2. Reduces spatial dimensions by half again.
# Reducing the dimensions further helps to control the number of parameters and computational complexity.
self.pool2 = nn.MaxPool2d(kernel_size=2, stride=2)
# Output: (Batch Size, 128, 12, 12)
# From the second pooling layer, we will flatten the output to feed it into fully connected layers.
# The feature size is calculated as follows:
# Feature size = Number of output channels * Height * Width
self._feature_size = 128 * 12 * 12
# Fully Connected Layer 1 (Hidden): Maps flattened features to hidden units.
# This layer will learn to combine the features extracted by the convolutional layers.
self.fc1 = nn.Linear(self._feature_size, 512)
# Fully Connected Layer 2 (Output): Maps hidden units to class logits.
# Output size MUST match num_classes
self.fc2 = nn.Linear(512, num_classes)
# Dropout layer configuration with a dropout rate of 0.5.
# This layer is used to prevent overfitting by randomly setting a fraction of the input units to zero during training.
self.dropout = nn.Dropout(0.5)
def forward(self, x):
"""
The forward method defines the forward pass of the network.
It takes an input tensor `x` and applies the convolutional layers, pooling layers, and fully connected layers in sequence.
The input tensor `x` is expected to have the shape (Batch Size, Channels, Height, Width), where:
- Batch Size: Number of samples in the batch
- Channels: Number of input channels (e.g., 3 for RGB images)
- Height: Height of the input image (e.g., 48 for 48x48 images)
- Width: Width of the input image (e.g., 48 for 48x48 images)
The output of the forward method is the logits for each class, which can be used for classification tasks.
Args:
x (torch.Tensor): Input tensor of shape (Batch Size, Channels, Height, Width)
Returns:
torch.Tensor: Output tensor of shape (Batch Size, num_classes) containing the class logits.
"""
# Conv1 -> ReLU -> Conv2 -> ReLU -> Pool1 -> Conv3 -> ReLU -> Pool2
x = self.conv1(x)
x = F.relu(x)
x = self.conv2(x)
x = F.relu(x)
x = self.pool1(x)
x = self.conv3(x)
x = F.relu(x)
x = self.pool2(x)
# At this point, x has shape (Batch Size, 128, 12, 12)
# Flatten the output to feed it into fully connected layers
x = torch.flatten(x, 1)
# Apply dropout to prevent overfitting
x = self.dropout(x)
# First FC layer with ReLU activation
x = F.relu(self.fc1(x))
# Apply Dropout again
x = self.dropout(x)
# Final FC layer to get logits
x = self.fc2(x)
# Output shape will be (Batch Size, num_classes)
# Note that the output is not passed through a softmax activation here, as it is typically done in the loss function (e.g., CrossEntropyLoss)
return x
Esempio di codice per lâaddestramento CNN
Il seguente codice genererĂ alcuni dati di addestramento e addestrerĂ il modello MY_NET definito sopra. Alcuni valori interessanti da notare:
EPOCHSè il numero di volte che il modello vedrĂ lâintero dataset durante lâaddestramento. Se EPOCH è troppo piccolo, il modello potrebbe non apprendere abbastanza; se troppo grande, potrebbe sovradattarsi.LEARNING_RATEè la dimensione del passo per lâottimizzatore. Un tasso di apprendimento piccolo può portare a una convergenza lenta, mentre uno grande può superare la soluzione ottimale e impedire la convergenza.WEIGHT_DECAYè un termine di regolarizzazione che aiuta a prevenire il sovradattamento penalizzando i pesi grandi.
Riguardo al ciclo di addestramento, ecco alcune informazioni interessanti da sapere:
- Il
criterion = nn.CrossEntropyLoss()è la funzione di perdita utilizzata per compiti di classificazione multi-classe. Combina lâattivazione softmax e la perdita di entropia incrociata in unâunica funzione, rendendola adatta per addestrare modelli che producono logit di classe. - Se ci si aspettava che il modello producesse altri tipi di output, come la classificazione binaria o la regressione, utilizzeremmo funzioni di perdita diverse come
nn.BCEWithLogitsLoss()per la classificazione binaria onn.MSELoss()per la regressione. - Lâ
optimizer = optim.Adam(model.parameters(), lr=LEARNING_RATE, weight_decay=WEIGHT_DECAY)inizializza lâottimizzatore Adam, che è una scelta popolare per lâaddestramento di modelli di deep learning. Adatta il tasso di apprendimento per ogni parametro in base ai primi e secondi momenti dei gradienti. - Altri ottimizzatori come
optim.SGD(Stochastic Gradient Descent) ooptim.RMSproppotrebbero essere utilizzati, a seconda dei requisiti specifici del compito di addestramento. - Il metodo
model.train()imposta il modello in modalitĂ di addestramento, consentendo a strati come dropout e normalizzazione del batch di comportarsi in modo diverso durante lâaddestramento rispetto alla valutazione. optimizer.zero_grad()cancella i gradienti di tutti i tensori ottimizzati prima del passaggio allâindietro, il che è necessario perchĂŠ i gradienti si accumulano per impostazione predefinita in PyTorch. Se non vengono cancellati, i gradienti delle iterazioni precedenti verrebbero aggiunti ai gradienti correnti, portando a aggiornamenti errati.loss.backward()calcola i gradienti della perdita rispetto ai parametri del modello, che vengono poi utilizzati dallâottimizzatore per aggiornare i pesi.optimizer.step()aggiorna i parametri del modello in base ai gradienti calcolati e al tasso di apprendimento.
import torch, torch.nn.functional as F
from torch import nn, optim
from torch.utils.data import DataLoader
from torchvision import datasets, transforms
from tqdm import tqdm
from sklearn.metrics import classification_report, confusion_matrix
import numpy as np
# ---------------------------------------------------------------------------
# 1. Globals
# ---------------------------------------------------------------------------
IMG_SIZE = 48 # model expects 48Ă48
NUM_CLASSES = 10 # MNIST has 10 digits
BATCH_SIZE = 64 # batch size for training and validation
EPOCHS = 5 # number of training epochs
LEARNING_RATE = 1e-3 # initial learning rate for Adam optimiser
WEIGHT_DECAY = 1e-4 # L2 regularisation to prevent overfitting
# Channel-wise mean / std for MNIST (grayscale â repeat for 3-channel input)
MNIST_MEAN = (0.1307, 0.1307, 0.1307)
MNIST_STD = (0.3081, 0.3081, 0.3081)
# ---------------------------------------------------------------------------
# 2. Transforms
# ---------------------------------------------------------------------------
# 1) Baseline transform: resize + tensor (no colour/aug/no normalise)
transform_base = transforms.Compose([
transforms.Resize((IMG_SIZE, IMG_SIZE)), # đš Resize â force all images to 48 Ă 48 so the CNN sees a fixed geometry
transforms.Grayscale(num_output_channels=3), # đš GrayscaleâRGB â MNIST is 1-channel; duplicate into 3 channels for convnet
transforms.ToTensor(), # đš ToTensor â convert PIL image [0â255] â float tensor [0.0â1.0]
])
# 2) Training transform: augment + normalise
transform_norm = transforms.Compose([
transforms.Resize((IMG_SIZE, IMG_SIZE)), # keep 48 Ă 48 input size
transforms.Grayscale(num_output_channels=3), # still need 3 channels
transforms.RandomRotation(10), # đš RandomRotation(Âą10°) â small tilt ⢠rotation-invariance, combats overfitting
transforms.ColorJitter(brightness=0.2,
contrast=0.2), # đš ColorJitter â pseudo-RGB brightness/contrast noise; extra variety
transforms.ToTensor(), # convert to tensor before numeric ops
transforms.Normalize(mean=MNIST_MEAN,
std=MNIST_STD), # đš Normalize â zero-centre & scale so every channel â N(0,1)
])
# 3) Test/validation transform: only resize + normalise (no aug)
transform_test = transforms.Compose([
transforms.Resize((IMG_SIZE, IMG_SIZE)), # same spatial size as train
transforms.Grayscale(num_output_channels=3), # match channel count
transforms.ToTensor(), # tensor conversion
transforms.Normalize(mean=MNIST_MEAN,
std=MNIST_STD), # đš keep test data on same scale as training data
])
# ---------------------------------------------------------------------------
# 3. Datasets & loaders
# ---------------------------------------------------------------------------
train_set = datasets.MNIST("data", train=True, download=True, transform=transform_norm)
test_set = datasets.MNIST("data", train=False, download=True, transform=transform_test)
train_loader = DataLoader(train_set, batch_size=BATCH_SIZE, shuffle=True)
test_loader = DataLoader(test_set, batch_size=256, shuffle=False)
print(f"Training on {len(train_set)} samples, validating on {len(test_set)} samples.")
# ---------------------------------------------------------------------------
# 4. Model / loss / optimiser
# ---------------------------------------------------------------------------
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model = MY_NET(num_classes=NUM_CLASSES).to(device)
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=LEARNING_RATE, weight_decay=WEIGHT_DECAY)
# ---------------------------------------------------------------------------
# 5. Training loop
# ---------------------------------------------------------------------------
for epoch in range(1, EPOCHS + 1):
model.train() # Set model to training mode enabling dropout and batch norm
running_loss = 0.0 # sums batch losses to compute epoch average
correct = 0 # number of correct predictions
total = 0 # number of samples seen
# tqdm wraps the loader to show a live progress-bar per epoch
for X_batch, y_batch in tqdm(train_loader, desc=f"Epoch {epoch}", leave=False):
# 3-a) Move data to GPU (if available) ----------------------------------
X_batch, y_batch = X_batch.to(device), y_batch.to(device)
# 3-b) Forward pass -----------------------------------------------------
logits = model(X_batch) # raw class scores (shape: [B, NUM_CLASSES])
loss = criterion(logits, y_batch)
# 3-c) Backward pass & parameter update --------------------------------
optimizer.zero_grad() # clear old gradients
loss.backward() # compute new gradients
optimizer.step() # gradient â weight update
# 3-d) Statistics -------------------------------------------------------
running_loss += loss.item() * X_batch.size(0) # sum of (batch loss Ă batch size)
preds = logits.argmax(dim=1) # predicted class labels
correct += (preds == y_batch).sum().item() # correct predictions in this batch
total += y_batch.size(0) # samples processed so far
# 3-e) Epoch-level metrics --------------------------------------------------
epoch_loss = running_loss / total
epoch_acc = 100.0 * correct / total
print(f"[Epoch {epoch}] loss = {epoch_loss:.4f} | accuracy = {epoch_acc:.2f}%")
print("\nâ
Training finished.\n")
# ---------------------------------------------------------------------------
# 6. Evaluation on test set
# ---------------------------------------------------------------------------
model.eval() # Set model to evaluation mode (disables dropout and batch norm)
with torch.no_grad():
logits_all, labels_all = [], []
for X, y in test_loader:
logits_all.append(model(X.to(device)).cpu())
labels_all.append(y)
logits_all = torch.cat(logits_all)
labels_all = torch.cat(labels_all)
preds_all = logits_all.argmax(1)
test_loss = criterion(logits_all, labels_all).item()
test_acc = (preds_all == labels_all).float().mean().item() * 100
print(f"Test loss: {test_loss:.4f}")
print(f"Test accuracy: {test_acc:.2f}%\n")
print("Classification report (precision / recall / F1):")
print(classification_report(labels_all, preds_all, zero_division=0))
print("Confusion matrix (rows = true, cols = pred):")
print(confusion_matrix(labels_all, preds_all))
Reti Neurali Ricorrenti (RNN)
Le Reti Neurali Ricorrenti (RNN) sono una classe di reti neurali progettate per elaborare dati sequenziali, come serie temporali o linguaggio naturale. A differenza delle tradizionali reti neurali feedforward, le RNN hanno connessioni che si riavvolgono su se stesse, permettendo loro di mantenere uno stato nascosto che cattura informazioni sugli input precedenti nella sequenza.
I principali componenti delle RNN includono:
- Strati Ricorrenti: Questi strati elaborano le sequenze di input un passo temporale alla volta, aggiornando il loro stato nascosto in base allâinput attuale e allo stato nascosto precedente. Questo consente alle RNN di apprendere dipendenze temporali nei dati.
- Stato Nascosto: Lo stato nascosto è un vettore che riassume le informazioni dai passi temporali precedenti. Viene aggiornato ad ogni passo temporale ed è utilizzato per fare previsioni sullâinput attuale.
- Strato di Uscita: Lo strato di uscita produce le previsioni finali basate sullo stato nascosto. In molti casi, le RNN sono utilizzate per compiti come la modellazione del linguaggio, dove lâoutput è una distribuzione di probabilitĂ sulla prossima parola in una sequenza.
Ad esempio, in un modello di linguaggio, la RNN elabora una sequenza di parole, ad esempio, âIl gatto si è seduto suâ e prevede la prossima parola in base al contesto fornito dalle parole precedenti, in questo caso, âtappetoâ.
Memoria a Lungo e Breve Termine (LSTM) e UnitĂ Ricorrente Gated (GRU)
Le RNN sono particolarmente efficaci per compiti che coinvolgono dati sequenziali, come la modellazione del linguaggio, la traduzione automatica e il riconoscimento vocale. Tuttavia, possono avere difficoltĂ con dipendenze a lungo raggio a causa di problemi come il gradiente che svanisce.
Per affrontare questo problema, sono state sviluppate architetture specializzate come la Memoria a Lungo e Breve Termine (LSTM) e lâUnitĂ Ricorrente Gated (GRU). Queste architetture introducono meccanismi di gating che controllano il flusso di informazioni, permettendo loro di catturare dipendenze a lungo raggio in modo piĂš efficace.
- LSTM: Le reti LSTM utilizzano tre porte (porta di input, porta di dimenticanza e porta di output) per regolare il flusso di informazioni dentro e fuori dallo stato della cella, consentendo loro di ricordare o dimenticare informazioni su lunghe sequenze. La porta di input controlla quanto nuova informazione aggiungere in base allâinput e allo stato nascosto precedente, la porta di dimenticanza controlla quanto informazione scartare. Combinando la porta di input e la porta di dimenticanza otteniamo il nuovo stato. Infine, combinando il nuovo stato della cella, con lâinput e lo stato nascosto precedente otteniamo anche il nuovo stato nascosto.
- GRU: Le reti GRU semplificano lâarchitettura LSTM combinando le porte di input e di dimenticanza in unâunica porta di aggiornamento, rendendole computazionalmente piĂš efficienti pur catturando ancora dipendenze a lungo raggio.
LLM (Modelli di Linguaggio di Grandi Dimensioni)
I Modelli di Linguaggio di Grandi Dimensioni (LLM) sono un tipo di modello di deep learning specificamente progettato per compiti di elaborazione del linguaggio naturale. Sono addestrati su enormi quantitĂ di dati testuali e possono generare testo simile a quello umano, rispondere a domande, tradurre lingue e svolgere vari altri compiti legati al linguaggio. Gli LLM si basano tipicamente su architetture transformer, che utilizzano meccanismi di autoattenzione per catturare relazioni tra le parole in una sequenza, permettendo loro di comprendere il contesto e generare testo coerente.
Architettura Transformer
Lâarchitettura transformer è la base di molti LLM. Consiste in una struttura encoder-decoder, dove lâencoder elabora la sequenza di input e il decoder genera la sequenza di output. I componenti chiave dellâarchitettura transformer includono:
- Meccanismo di Autoattenzione: Questo meccanismo consente al modello di pesare lâimportanza di diverse parole in una sequenza quando genera rappresentazioni. Calcola punteggi di attenzione basati sulle relazioni tra le parole, consentendo al modello di concentrarsi sul contesto rilevante.
- Attenzione Multi-Testa: Questo componente consente al modello di catturare piĂš relazioni tra le parole utilizzando piĂš teste di attenzione, ognuna focalizzata su diversi aspetti dellâinput.
- Codifica Posizionale: PoichĂŠ i transformer non hanno una nozione incorporata dellâordine delle parole, la codifica posizionale viene aggiunta agli embedding di input per fornire informazioni sulla posizione delle parole nella sequenza.
Modelli di Diffusione
I modelli di diffusione sono una classe di modelli generativi che apprendono a generare dati simulando un processo di diffusione. Sono particolarmente efficaci per compiti come la generazione di immagini e hanno guadagnato popolaritĂ negli ultimi anni. I modelli di diffusione funzionano trasformando gradualmente una semplice distribuzione di rumore in una distribuzione di dati complessa attraverso una serie di passaggi di diffusione. I componenti chiave dei modelli di diffusione includono:
- Processo di Diffusione Avanzata: Questo processo aggiunge gradualmente rumore ai dati, trasformandoli in una semplice distribuzione di rumore. Il processo di diffusione avanzata è tipicamente definito da una serie di livelli di rumore, dove ogni livello corrisponde a una specifica quantità di rumore aggiunta ai dati.
- Processo di Diffusione Inversa: Questo processo apprende a invertire il processo di diffusione avanzata, denoising gradualmente i dati per generare campioni dalla distribuzione target. Il processo di diffusione inversa viene addestrato utilizzando una funzione di perdita che incoraggia il modello a ricostruire i dati originali da campioni rumorosi.
Inoltre, per generare unâimmagine da un prompt testuale, i modelli di diffusione seguono tipicamente questi passaggi:
- Codifica del Testo: Il prompt testuale viene codificato in una rappresentazione latente utilizzando un codificatore di testo (ad esempio, un modello basato su transformer). Questa rappresentazione cattura il significato semantico del testo.
- Campionamento del Rumore: Un vettore di rumore casuale viene campionato da una distribuzione gaussiana.
- Passaggi di Diffusione: Il modello applica una serie di passaggi di diffusione, trasformando gradualmente il vettore di rumore in unâimmagine che corrisponde al prompt testuale. Ogni passaggio comporta lâapplicazione di trasformazioni apprese per denoising lâimmagine.
Tip
Impara e pratica il hacking AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica il hacking GCP:HackTricks Training GCP Red Team Expert (GRTE)
Impara e pratica il hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Supporta HackTricks
- Controlla i piani di abbonamento!
- Unisciti al đŹ gruppo Discord o al gruppo telegram o seguici su Twitter đŚ @hacktricks_live.
- Condividi trucchi di hacking inviando PR ai HackTricks e HackTricks Cloud repos github.
HackTricks

