Matrici a Gradini e Multicollinearità: Guida Diagnostica all’Algebra Lineare per Data Scientist

Cerca:

Generic selectors
Exact matches only
Search in title
Search in content
Post Type Selectors
Guida Diagnostica all’Algebra Lineare per Data Scientist

Perché l’Algebra Lineare Decide il Successo dei Modelli

Quando si parla di machine learning si citano spesso librerie, framework e architetture.
Raramente si dice la verità più scomoda:

ogni modello supervisionato vive dentro un sistema lineare.

Regressione lineare, regressione logistica (localmente), PCA, SVD, least squares, ridge, lasso:
tutto nasce da una matrice e dal suo comportamento strutturale.

Uno degli strumenti più sottovalutati — ma più potenti — è la forma a gradini (row echelon form).

Non è un esercizio da maturità.
È una diagnostica matematica del dataset.

In questo articolo rivediamo 6 esercizi classici, ma reinterpretati come farebbe un data scientist, con soluzioni commentate e insight operativi.

Pubblicità

Esercizio 1 — Riconoscere la forma a gradini = Riconoscere la collinearità

Problema originale: stabilire se una matrice è a gradini.

Versione data science: stabilire se le feature sono collineari.

👉 In ML, una matrice NON a gradini spesso indica collinearità o feature duplicate.

Se una riga non può “scalare” verso destra, significa che una feature è combinazione lineare delle precedenti.

Interpretazione ML:

  • Se la matrice è a gradini → le feature sono indipendenti.
  • Se non lo è → regressione lineare instabile, pesi non identificabili, warning di scikit‑learn.

💡 Insight: La forma a gradini è un test manuale di multicollinearità.

Collegamento con le Feature in Machine Learning

In ambito ML, l’algebra lineare non è solo calcolo, ma fornisce strumenti diagnostici fondamentali per la qualità dei dati.

1. La Matrice dei Dati [math]X[/math]

Consideriamo una matrice [math]X[/math] di dimensioni [math]m \times n[/math]:

  • Righe ([math]m[/math]): Rappresentano gli esempi (samples, osservazioni).
  • Colonne ([math]n[/math]): Rappresentano le feature (variabili) [math]X_1, X_2, \dots, X_n[/math].

In genere, per avere un modello robusto, desideriamo che [math]m \ge n[/math] (più dati che variabili) e che le colonne siano linearmente indipendenti.

2. Il Problema della Multicollinearità

La collinearità (o multicollinearità) si verifica quando una feature (una colonna) è combinazione lineare delle altre. In termini pratici, significa che quella feature è ridondante: non porta nuova informazione, ma ripete informazioni già presenti.

Conseguenze matematiche:

  • Se c’è dipendenza lineare, il rango di [math]X[/math] non è massimo: [math]\text{rango}(X) < n[/math].
  • Nella regressione lineare (metodo dei minimi quadrati), cerchiamo di risolvere [math]Xw = y[/math]. La soluzione analitica richiede l’inversione di [math]X^T X[/math]:
    [math]\displaystyle w = (X^T X)^{-1} X^T y[/math]
  • Se [math]\text{rango}(X) < n[/math], la matrice [math]X^T X[/math] diventa singolare (determinante nullo) e non può essere invertita. Questo rende la regressione instabile o impossibile.

3. Diagnosi tramite Matrici a Gradini

Come facciamo a scoprire se soffriamo di multicollinearità senza calcolare determinanti complessi? Usiamo l’eliminazione di Gauss per portare la matrice [math]X[/math] in forma a gradini.

Per il teorema fondamentale dell’algebra lineare, il rango per righe è uguale al rango per colonne. Quindi, contando i pivot otteniamo la risposta.

Analisi dei Pivot Interpretazione ML Conseguenza
Numero Pivot = [math]n[/math] Colonne indipendenti ✔ Nessuna multicollinearità
Numero Pivot < [math]n[/math] Colonne dipendenti ⚠ Multicollinearità (Feature ridondanti)
💡 Nota Pratica:
Se durante l’eliminazione di Gauss su [math]X[/math] trovi una colonna che non genera un nuovo pivot (ovvero, la variabile corrispondente è libera), quella specifica feature è linearmente dipendente dalle precedenti (nell’ordine in cui sono state processate).

Esempio: Diagnosi di Collinearità nel Machine Learning

Immaginiamo di avere un dataset con 3 feature (variabili) e 3 osservazioni. Vogliamo verificare se queste variabili sono indipendenti o se creano instabilità nel modello.

1. Definizione della Matrice Dati [math]X[/math]

Siano le nostre feature:

  • [math]X_1 = [1, 2, 3]^T[/math]
  • [math]X_2 = [2, 4, 6]^T[/math] (Notiamo subito che [math]X_2 = 2X_1[/math])
  • [math]X_3 = [1, 1, 1]^T[/math]

