Regressione Lineare: Il Fondamento del Machine Learning
La regressione lineare è l'algoritmo più semplice e fondamentale del Machine Learning supervisionato. Il suo obiettivo è trovare la relazione lineare tra una o più variabili indipendenti (feature) e una variabile dipendente (target) continua. Nonostante la sua semplicità, è uno strumento potentissimo e rappresenta la base su cui si costruiscono algoritmi molto più complessi.
Matematicamente, la regressione lineare semplice modella la relazione come y = wx + b, dove w è il peso (slope) e b è il bias (intercetta). Per più feature si estende a y = w1*x1 + w2*x2 + ... + wn*xn + b. L'algoritmo cerca i valori di w e b che minimizzano l'errore tra le previsioni e i valori reali.
Cosa Imparerai in Questo Articolo
- Come funziona la regressione lineare e la sua formulazione matematica
- Il metodo dei minimi quadrati (Least Squares)
- La regressione logistica per problemi di classificazione
- Il Gradient Descent: come gli algoritmi apprendono
- Implementazione completa in Python con scikit-learn
- Metriche di valutazione per regressione e classificazione
La Cost Function: Misurare l'Errore
Per trovare i parametri ottimali, abbiamo bisogno di una funzione che misuri quanto il nostro modello sbaglia: la cost function (o loss function). Per la regressione lineare, la cost function standard è il Mean Squared Error (MSE), che calcola la media dei quadrati delle differenze tra valori predetti e valori reali.
L'MSE penalizza maggiormente gli errori grandi grazie all'elevamento al quadrato: un errore di 10 pesa 100 volte più di un errore di 1. Questo rende il modello sensibile agli outlier. Alternative come il Mean Absolute Error (MAE) sono più robuste agli outlier ma meno smooth matematicamente.
import numpy as np
# Dataset semplice: area casa (m2) -> prezzo (migliaia euro)
X = np.array([50, 70, 80, 100, 120, 150])
y = np.array([150, 200, 220, 280, 330, 400])
# Calcolo parametri con metodo dei minimi quadrati (OLS)
n = len(X)
x_mean = np.mean(X)
y_mean = np.mean(y)
# w = sum((xi - x_mean)(yi - y_mean)) / sum((xi - x_mean)^2)
numerator = np.sum((X - x_mean) * (y - y_mean))
denominator = np.sum((X - x_mean) ** 2)
w = numerator / denominator
b = y_mean - w * x_mean
print(f"Peso (w): {w:.2f}") # ~2.5 (ogni m2 vale ~2500 euro)
print(f"Bias (b): {b:.2f}") # intercetta
# Predizione per una casa di 90 m2
prezzo_90 = w * 90 + b
print(f"Prezzo stimato per 90m2: {prezzo_90:.0f}k euro")
# Calcolo MSE
predictions = w * X + b
mse = np.mean((y - predictions) ** 2)
print(f"MSE: {mse:.2f}")
Gradient Descent: Come gli Algoritmi Apprendono
Il Gradient Descent è l'algoritmo di ottimizzazione più importante nel ML. Invece di risolvere analiticamente l'equazione (come con i minimi quadrati), il gradient descent trova i parametri ottimali iterativamente, muovendosi nella direzione che riduce maggiormente la cost function.
Funziona così: si parte da parametri casuali, si calcola il gradiente (la derivata parziale della cost function rispetto a ciascun parametro), e si aggiornano i parametri nella direzione opposta al gradiente. Il learning rate controlla la dimensione di ogni passo: troppo grande e l'algoritmo oscilla senza convergere, troppo piccolo e la convergenza è lentissima.
import numpy as np
def gradient_descent(X, y, learning_rate=0.0001, epochs=1000):
"""Gradient descent per regressione lineare."""
w = 0.0 # peso iniziale
b = 0.0 # bias iniziale
n = len(X)
for epoch in range(epochs):
# Predizioni attuali
y_pred = w * X + b
# Calcolo gradienti (derivate parziali della MSE)
dw = (-2/n) * np.sum(X * (y - y_pred))
db = (-2/n) * np.sum(y - y_pred)
# Aggiornamento parametri
w -= learning_rate * dw
b -= learning_rate * db
if epoch % 200 == 0:
mse = np.mean((y - y_pred) ** 2)
print(f"Epoch {epoch}: MSE={mse:.2f}, w={w:.4f}, b={b:.4f}")
return w, b
# Uso
X = np.array([50, 70, 80, 100, 120, 150], dtype=float)
y = np.array([150, 200, 220, 280, 330, 400], dtype=float)
w_opt, b_opt = gradient_descent(X, y)
print(f"\nParametri ottimali: w={w_opt:.4f}, b={b_opt:.4f}")
Regressione Logistica: Da Regressione a Classificazione
Nonostante il nome, la regressione logistica è un algoritmo di classificazione. Trasforma l'output della regressione lineare in una probabilità tra 0 e 1 usando la funzione sigmoid: σ(z) = 1 / (1 + e^(-z)). Se la probabilità supera una soglia (tipicamente 0.5), il campione viene classificato come positivo, altrimenti come negativo.
La cost function della regressione logistica è la Binary Cross-Entropy (o Log Loss), che penalizza le predizioni confidenti ma sbagliate. Il gradient descent viene usato anche qui per ottimizzare i parametri. La regressione logistica è sorprendentemente efficace e viene usata come baseline in moltissimi problemi di classificazione.
from sklearn.linear_model import LogisticRegression, LinearRegression
from sklearn.model_selection import train_test_split
from sklearn.metrics import (
accuracy_score, precision_score, recall_score,
mean_squared_error, mean_absolute_error, r2_score
)
from sklearn.datasets import load_breast_cancer
import numpy as np
# --- CLASSIFICAZIONE con Regressione Logistica ---
data = load_breast_cancer()
X, y = data.data, data.target
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42
)
# Training
log_reg = LogisticRegression(max_iter=10000, random_state=42)
log_reg.fit(X_train, y_train)
# Valutazione
y_pred = log_reg.predict(X_test)
print("=== Regressione Logistica (Classificazione) ===")
print(f"Accuracy: {accuracy_score(y_test, y_pred):.3f}")
print(f"Precision: {precision_score(y_test, y_pred):.3f}")
print(f"Recall: {recall_score(y_test, y_pred):.3f}")
# Probabilità' di classe
probabilities = log_reg.predict_proba(X_test)[:5]
print(f"\nPrime 5 probabilità':\n{probabilities}")
# --- REGRESSIONE con Regressione Lineare ---
from sklearn.datasets import fetch_california_housing
housing = fetch_california_housing()
X_h, y_h = housing.data, housing.target
X_train_h, X_test_h, y_train_h, y_test_h = train_test_split(
X_h, y_h, test_size=0.2, random_state=42
)
lin_reg = LinearRegression()
lin_reg.fit(X_train_h, y_train_h)
y_pred_h = lin_reg.predict(X_test_h)
print("\n=== Regressione Lineare ===")
print(f"MSE: {mean_squared_error(y_test_h, y_pred_h):.3f}")
print(f"MAE: {mean_absolute_error(y_test_h, y_pred_h):.3f}")
print(f"R2: {r2_score(y_test_h, y_pred_h):.3f}")
Visualizzazione del Decision Boundary
Il decision boundary è la frontiera che separa le classi nello spazio delle feature. Per la regressione logistica con due feature, è una linea retta. Visualizzarlo aiuta a capire come il modello prende decisioni e dove commette errori. Con più di due feature, il boundary diventa un iperpiano nello spazio multidimensionale, ma il concetto resta lo stesso.
Regressione lineare vs logistica: La regressione lineare predice valori continui (prezzi, temperature, vendite). La regressione logistica predice probabilità di appartenenza a una classe. Usarle nel contesto sbagliato è uno degli errori più comuni tra i principianti del ML.
Metriche di Valutazione
Per la regressione si usano: MSE (Mean Squared Error), MAE (Mean Absolute Error), RMSE (Root MSE) e R² (coefficiente di determinazione, che indica la proporzione di varianza spiegata dal modello).
Per la classificazione: Accuracy (percentuale di previsioni corrette), Precision (quanti dei positivi predetti sono corretti), Recall (quanti dei positivi reali sono stati trovati) e F1-Score (media armonica di precision e recall). Approfondiremo ciascuna metrica in un articolo dedicato della serie.
Punti Chiave
- La regressione lineare trova la relazione y = wx + b minimizzando il MSE
- Il Gradient Descent ottimizza iterativamente i parametri nella direzione del gradiente negativo
- Il learning rate controlla la velocità di convergenza: troppo grande o troppo piccolo causa problemi
- La regressione logistica usa la sigmoid per trasformare la regressione lineare in classificazione
- MSE/MAE/R² per regressione, Accuracy/Precision/Recall/F1 per classificazione
- Questi due algoritmi sono la base su cui si costruiscono tecniche più avanzate







