TLDR

  • La regressione logistica risolve problemi di classificazione incapsulando la combinazione lineare nella funzione Sigmoide.
  • L'output del modello rappresenta la probabilità condizionata P(y=1|x) calibrata nell'intervallo [0, 1].
  • La funzione di costo MSE genera superfici non convesse: si adotta quindi la Binary Cross-Entropy Loss.
  • La regolarizzazione L2 (Ridge) contrasta l'overfitting applicando una contrazione automatica dei pesi (Weight Decay).

Dai Problemi di Regressione alla Classificazione

In molte applicazioni ingegneristiche e di sicurezza informatica, il valore da prevedere non è continuo, ma discreto e categorico:

  • Un pacchetto di rete è traffico legittimo ($y=0$) o un tentativo di exploit/intrusione ($y=1$)?
  • Un microchip in fase di test supera il collaudo di qualità ($y=1$) o è difettoso ($y=0$)?
  • Una transazione finanziaria è regolare ($y=0$) o fraudolenta ($y=1$)?

Se proviamo ad applicare la regressione lineare convenzionale assegnando $y \in {0, 1}$ e impostando una soglia a $0.5$, incontriamo due gravi fallimenti strutturali:

  1. Predizioni Fuori Scala: Il modello lineare calcola valori arbitrari $f(x) > 1$ o $f(x) < 0$, privi di significato probabilistico.
  2. Sensibilità Estrema agli Outlier: L'inserimento nel dataset di un campione positivo con valore di feature molto elevato sposta la pendenza della retta, allontanando la soglia $0.5$ e causando falsi negativi sistematici.

Il Modello di Regressione Logistica e la Funzione Sigmoide

Per vincolare l'output nell'intervallo continuo $[0, 1]$, incapsuliamo la combinazione lineare $z = \mathbf{w} \cdot \mathbf{x} + b$ all'interno della funzione Sigmoide (o logistica):

$$g(z) = \frac{1}{1 + e^{-z}}$$

Curva a S della funzione Sigmoide e mappatura dei Logits
Curva sigmoide: mappatura non lineare continua dallo spazio dei Logits (-inf, +inf) allo spazio delle probabilità [0, 1].

L'equazione complessiva del modello di Regressione Logistica diventa:

$$f_{\mathbf{w},b}(\mathbf{x}) = g(\mathbf{w} \cdot \mathbf{x} + b) = \frac{1}{1 + e^{-(\mathbf{w} \cdot \mathbf{x} + b)}}$$

Interpretazione Probabilistica e Soglia di Decisione

L'output $f_{\mathbf{w},b}(\mathbf{x})$ rappresenta la probabilità condizionata che l'etichetta sia $1$ date le feature $\mathbf{x}$: $$f_{\mathbf{w},b}(\mathbf{x}) = P(y = 1 \mid \mathbf{x}; \mathbf{w}, b)$$ $$P(y = 0 \mid \mathbf{x}; \mathbf{w}, b) = 1 - f_{\mathbf{w},b}(\mathbf{x})$$

Fissando la soglia decisionale convenzionale a $0.5$: $$\hat{y} = \begin{cases} 1 & \text{se } f_{\mathbf{w},b}(\mathbf{x}) \ge 0.5 \iff z = \mathbf{w} \cdot \mathbf{x} + b \ge 0 \ 0 & \text{se } f_{\mathbf{w},b}(\mathbf{x}) < 0.5 \iff z = \mathbf{w} \cdot \mathbf{x} + b < 0 \end{cases}$$


Il Confine Decisionale (Decision Boundary)

Il Confine Decisionale è il luogo geometrico dei punti nello spazio delle feature in cui il modello è massimamente incerto, ovvero dove $z = \mathbf{w} \cdot \mathbf{x} + b = 0$.

  • Confine Lineare: In presenza di feature lineari di primo grado ($w_1 x_1 + w_2 x_2 + b = 0$), il confine è una retta o un iperpiano piano.
  • Confine Non Lineare: Integrando feature polinomiali nell'argomento $z$ (es. $w_1 x_1^2 + w_2 x_2^2 + b = 0$), il confine decisionale assume geometrie circolari, ellittiche o contorni ad anello complessi.

La Funzione di Costo: Binary Cross-Entropy

Se applicassimo l'errore quadratico medio (MSE) alla regressione logistica, inserendo $g(z)$ all'interno dei quadrati, otterremmo una superficie di errore non convessa ricca di trappole e minimi locali.