La matrice dei dati [math]X[/math] ([math]3 \times 3[/math]) è:

[math]\displaystyle
X = \begin{pmatrix}
1 & 2 & 1 \\
2 & 4 & 1 \\
3 & 6 & 1
\end{pmatrix}
[/math]


2. Riduzione a Gradini (Algoritmo di Gauss)

Applichiamo le operazioni elementari per annullare gli elementi sotto il primo pivot:

  • Passo 1: [math]R_2 \leftarrow R_2 – 2R_1[/math] → [math](2, 4, 1) – (2, 4, 2) = (0, 0, -1)[/math]
  • Passo 2: [math]R_3 \leftarrow R_3 – 3R_1[/math] → [math](3, 6, 1) – (3, 6, 3) = (0, 0, -2)[/math]

La matrice parziale è ora:

[math]\displaystyle \begin{pmatrix} 1 & 2 & 1 \\ 0 & 0 & -1 \\ 0 & 0 & -2 \end{pmatrix}[/math]

  • Passo 3: [math]R_3 \leftarrow R_3 – 2R_2[/math] → [math](0, 0, -2) – (0, 0, -2) = (0, 0, 0)[/math]

Matrice a gradini finale:

[math]\displaystyle
\begin{pmatrix}
\mathbf{1} & 2 & 1 \\
0 & 0 & \mathbf{-1} \\
0 & 0 & 0
\end{pmatrix}
[/math]


3. Interpretazione Diagnostica per il Machine Learning

Analizziamo il risultato ottenuto:

  • Numero di Pivot: 2 (nelle colonne 1 e 3).
  • Numero di Feature: 3.
  • Risultato: Poiché il Rango (2) < Numero Feature (3), esiste una collinearità perfetta.
⚠️ Problemi in Regressione Lineare:
In questo scenario, il modello di regressione fallirà o sarà instabile perché:

  1. L’inversa di [math]X^T X[/math] non esiste (determinante nullo).
  2. I coefficienti [math]w[/math] non sono unici (esistono infinite combinazioni di pesi).
  3. Librerie come Scikit-Learn potrebbero dare warning di ill-conditioned matrix.

4. Conclusione Finale

Il “test della forma a gradini” applicato alla matrice dei dati rivela la salute del dataset:

  • Forma a gradini con [math]n[/math] pivot: Le feature sono indipendenti. Il modello sarà stabile.
  • Forma a gradini con [math] < n[/math] pivot: Almeno una feature è ridondante. Azione richiesta: Rimuovere la feature che non ha generato il pivot (nel nostro caso, la seconda colonna).

La forma a gradini è il “test del DNA” delle tue feature: rivela legami di parentela nascosti che potrebbero confondere il tuo modello.

Ecco uno snippet Python che implementa il test della multicollinearità tramite la forma a gradini:

import numpy as np
from scipy import linalg
import warnings

def is_row_echelon(matrix, tol=1e-10):
    """
    Verifica se una matrice è in forma a gradini (row echelon form).
    
    Args:
        matrix: Matrice numpy (m x n)
        tol: Tolleranza per considerare un elemento zero
        
    Returns:
        bool: True se la matrice è in forma a gradini
    """
    m, n = matrix.shape
    
    # Troviamo i pivot di ogni riga (primo elemento non zero)
    pivot_positions = []
    for i in range(m):
        pivot_col = None
        for j in range(n):
            if abs(matrix[i, j]) > tol:
                pivot_col = j
                break
        pivot_positions.append(pivot_col)
    
    # Controllo delle condizioni della forma a gradini
    last_pivot = -1
    for i, pivot in enumerate(pivot_positions):
        if pivot is None:  # riga tutta zero
            # Verifica che tutte le righe sotto siano anche zero
            for k in range(i+1, m):
                if pivot_positions[k] is not None:
                    return False
            continue
        
        # Condizione: ogni pivot deve essere a destra del precedente
        if pivot <= last_pivot:
            return False
        
        last_pivot = pivot

