W3docs

Regressione Lineare

Scopri come funziona la regressione lineare, la matematica alla base e come implementarla in Python con scikit-learn, semplice e multipla.

La regressione lineare è uno degli algoritmi più fondamentali nel machine learning. Modella la relazione tra una variabile dipendente (ciò che si vuole prevedere) e una o più variabili indipendenti (gli input) adattando una linea retta — o un iperpiano — ai dati.

Questa pagina copre:

  • Come funzionano matematicamente la regressione lineare semplice e quella multipla
  • Il metodo dei minimi quadrati ordinari (OLS) per adattare una retta
  • Le assunzioni fondamentali da verificare prima di fidarsi del modello
  • Una guida completa con scikit-learn: caricare i dati, addestrare, valutare e interpretare i risultati
  • Come leggere i coefficienti del modello e individuare le insidie più comuni

Come Funziona la Regressione Lineare

L'Equazione

La regressione lineare semplice (una sola variabile di input) adatta questa retta:

y = β₀ + β₁x + ε
  • y — la variabile dipendente (target)
  • x — la variabile indipendente (feature)
  • β₀ — l'intercetta (valore di y quando x = 0)
  • β₁ — la pendenza (variazione di y per un aumento unitario di x)
  • ε — il termine di errore (rumore che il modello non riesce a spiegare)

La regressione lineare multipla estende questo concetto a n feature:

y = β₀ + β₁x₁ + β₂x₂ + ... + βₙxₙ + ε

Ogni coefficiente βᵢ indica di quanto cambia y quando xᵢ aumenta di un'unità, mantenendo costanti tutte le altre feature.

Minimi Quadrati Ordinari (OLS)

Il modello apprende i coefficienti minimizzando la somma dei residui al quadrato — la differenza tra ogni valore reale yᵢ e la previsione del modello ŷᵢ:

SSR = Σ(yᵢ - ŷᵢ)²

L'elevamento al quadrato dei residui penalizza gli errori grandi più di quelli piccoli e garantisce che gli errori positivi e negativi non si annullino a vicenda. Questo criterio ha una soluzione in forma chiusa esatta, motivo per cui la regressione lineare si addestra quasi istantaneamente anche su dataset di grandi dimensioni.

Assunzioni Fondamentali

La regressione lineare produce previsioni affidabili solo quando valgono queste condizioni:

AssunzioneCosa verificare
LinearitàLa relazione tra le feature e il target è approssimativamente lineare
IndipendenzaLe osservazioni sono indipendenti tra loro
OmoschedasticitàLa varianza dei residui è circa costante su tutte le previsioni
Normalità dei residuiI residui sono distribuiti approssimativamente in modo normale
Assenza di multicollinearitàLe variabili indipendenti non sono altamente correlate tra loro

Quando queste assunzioni vengono violate, le stime dei coefficienti possono essere distorte oppure il modello può avere prestazioni scarse su dati nuovi.

Esempio di Regressione Lineare Semplice

Prima di passare a più feature, vediamo come l'algoritmo adatta una retta a una singola feature. Questo rende la geometria facile da visualizzare.

import numpy as np
import matplotlib
matplotlib.use('Agg')  # non-interactive backend for scripts
import matplotlib.pyplot as plt
from sklearn.linear_model import LinearRegression

# Simulate: house size (sq ft) vs price ($1000s)
rng = np.random.default_rng(42)
X_simple = rng.uniform(500, 3000, 50).reshape(-1, 1)
y_simple = 50 + 0.1 * X_simple.ravel() + rng.normal(0, 15, 50)

model = LinearRegression()
model.fit(X_simple, y_simple)

print(f"Intercept (β₀): {model.intercept_:.2f}")
print(f"Slope    (β₁): {model.coef_[0]:.4f}")
print(f"Interpretation: each extra sq ft adds ${model.coef_[0]*1000:.0f} to the predicted price")

Output atteso:

Intercept (β₀): 46.17
Slope    (β₁): 0.1007
Interpretation: each extra sq ft adds $101 to the predicted price

I valori di intercetta e pendenza vengono recuperati automaticamente dall'OLS — non è necessario eseguire alcun calcolo algebrico manualmente.

Regressione Lineare Multipla con scikit-learn

I dataset reali hanno molte feature. Questa sezione illustra una pipeline completa sul dataset California Housing, che registra statistiche abitative a livello di blocco censimento per la California nel 1990.

Passo 1: Importare le Librerie