Definiamo invece la Binary Cross-Entropy Loss per la singola osservazione:

$$L\left(f_{\mathbf{w},b}(\mathbf{x}), y\right) = \begin{cases} -\log\left(f_{\mathbf{w},b}(\mathbf{x})\right) & \text{se } y = 1 \ -\log\left(1 - f_{\mathbf{w},b}(\mathbf{x})\right) & \text{se } y = 0 \end{cases}$$

Sintetizzabile in una singola espressione compatta per l'intero dataset di $m$ campioni:

$$J(\mathbf{w}, b) = -\frac{1}{m} \sum_{i=1}^{m} \left[ y^{(i)} \log\left(f_{\mathbf{w},b}(\mathbf{x}^{(i)})\right) + (1 - y^{(i)}) \log\left(1 - f_{\mathbf{w},b}(\mathbf{x}^{(i)})\right) \right]$$

Proprietà di Penalizzazione Asintotica

  • Se il target reale è $y=1$ e il modello predice $f \to 1$, la perdita è nulla ($-\log(1) = 0$). Se il modello predice erroneamente con sicurezza $f \to 0$, la perdita tende asintoticamente a $+\infty$.
  • La combinazione della perdita logaritmica con la sigmoide garantisce la stretta convessità globale di $J(\mathbf{w}, b)$.

Discesa del Gradiente e Regolarizzazione L2 (Ridge)

Calcolando le derivate parziali di $J(\mathbf{w}, b)$ rispetto ai pesi e al bias:

$$\frac{\partial J(\mathbf{w}, b)}{\partial w_j} = \frac{1}{m} \sum_{i=1}^{m} \left( f_{\mathbf{w},b}(\mathbf{x}^{(i)}) - y^{(i)} \right) x_j^{(i)}$$

$$\frac{\partial J(\mathbf{w}, b)}{\partial b} = \frac{1}{m} \sum_{i=1}^{m} \left( f_{\mathbf{w},b}(\mathbf{x}^{(i)}) - y^{(i)} \right)$$

Notate la straordinaria eleganza algebrica: pur essendo cambiata la definizione di $f(\mathbf{x})$, la forma matematica del gradiente è identica a quella della regressione lineare.

Trade-off tra Underfitting, Adattamento Ottimale e Overfitting
Diagnosi di Bias e Varianza: dal modello troppo rigido all'overfitting da regolarizzare.

Regolarizzazione L2 e Weight Decay

Quando si utilizzano molte feature o polinomi di grado elevato, i coefficienti $w$ possono assumere valori giganteschi nel tentativo di memorizzare il rumore (Overfitting).

Aggiungiamo una penalità di regolarizzazione $L_2$ proporzionale al parametro $\lambda$:

$$J_{\text{reg}}(\mathbf{w}, b) = J(\mathbf{w}, b) + \frac{\lambda}{2m} \sum_{j=1}^{n} w_j^2$$

L'aggiornamento iterativo dei pesi incorpora il fattore di contrazione (Weight Decay):

$$w_j := w_j \left( 1 - \alpha \frac{\lambda}{m} \right) - \alpha \frac{1}{m} \sum_{i=1}^{m} \left( f_{\mathbf{w},b}(\mathbf{x}^{(i)}) - y^{(i)} \right) x_j^{(i)}$$


Laboratorio Pratico Completo in Python

Di seguito l'implementazione completa from-scratch della Regressione Logistica Regolarizzata:

import numpy as np

# 1. Definizione della funzione Sigmoide numericamente stabile
def sigmoid(z):
    z = np.clip(z, -500, 500) # Prevenzione overflow numerico
    return 1.0 / (1.0 + np.exp(-z))

# 2. Calcolo del Costo Regolarizzato (Binary Cross-Entropy)
def compute_cost_logistic_reg(X, y, w, b, lambda_reg=1.0):
    m = X.shape[0]
    z = np.dot(X, w) + b
    f_wb = sigmoid(z)
    
    # Epsilon per stabilizzare il calcolo del logaritmo
    eps = 1e-15
    f_wb = np.clip(f_wb, eps, 1.0 - eps)
    
    loss = - (y * np.log(f_wb) + (1.0 - y) * np.log(1.0 - f_wb))
    cost = (1.0 / m) * np.sum(loss)
    
    reg_cost = (lambda_reg / (2.0 * m)) * np.sum(w ** 2)
    return cost + reg_cost