def check_multicollinearity(X, tol=1e-10, verbose=True):
    """
    Controlla la multicollinearità nelle feature usando la forma a gradini.
    
    Args:
        X: Matrice dei dati (esempi x feature)
        tol: Tolleranza numerica
        verbose: Se True, stampa informazioni dettagliate
        
    Returns:
        dict: Risultati del test
    """
    # Trasponiamo per avere le feature come righe
    X_T = X.T
    
    # Calcoliamo la forma a gradini
    m, n = X_T.shape
    
    # Copia per non modificare l'originale
    A = X_T.copy().astype(float)
    
    # Riduzione a gradini (Gauss semplice)
    rows, cols = A.shape
    pivot_cols = []
    current_row = 0
    
    for col in range(cols):
        if current_row >= rows:
            break
            
        # Trova il pivot in questa colonna
        pivot_row = None
        for r in range(current_row, rows):
            if abs(A[r, col]) > tol:
                pivot_row = r
                break
        
        if pivot_row is None:
            continue  # Nessun pivot in questa colonna
        
        # Scambia le righe
        if pivot_row != current_row:
            A[[current_row, pivot_row]] = A[[pivot_row, current_row]]
        
        # Normalizza la riga del pivot (opzionale, per chiarezza)
        pivot_val = A[current_row, col]
        if abs(pivot_val) > tol:
            A[current_row] = A[current_row] / pivot_val
        
        # Elimina sotto il pivot
        for r in range(current_row + 1, rows):
            factor = A[r, col]
            if abs(factor) > tol:
                A[r] = A[r] - factor * A[current_row]
        
        pivot_cols.append((current_row, col))
        current_row += 1
    
    # Numero di pivot (rango della trasposta)
    num_pivots = len(pivot_cols)
    num_features = X.shape[1]
    
    # Risultati
    is_echelon = is_row_echelon(A, tol)
    
    # Calcolo del numero di condizione per ulteriore validazione
    if X.shape[0] >= X.shape[1]:
        try:
            cond_number = np.linalg.cond(X)
            high_cond = cond_number > 1e12  # Soglia per multicollinearità grave
        except:
            cond_number = np.inf
            high_cond = True
    else:
        cond_number = None
        high_cond = False
    
    # Interpretazione
    independent = (num_pivots == num_features)
    collinear = not independent
    
    if verbose:
        print("="*60)
        print("TEST DI MULTICOLLINEARITÀ TRAMITE FORMA A GRADINI")
        print("="*60)
        print(f"Matrice dati: {X.shape[0]} esempi, {X.shape[1]} feature")
        print(f"Matrice trasposta (feature come righe): {X_T.shape}")
        print(f"\nNumero di pivot trovati: {num_pivots}")
        print(f"Numero di feature: {num_features}")
        print(f"Matrice risultante è a gradini: {is_echelon}")
        
        if cond_number is not None:
            print(f"Numero di condizione di X: {cond_number:.2e}")
        
        print(f"\n{'='*60}")
        print("DIAGNOSI:")
        if independent:
            print("✅ Feature INDIPENDENTI (nessuna multicollinearità)")
            print("   Regressione lineare stabile, pesi identificabili")
        else:
            print("❌ MULTICOLLINEARITÀ RILEVATA")
            print(f"   Rango: {num_pivots} < {num_features}")
            print("   Almeno una feature è combinazione lineare delle altre")
            print("   Regressione lineare instabile, possibili warning")
            
            # Suggerimenti
            print("\n💡 SUGGERIMENTI:")
            print("   1. Rimuovere feature ridondanti")
            print("   2. Usare Ridge Regression (L2 regularization)")
            print("   3. Applicare PCA per ridurre la dimensionalità")
            print("   4. Verificare correlazioni tra feature")
        
        if high_cond and cond_number is not None:
            print(f"\n⚠️  Attenzione: numero di condizione molto alto ({cond_number:.2e})")
            print("   Indica multicollinearità grave anche se il rango è massimo")
    
    return {
        'independent': independent,
        'collinear': collinear,
        'num_pivots': num_pivots,
        'num_features': num_features,
        'rank': num_pivots,
        'condition_number': cond_number,
        'is_row_echelon': is_echelon,
        'echelon_matrix': A,
        'pivot_positions': pivot_cols
    }

def create_example_data(example_type='independent'):
    """Crea dati di esempio per testare la multicollinearità."""
    
    if example_type == 'independent':
        # Feature indipendenti
        X = np.array([
            [1, 2, 3],
            [4, 5, 6],
            [7, 8, 10],
            [2, 3, 4]
        ])
    
    elif example_type == 'collinear':
        # Feature 2 = 2 * Feature 1
        X = np.array([
            [1, 2, 5],
            [2, 4, 6],
            [3, 6, 7],
            [4, 8, 8]
        ])
    
    elif example_type == 'perfect_collinear':
        # Feature 3 = Feature 1 + Feature 2
        X = np.array([
            [1, 2, 3],
            [2, 3, 5],
            [3, 4, 7],
            [4, 5, 9]
        ])
    
    elif example_type == 'almost_collinear':
        # Quasi collinearità (numericamente problematico)
        X = np.array([
            [1, 2.001, 3],
            [2, 4, 6],
            [3, 6.002, 9],
            [4, 8, 12]
        ])
    
    return X