import pandas as pd
import numpy as np
from sklearn.datasets import fetch_california_housing
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error, r2_score

Passo 2: Caricare ed Esplorare il Dataset

california = fetch_california_housing()
df = pd.DataFrame(california.data, columns=california.feature_names)
df['MedHouseVal'] = california.target  # median house value in $100,000s

print(df.shape)          # (20640, 9)
print(df.head())
print(df.describe())

Il dataset ha 20.640 righe e 8 feature di input:

FeatureDescrizione
MedIncReddito mediano nel blocco (in decine di migliaia di dollari)
HouseAgeEtà mediana delle abitazioni nel blocco
AveRoomsNumero medio di stanze per nucleo familiare
AveBedrmsNumero medio di camere da letto per nucleo familiare
PopulationPopolazione del blocco
AveOccupOccupazione media per nucleo familiare
LatitudeLatitudine del blocco
LongitudeLongitudine del blocco

Il target MedHouseVal è il valore mediano delle abitazioni in unità da $100.000.

Passo 3: Scegliere le Feature e Dividere i Dati

Per una dimostrazione semplice, utilizziamo tutte e 8 le feature. Vedi Train/Test Split per una spiegazione dettagliata del motivo per cui si dividono i dati.

X = df[california.feature_names]   # all 8 features
y = df['MedHouseVal']

X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, random_state=42
)

print(f"Training samples: {len(X_train)}")   # 16512
print(f"Test samples:     {len(X_test)}")    # 4128

Il parametro random_state=42 garantisce suddivisioni riproducibili ogni volta che si esegue lo script.

Passo 4: Addestrare il Modello

model = LinearRegression()
model.fit(X_train, y_train)

È tutto ciò che occorre. Il metodo fit() risolve il problema OLS analiticamente usando l'algebra matriciale — non è previsto alcun gradient descent iterativo per impostazione predefinita.

Passo 5: Ispezionare i Coefficienti Appresi

Capire ciò che il modello ha appreso è importante quanto la sua accuratezza:

coef_df = pd.DataFrame({
    'Feature': california.feature_names,
    'Coefficient': model.coef_
}).sort_values('Coefficient', key=abs, ascending=False)

print(coef_df.to_string(index=False))
print(f"\nIntercept: {model.intercept_:.4f}")

Output tipico:

   Feature  Coefficient
 AveBedrms     0.7831
    MedInc     0.4487
 Longitude    -0.4337
  Latitude    -0.4198
  AveRooms    -0.1233
  HouseAge     0.0097
  AveOccup    -0.0035
Population    -0.0000

Intercept: -37.0233

Lettura dei coefficienti:

  • AveBedrms = 0.783: un aumento unitario nel numero medio di camere da letto prevede un aumento di $78.300 nel valore dell'abitazione — ma questo è intrecciato con AveRooms (sono correlati). Quando feature correlate sono entrambe presenti, i singoli coefficienti possono diventare grandi, instabili o addirittura controintuitivi. Questo è il fenomeno della multicollinearità.
  • MedInc = 0.449: un aumento unitario del reddito mediano (circa $10.000) prevede un aumento di $44.900 nel valore dell'abitazione, a parità di tutte le altre condizioni.
  • Longitude = -0.434 e Latitude = -0.420: controlli puramente geografici; il modello li utilizza per catturare gli effetti della posizione anche se non riesce a modellare bene la geografia non lineare.

Passo 6: Valutare il Modello

y_pred = model.predict(X_test)

mse  = mean_squared_error(y_test, y_pred)
rmse = np.sqrt(mse)
r2   = r2_score(y_test, y_pred)

print(f"RMSE: {rmse:.4f}  (in $100,000s, so ±${rmse*100_000:,.0f})")
print(f"R²:   {r2:.4f}")

Output atteso:

RMSE: 0.7456  (in $100,000s, so ±$74,560)
R²:   0.5758

Interpretazione delle metriche:

  • RMSE (Root Mean Squared Error) — l'errore medio di previsione nelle stesse unità del target. Valori più bassi sono migliori.
  • R² (coefficiente di determinazione) — la proporzione di varianza in y spiegata dal modello. Un R² di 0,58 significa che il modello spiega circa il 58% della varianza nei prezzi delle abitazioni. Valori vicini a 1,0 sono migliori; valori vicini a 0 indicano che il modello è a malapena migliore della previsione della media.

Un R² di ~0,58 è tipico per questo dataset con la regressione lineare. La relazione tra i prezzi delle abitazioni e queste feature è in parte non lineare, motivo per cui metodi come la regressione polinomiale o il gradient boosting ottengono spesso punteggi più alti.