# 3. Calcolo del Gradiente Regolarizzato
def compute_gradient_logistic_reg(X, y, w, b, lambda_reg=1.0):
    m, n = X.shape
    f_wb = sigmoid(np.dot(X, w) + b)
    err = f_wb - y
    
    dj_dw = (1.0 / m) * np.dot(X.T, err) + (lambda_reg / m) * w
    dj_db = (1.0 / m) * np.sum(err)
    return dj_dw, dj_db

# 4. Addestramento con Discesa del Gradiente
def fit_logistic_regression(X, y, alpha=0.1, lambda_reg=0.1, iters=1000):
    m, n = X.shape
    w = np.zeros(n)
    b = 0.0
    
    for i in range(iters):
        dj_dw, dj_db = compute_gradient_logistic_reg(X, y, w, b, lambda_reg)
        w -= alpha * dj_dw
        b -= alpha * dj_db
        
        if i % 200 == 0:
            cost = compute_cost_logistic_reg(X, y, w, b, lambda_reg)
            print(f"Iterazione {i:4d}: Costo BCE = {cost:.4f}")
            
    return w, b

# 5. Esecuzione su dati di test (Quality Assurance Microchip)
np.random.seed(42)
m_samples = 120
X_test_data = np.random.randn(m_samples, 2)
# Campioni con distanza dall'origine < 1.0 sono validi (y=1)
y_test_data = ((X_test_data[:, 0]**2 + X_test_data[:, 1]**2) < 1.2).astype(float)

# Ingegneria di feature polinomiali per confine circolare: [x1, x2, x1^2, x2^2]
X_poly = np.column_stack([
    X_test_data[:, 0],
    X_test_data[:, 1],
    X_test_data[:, 0]**2,
    X_test_data[:, 1]**2
])

w_trained, b_trained = fit_logistic_regression(X_poly, y_test_data, alpha=0.5, lambda_reg=0.01, iters=1000)

# 6. Valutazione accuratezza
preds_prob = sigmoid(np.dot(X_poly, w_trained) + b_trained)
preds_class = (preds_prob >= 0.5).astype(float)
accuracy = np.mean(preds_class == y_test_data) * 100

print(f"\nAccuratezza finale di classificazione: {accuracy:.2f}%")
print(f"Pesi ottimali: {w_trained}")
print(f"Bias ottimale: {b_trained:.4f}")

Conclusioni

La regressione logistica regolarizzata costituisce il fondamento concettuale su cui si innestano le architetture neurali moderne. Nel prossimo articolo faremo il salto nel mondo del Deep Learning, analizzando come l'impilamento gerarchico di neuroni con attivazioni non lineari consenta di apprendere confini decisionali infinitamente complessi.

FAQ

Perché la regressione lineare non è adatta per problemi di classificazione binaria?

La regressione lineare produce valori continui illimitati (-inf, +inf) anziché probabilità [0, 1]. Inoltre, la presenza di outlier lontani dal confine decisionale sposta sensibilmente la retta di regressione, alterando drasticamente la soglia di classificazione corretta.

Cosa rappresenta la funzione Sigmoide g(z)?

La funzione Sigmoide g(z) = 1 / (1 + e^-z) mappa qualsiasi valore reale z (logit) nell'intervallo continuo tra 0 e 1, consentendo un'interpretazione probabilistica naturale della decisione.

Come si definisce geometricamente il confine decisionale (Decision Boundary)?

Il confine decisionale è l'iperpiano o la curva definita dall'equazione z = w * x + b = 0, dove la probabilità predetta è esattamente 0.5. Separa lo spazio delle feature nella regione associata alla classe 1 da quella associata alla classe 0.

Perché la Binary Cross-Entropy garantisce l'ottimizzazione globale?

Quando combinata con la funzione sigmoide, la Binary Cross-Entropy produce una superficie di costo strettamente convessa priva di minimi locali secondari, consentendo alla discesa del gradiente di convergere sempre alla soluzione ottima.

Come agisce il termine di regolarizzazione L2 durante la discesa del gradiente?

A ogni iterazione, prima di sottrarre il gradiente dell'errore, ogni peso w_j viene moltiplicato per un fattore (1 - alpha * lambda / m) strettamente minore di 1, inducendo un decadimento esponenziale che penalizza i pesi eccessivamente elevati.

Fonti