def test_examples():
    """Testa diversi esempi di multicollinearità."""
    
    examples = ['independent', 'collinear', 'perfect_collinear', 'almost_collinear']
    
    for ex_type in examples:
        print(f"\n{'='*60}")
        print(f"TEST: {ex_type.upper()}")
        print(f"{'='*60}")
        
        X = create_example_data(ex_type)
        print(f"\nMatrice X:\n{X}")
        
        result = check_multicollinearity(X, verbose=True)
        
        # Mostra la matrice a gradini risultante
        print(f"\nMatrice a gradini (feature come righe):")
        print(result['echelon_matrix'].round(4))
        
        # Mostra posizioni dei pivot
        if result['pivot_positions']:
            print(f"Posizioni pivot (riga, colonna): {result['pivot_positions']}")

# -----------------------------------------------------------------
# ESEMPIO DI UTILIZZO
# -----------------------------------------------------------------
if __name__ == "__main__":
    # Test con tutti gli esempi
    test_examples()
    
    print("\n" + "="*60)
    print("USO PRATICO CON NUOVI DATI")
    print("="*60)
    
    # Crea i tuoi dati
    print("\n1. Inserisci manualmente i dati:")
    X_custom = np.array([
        [1, 2, 3],
        [4, 8, 6],  # Nota: colonna 2 = 2 * colonna 1
        [2, 4, 5],
        [3, 6, 7]
    ])
    
    print(f"Matrice:\n{X_custom}")
    result = check_multicollinearity(X_custom, verbose=True)
    
    # Verifica con scikit-learn per confronto
    try:
        from sklearn.linear_model import LinearRegression
        
        print(f"\n{'='*60}")
        print("VERIFICA CON SCKIT-LEARN")
        print("="*60)
        
        # Crea target fittizio
        y = np.array([1, 2, 3, 4])
        
        model = LinearRegression()
        
        try:
            model.fit(X_custom, y)
            print("✅ Scikit-learn ha completato il fit senza errori")
            print(f"   Coefficienti: {model.coef_}")
        except Exception as e:
            print(f"❌ Scikit-learn ha sollevato un'eccezione: {e}")
            
            # Test con Ridge per confronto
            from sklearn.linear_model import Ridge
            ridge_model = Ridge(alpha=1.0)
            ridge_model.fit(X_custom, y)
            print(f"   Ridge Regression coefficienti: {ridge_model.coef_}")
            
    except ImportError:
        print("\nNota: scikit-learn non installato. Per installare: pip install scikit-learn")
============================================================
TEST: INDEPENDENT
============================================================

Matrice X:
[[ 1  2  3]
 [ 4  5  6]
 [ 7  8 10]
 [ 2  3  4]]
============================================================
TEST DI MULTICOLLINEARITÀ TRAMITE FORMA A GRADINI
============================================================
Matrice dati: 4 esempi, 3 feature
Matrice trasposta (feature come righe): (3, 4)

Numero di pivot trovati: 3
Numero di feature: 3
Matrice risultante è a gradini: True
Numero di condizione di X: 9.16e+01

============================================================
DIAGNOSI:
✅ Feature INDIPENDENTI (nessuna multicollinearità)
   Regressione lineare stabile, pesi identificabili

Matrice a gradini (feature come righe):
[[ 1.      4.      7.      2.    ]
 [-0.      1.      2.      0.3333]
 [ 0.      0.      1.      0.    ]]
Posizioni pivot (riga, colonna): [(0, 0), (1, 1), (2, 2)]

============================================================
TEST: COLLINEAR
============================================================

Matrice X:
[[1 2 5]
 [2 4 6]
 [3 6 7]
 [4 8 8]]
============================================================
TEST DI MULTICOLLINEARITÀ TRAMITE FORMA A GRADINI
============================================================
Matrice dati: 4 esempi, 3 feature
Matrice trasposta (feature come righe): (3, 4)

Numero di pivot trovati: 2
Numero di feature: 3
Matrice risultante è a gradini: True
Numero di condizione di X: 2.77e+16

============================================================
DIAGNOSI:
❌ MULTICOLLINEARITÀ RILEVATA
   Rango: 2 < 3
   Almeno una feature è combinazione lineare delle altre
   Regressione lineare instabile, possibili warning

💡 SUGGERIMENTI:
   1. Rimuovere feature ridondanti
   2. Usare Ridge Regression (L2 regularization)
   3. Applicare PCA per ridurre la dimensionalità
   4. Verificare correlazioni tra feature

⚠️  Attenzione: numero di condizione molto alto (2.77e+16)
   Indica multicollinearità grave anche se il rango è massimo

Matrice a gradini (feature come righe):
[[ 1.  2.  3.  4.]
 [-0.  1.  2.  3.]
 [ 0.  0.  0.  0.]]
Posizioni pivot (riga, colonna): [(0, 0), (1, 1)]

============================================================
TEST: PERFECT_COLLINEAR
============================================================

Matrice X:
[[1 2 3]
 [2 3 5]
 [3 4 7]
 [4 5 9]]
============================================================
TEST DI MULTICOLLINEARITÀ TRAMITE FORMA A GRADINI
============================================================
Matrice dati: 4 esempi, 3 feature
Matrice trasposta (feature come righe): (3, 4)