Passo 7: Visualizzare i Valori Previsti vs Effettivi

Il grafico diagnostico più chiaro per un modello di regressione è previsto vs effettivo — funziona indipendentemente dal numero di feature che si hanno:

import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt

plt.figure(figsize=(7, 5))
plt.scatter(y_test, y_pred, alpha=0.3, s=10, color='steelblue')
plt.plot([y_test.min(), y_test.max()],
         [y_test.min(), y_test.max()],
         'r--', linewidth=1.5, label='Perfect prediction')
plt.xlabel('Actual Median House Value ($100,000s)')
plt.ylabel('Predicted Median House Value ($100,000s)')
plt.title('Linear Regression: Predicted vs Actual')
plt.legend()
plt.tight_layout()
plt.savefig('lr_predicted_vs_actual.png', dpi=120)
print("Plot saved.")

I punti che cadono sulla linea tratteggiata rossa sono previsioni perfette. La dispersione attorno alla linea mostra l'errore. Una forma a ventaglio (dispersione più ampia per valori più alti) segnala eteroschedasticità — una delle assunzioni fondamentali è violata.

Pipeline Completa (Tutti i Passi Insieme)

import pandas as pd
import numpy as np
from sklearn.datasets import fetch_california_housing
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error, r2_score

# Load data
california = fetch_california_housing()
df = pd.DataFrame(california.data, columns=california.feature_names)
df['MedHouseVal'] = california.target

# Split
X = df[california.feature_names]
y = df['MedHouseVal']
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# Train
model = LinearRegression()
model.fit(X_train, y_train)

# Evaluate
y_pred = model.predict(X_test)
rmse = np.sqrt(mean_squared_error(y_test, y_pred))
r2   = r2_score(y_test, y_pred)

print(f"RMSE: {rmse:.4f}")
print(f"R²:   {r2:.4f}")

Quando Usare la Regressione Lineare

La regressione lineare è una buona prima scelta quando:

  • La relazione tra input e output è approssimativamente lineare
  • L'interpretabilità è importante — è necessario spiegare le previsioni agli stakeholder
  • Il dataset è di dimensioni piccole o medie e la velocità di addestramento è importante
  • Si desidera una baseline rapida prima di provare modelli più complessi

Considera delle alternative quando:

  • Le feature e il target hanno relazioni fortemente non lineari → prova la regressione polinomiale o gli alberi decisionali
  • Hai molte feature che potrebbero essere irrilevanti → le varianti regolarizzate (Ridge, Lasso) prevengono l'overfitting riducendo i coefficienti
  • Il target è una categoria, non un numero → usa invece la regressione logistica

Insidie Comuni

Dimenticare di scalare le feature. I coefficienti della regressione lineare riflettono le unità di ciascuna feature. Se una feature è espressa in migliaia e un'altra in frazioni, le dimensioni dei coefficienti grezzi non sono comparabili. Usa StandardScaler prima di confrontare le importanze delle feature. Vedi Feature Scaling per i dettagli.

Multicollinearità. Feature altamente correlate rendono i singoli coefficienti inaffidabili — possono persino cambiare segno. Controlla la matrice di correlazione con df.corr() e rimuovi o combina le feature correlate.

Estrapolazione. Un modello lineare addestrato su dati in un certo intervallo può fornire previsioni completamente errate al di fuori di quell'intervallo. Verifica sempre che i nuovi input ricadano nella distribuzione di addestramento.

Ignorare i grafici dei residui. Traccia sempre i residui dopo l'adattamento. I pattern nei residui (curve, ventagli, cluster di outlier) indicano che le assunzioni del modello sono violate e le previsioni non dovrebbero essere considerate affidabili senza ulteriori indagini.

Passi Successivi

Una volta ottenuta una baseline di regressione lineare funzionante, esplora questi argomenti correlati:

  • Multiple Regression — approfondimento sull'uso di più feature e sull'interpretazione di ciascun coefficiente
  • Polynomial Regression — adatta curve invece di rette aggiungendo termini di feature polinomiali
  • Train/Test Split — comprendi perché e come valutare correttamente le prestazioni del modello
  • Feature Scaling — standardizza gli input affinché i coefficienti e i solver basati su gradiente si comportino correttamente
  • Logistic Regression — prevedi categorie (sì/no, spam/non-spam) invece di valori continui
Was this page helpful?