Numero di pivot trovati: 2
Numero di feature: 3
Matrice risultante è a gradini: True
Numero di condizione di X: 3.95e+16

============================================================
DIAGNOSI:
❌ MULTICOLLINEARITÀ RILEVATA
   Rango: 2 < 3
   Almeno una feature è combinazione lineare delle altre
   Regressione lineare instabile, possibili warning

💡 SUGGERIMENTI:
   1. Rimuovere feature ridondanti
   2. Usare Ridge Regression (L2 regularization)
   3. Applicare PCA per ridurre la dimensionalità
   4. Verificare correlazioni tra feature

⚠️  Attenzione: numero di condizione molto alto (3.95e+16)
   Indica multicollinearità grave anche se il rango è massimo

Matrice a gradini (feature come righe):
[[ 1.  2.  3.  4.]
 [-0.  1.  2.  3.]
 [ 0.  0.  0.  0.]]
Posizioni pivot (riga, colonna): [(0, 0), (1, 1)]

============================================================
TEST: ALMOST_COLLINEAR
============================================================

Matrice X:
[[ 1.     2.001  3.   ]
 [ 2.     4.     6.   ]
 [ 3.     6.002  9.   ]
 [ 4.     8.    12.   ]]
============================================================
TEST DI MULTICOLLINEARITÀ TRAMITE FORMA A GRADINI
============================================================
Matrice dati: 4 esempi, 3 feature
Matrice trasposta (feature come righe): (3, 4)

Numero di pivot trovati: 2
Numero di feature: 3
Matrice risultante è a gradini: True
Numero di condizione di X: 6.34e+16

============================================================
DIAGNOSI:
❌ MULTICOLLINEARITÀ RILEVATA
   Rango: 2 < 3
   Almeno una feature è combinazione lineare delle altre
   Regressione lineare instabile, possibili warning

💡 SUGGERIMENTI:
   1. Rimuovere feature ridondanti
   2. Usare Ridge Regression (L2 regularization)
   3. Applicare PCA per ridurre la dimensionalità
   4. Verificare correlazioni tra feature

⚠️  Attenzione: numero di condizione molto alto (6.34e+16)
   Indica multicollinearità grave anche se il rango è massimo

Matrice a gradini (feature come righe):
[[ 1.   2.   3.   4. ]
 [-0.   1.   0.5  2. ]
 [ 0.   0.   0.   0. ]]
Posizioni pivot (riga, colonna): [(0, 0), (1, 1)]

============================================================
USO PRATICO CON NUOVI DATI
============================================================

1. Inserisci manualmente i dati:
Matrice:
[[1 2 3]
 [4 8 6]
 [2 4 5]
 [3 6 7]]
============================================================
TEST DI MULTICOLLINEARITÀ TRAMITE FORMA A GRADINI
============================================================
Matrice dati: 4 esempi, 3 feature
Matrice trasposta (feature come righe): (3, 4)

Numero di pivot trovati: 2
Numero di feature: 3
Matrice risultante è a gradini: True
Numero di condizione di X: 2.22e+16

============================================================
DIAGNOSI:
❌ MULTICOLLINEARITÀ RILEVATA
   Rango: 2 < 3
   Almeno una feature è combinazione lineare delle altre
   Regressione lineare instabile, possibili warning

💡 SUGGERIMENTI:
   1. Rimuovere feature ridondanti
   2. Usare Ridge Regression (L2 regularization)
   3. Applicare PCA per ridurre la dimensionalità
   4. Verificare correlazioni tra feature

⚠️  Attenzione: numero di condizione molto alto (2.22e+16)
   Indica multicollinearità grave anche se il rango è massimo

============================================================
VERIFICA CON SCKIT-LEARN
============================================================
✅ Scikit-learn ha completato il fit senza errori
   Coefficienti: [-0.18888889 -0.37777778  1.22222222]

Per utilizzarlo con i tuoi dati:

import numpy as np

# Carica i tuoi dati
# X = np.array([...])  # Matrice (esempi × feature)

# Esegui il test
result = check_multicollinearity(X, verbose=True)

L’output mostrerà chiaramente se le feature sono collineari e fornirà indicazioni su come procedere.

Forse potrebbe interessarti anche:  Errori Comuni nelle Distribuzioni di Probabilità: Guida, Esempi Pratici e Correzione di Continuità

Quasi-Collinearità: Quando il “Quasi” è Peggio del “Certo”

In teoria, una matrice o ha rango pieno o non ce l’ha. Nella realtà del Data Science, le feature non sono quasi mai perfettamente collineari (es. [math]X_2 = 2 \cdot X_1[/math]), ma spesso sono quasi collineari (es. [math]X_2 = 2 \cdot X_1 + \epsilon[/math], dove [math]\epsilon[/math] è un rumore piccolissimo).

1. Il Limite della Forma a Gradini

L’algoritmo di Gauss usa una tolleranza (tol) per decidere se un pivot è zero.

  • Se la collinearità è “quasi perfetta”, Gauss vedrà un numero molto piccolo ma diverso da zero e manterrà il pivot.
  • Risultato: La RREF ti dirà che le feature sono indipendenti, ma il tuo modello di regressione si comporterà comunque in modo folle.

2. Che cos’è il Condition Number?

Il numero di condizione di una matrice [math]X[/math] si definisce come il rapporto tra il valore singolare più grande e quello più piccolo ottenuto tramite la SVD (Singular Value Decomposition):

[math]\displaystyle \kappa(X) = \frac{\sigma_{max}}{\sigma_{min}}[/math]

Valore di [math]\kappa[/math] Significato Strategico
[math]\kappa = 1[/math] Feature perfettamente ortogonali (il sogno di ogni DS).
[math]10^3[/math] a [math]10^6[/math] Inizia a esserci “attrito” numerico; instabilità moderata.
[math]> 10^{12}[/math] Matrice ill-conditioned. Siamo in zona pericolo estremo.

Perché il “Quasi” è peggio del “Certo”?

Se due feature sono perfettamente collineari, l’algebra lineare “rompe” il sistema e ti avverte chiaramente (rango ridotto).

Se sono quasi collineari:

  1. Il sistema calcola comunque una soluzione, ma i pesi [math]w[/math] diventano enormi e instabili.
  2. Piccole variazioni nel rumore di input causano oscillazioni gigantesche nell’output.
  3. L’interpretazione dei coefficienti perde senso: il modello non riesce più a distinguere il contributo di una feature dall’altra.

Diagnostica Avanzata: Algebra Lineare come Bussola per il ML

Oltre al calcolo del rango, la forma a gradini ci permette di fare il “tagliando” al nostro dataset.

Forse potrebbe interessarti anche:  Algoritmi Greedy: Una Scelta Ottimale (a Volte)

Ecco come interpretare le anomalie matematiche in ottica Data Science.

Esercizio 2 — Righe Inconsistenti = Dati Contraddittori

Problema: Una matrice aumentata [math][A|b][/math] che, dopo l’eliminazione di Gauss, presenta una riga del tipo [math][0, 0, 0 | k][/math] con [math]k \neq 0[/math].

Versione Data Science: Identificare record che confondono il modello (Target diversi per input identici).

Interpretazione ML:

In un sistema lineare, una riga [math][0, 0, 0 | 5][/math] significa [math]0 = 5[/math]. Impossibile.

Nel Machine Learning, questo accade quando hai due righe nel dataset con feature identiche ma etichette (target) diverse.

Esempio: Due case con la stessa metratura, posizione e anno, ma prezzi drasticamente diversi senza una feature che lo spieghi.

Diagnosi: Il dataset è “rumoroso” o mancano feature deterministiche. Nessun modello potrà mai avere un errore zero qui.

Rappresentazione formale dell’inconsistenza:

[math]\displaystyle \begin{aligned}
\text{Se } \exists i \text{ tale che: } & \sum_{j=1}^{n} a_{ij}x_j = 0 \\
& \text{ma } b_i \neq 0 \\
\implies & \text{Sistema Impossibile}
\end{aligned}[/math]

Insight Critico: Se il sistema è impossibile, il tuo gradiente “impazzirà” cercando di minimizzare la loss tra due target opposti. Non è colpa dell’algoritmo, ma della qualità dei dati.

Esercizio 3 — Variabili Libere = Sotto-determinazione e Overfitting

Problema: La forma a gradini ha meno pivot delle colonne ([math]r < n[/math]).

Versione Data Science: Troppe feature per pochi dati ([math]p > n[/math]).

Interpretazione ML:

Se hai colonne senza pivot, quelle sono “variabili libere”. In ML, questo significa che il modello ha infiniti modi (infinite combinazioni di pesi [math]w[/math]) per mappare [math]X[/math] su [math]y[/math].

Conseguenza: È il paradiso dell’overfitting. Il modello “memorizza” il rumore perché ha troppa libertà di movimento.

Soluzione Matematica: La forma a gradini ti dice esattamente quante e quali sono le feature che stanno creando questa libertà eccessiva.

Insight Critico:

Non è “flessibilità”, è anarchia. Quando vedi variabili libere nella tua matrice, la regolarizzazione (Lasso/Ridge) non è un optional, è l’unico modo per scegliere una soluzione tra le infinite possibili.

Relazione tra Pivot e Dimensionalità:

[math]\displaystyle \begin{aligned}
\text{Dimensione del Kernel (Null Space)} &= n – r \\
&{} \quad \text{(Numero di variabili libere)} \\
\text{Se } n – r > 0 \implies & \text{Infinità di soluzioni } \mathbf{w} \\
& \text{tali che } \mathbf{Xw} = \mathbf{y}
\end{aligned}[/math]


Esercizio 4 — Matrice Identità = Feature Ortogonali (Il Sogno)

Problema: La forma a gradini ridotta (RREF) è una matrice identità [math]I[/math].

Versione Data Science: Feature perfettamente indipendenti e “pulite”.

Interpretazione ML:

Se Gauss ti restituisce una matrice identità, congratulazioni: ogni feature porta un’informazione unica e ortogonale alle altre.

Vantaggio: I coefficienti della tua regressione saranno estremamente interpretabili. Il peso [math]w_1[/math] riflette esattamente l’impatto della feature [math]X_1[/math] senza “contaminazioni” dalle altre.

Realtà: Succede quasi solo dopo aver applicato una PCA (Principal Component Analysis) o un processo di sbiancamento (whitening).

Insight Critico:

L’identità è il punto d’arrivo della Feature Engineering. Se la tua matrice dati originale somiglia già a un’identità, probabilmente hai fatto un lavoro di raccolta dati eccezionale o stai guardando dati sintetici.

Proprietà della Matrice Identità nel Sistema Lineare:

[math]\displaystyle \begin{aligned}
\mathbf{I} \mathbf{w} &= \mathbf{b} \\
\begin{bmatrix}
1 & 0 & 0 \\
0 & 1 & 0 \\
0 & 0 & 1
\end{bmatrix} \begin{bmatrix} w_1 \\ w_2 \\ w_3 \end{bmatrix} &= \begin{bmatrix} b_1 \\ b_2 \\ b_3 \end{bmatrix} \\
\implies w_i &= b_i
\end{aligned}[/math]

In questo scenario, la soluzione è unica e diretta: ogni coefficiente dipende esclusivamente dal proprio target corrispondente.

Forse potrebbe interessarti anche:  Data Analyst Italia 2025: Guida Completa a Stipendi, Carriera e Opportunità

Esercizio 5 — Righe Nulle = Osservazioni Inutili

Problema: Durante l’eliminazione di Gauss, una o più righe si annullano completamente [math][0, 0, 0 | 0][/math].

Versione Data Science: Record duplicati o informazioni che non aggiungono varianza.

Interpretazione ML:

Una riga di zeri significa che quel record era già “scritto” nelle altre righe. In termini matematici, è una combinazione lineare di altri esempi presenti nel dataset.

  • ML Case: Hai duplicati nel dataset o record che, pur non essendo identici, non aggiungono alcuna nuova informazione alla “superficie di decisione” del modello.
  • Efficienza: Elaborare queste righe spreca solo RAM e tempo di calcolo, un fattore critico specialmente quando si lavora su dataset di dimensioni massicce.

Insight Critico:

In un’epoca di “Big Data”, spesso accumuliamo righe sperando che la quantità batta la qualità. Gauss ci ricorda che se una riga si annulla, stai solo facendo fare ginnastica inutile alla tua CPU. La ridondanza non è solo inutile, è costosa.

Rappresentazione del Rango e Ridondanza:

[math]\displaystyle \begin{aligned}
\text{Rango}(A) &= r < m \\
&{} \quad \text{(m = numero totale di righe)} \\
\text{Righe Nulle} &= m – r \\
&{} \quad \text{(Informazioni ridondanti eliminate)}
\end{aligned}[/math]

Quando il rango [math]r[/math] è inferiore al numero di righe [math]m[/math], la matrice non è a rango pieno, indicando che il dataset contiene “eco” di informazioni già presenti.


Esercizio 6 — Forma Ridotta (RREF) = Feature Selection Implicita

Problema: Trasformare una matrice in forma a gradini ridotta (Reduced Row Echelon Form).

Versione Data Science: Capire quali feature “comandano” le altre.

Interpretazione ML:

La RREF non si limita a dirti se c’è dipendenza, ma esprime le variabili dipendenti come combinazione di quelle indipendenti (i pivot).

  • Esempio: Se la colonna 3 non ha un pivot, la RREF ti mostrerà coefficienti come [math]X_3 = 0.5 X_1 + 2 X_2[/math].
  • Applicazione: Questo è l’algoritmo di “compressione” più vecchio del mondo. Ti dice che puoi eliminare [math]X_3[/math] senza perdere un briciolo di informazione, perché è totalmente ricostruibile dalle altre due.

Insight Critico:

Prima di usare algoritmi complessi di Feature Selection, una passata di RREF ti direbbe già chi è il “capo” (pivot) e chi è solo un “eco” (variabile libera). È algebra lineare pura, non black box.

Relazione Matematica nella RREF:

[math]\displaystyle \begin{aligned}
\text{Data una matrice } R = \text{RREF}(A): & \\
\mathbf{r}_j = \sum_{i \in \text{Pivots}} c_i \mathbf{r}_i \\
&{} \quad \text{(Dove } \mathbf{r}_j \text{ è una colonna senza pivot)}
\end{aligned}[/math]

In questo stato, ogni colonna pivot è un vettore della base canonica [math]\mathbf{e}_i[/math], rendendo immediata la lettura delle relazioni di dipendenza tra le feature originali.

Come calcolare la RREF in Python usando la libreria SymPy per identificare esattamente quali colonne del tuo dataset sono ridondanti

Mentre NumPy è il re del calcolo numerico, quando si tratta di diagnostica strutturale e di trovare la forma a gradini ridotta (RREF), la libreria SymPy è lo strumento superiore.

Il motivo è semplice: NumPy lavora con i numeri in virgola mobile (floating point), che possono generare errori di arrotondamento rendendo difficile capire se un valore è “zero” o solo un numero molto piccolo. SymPy, invece, esegue calcoli simbolici esatti.

Ecco come implementare il test del DNA del tuo dataset.

Identificare Feature Ridondanti con SymPy

Immaginiamo di avere un dataset dove la terza colonna è esattamente la somma delle prime due (ridondanza perfetta).

import numpy as np
from sympy import Matrix

# 1. Creiamo un dataset di esempio (4 osservazioni, 3 feature)
# Feature 3 = Feature 1 + Feature 2 (Ridondante!)
data = np.array([
[1, 2, 3],
[2, 3, 5],
[3, 4, 7],
[4, 5, 9]
])

# 2. Convertiamo in una matrice SymPy
# Nota: SymPy preferisce lavorare con frazioni esatte
sympy_matrix = Matrix(data)

# 3. Calcoliamo la RREF
# rref() restituisce una tupla: (la matrice a gradini, gli indici dei pivot)
rref_matrix, pivot_indices = sympy_matrix.rref()

print(f"Matrice RREF:\n{rref_matrix}")
print(f"\nIndici delle colonne Pivot (Indipendenti): {pivot_indices}")

# 4. Identifichiamo le colonne da eliminare
all_indices = range(data.shape[1])
redundant_indices = [i for i in all_indices if i not in pivot_indices]

print(f"Colonne ridondanti rilevate: {redundant_indices}")

# 5. Pulizia del dataset originale
clean_data = data[:, pivot_indices]
print(f"\nDataset pulito (solo colonne indipendenti):\n{clean_data}")
Matrice RREF:
Matrix([[1, 0, 1], [0, 1, 1], [0, 0, 0], [0, 0, 0]])

Indici delle colonne Pivot (Indipendenti): (0, 1)
Colonne ridondanti rilevate: [2]

Dataset pulito (solo colonne indipendenti):
[[1 2]
 [2 3]
 [3 4]
 [4 5]]

Perché questo metodo è un “Superpotere” per un Data Scientist

Quando esegui .rref(), SymPy ti restituisce due elementi fondamentali:

  1. La Matrice RREF: Ti mostra visivamente come le variabili dipendenti sono costruite. Se una colonna non ha un pivot, vedrai i coefficienti esatti che la legano alle altre.

  2. Gli Indici dei Pivot (pivot_indices): Questa è la tua “lista della spesa” per la Feature Selection. Qualsiasi colonna il cui indice NON è in questa lista è matematicamente superflua. Non aggiunge varianza, aggiunge solo rumore e complessità computazionale.

Quando usare SymPy vs NumPy/Scikit-Learn?

Situazione Strumento consigliato Perché?
Debug del Dataset SymPy.rref() Analisi esatta, identifica dipendenze lineari matematiche.
Dataset enorme (+10k feature) SVD (NumPy/SciPy) Più veloce, gestisce la “quasi-collinearità” numerica.
Produzione / Training Scikit-learn Ottimizzato per la velocità, non per la diagnostica strutturale.

⚠️ Attenzione: SymPy è lento su matrici gigantesche perché calcola tutto in modo esatto. Usalo nelle fasi di Exploratory Data Analysis (EDA) su un campione significativo del tuo dataset per capire se il tuo processo di data collection sta creando duplicati logici.

I “sintomi” matematici e la loro “malattia” nel ML:

Sintomo Matematico (Gauss/RREF) Diagnosi Data Science Impatto sul Modello
Meno Pivot delle Colonne Multicollinearità / Ridondanza Pesi w instabili, overfitting.
Riga Inconsistente [0..0 \| k Dati Contraddittori Errore minimo non nullo (Rumore alto).
Righe Nulle [0..0 \| 0 Record Duplicati Spreco di memoria e computazione.
Matrice Identità I Feature Ortogonali Massima interpretabilità dei coefficienti.
Variabili Libere Sotto-determinazione Il modello “inventa” pattern (Overfitting).

Pubblicità