🏠 Regressione Lineare per Previsione Prezzi Immobili

Impara Machine Learning predittivo con Scikit-Learn e dataset reali

Introduzione

Benvenuto nella tua prima esercitazione di Machine Learning! Imparerai a costruire un modello di regressione lineare che predice i prezzi delle case basandosi su caratteristiche come metratura, numero di camere e posizione. Useremo Scikit-Learn, la libreria Python più popolare per il ML.

Scenario Reale:
Lavorerai come Data Scientist per un’agenzia immobiliare che vuole automatizzare la stima dei prezzi delle case. Costruirai un modello ML che impara dai dati storici e fa previsioni accurate.

⚠️ ATTENZIONE: COPIA BLOCCATA

Il codice è protetto da sistema anti-copia. Dovrai SCRIVERE manualmente tutto il codice per imparare veramente! 🚫📋

Parte 1: Setup e Dataset

▶ Importazione Librerie ML

1
Crea una nuova cella su Google Colab e importa le librerie:
PYTHON
# IMPORT LIBRERIE PER MACHINE LEARNING
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_absolute_error, mean_squared_error, r2_score

# Configurazione visualizzazione
sns.set_style("whitegrid")
plt.rcParams['figure.figsize'] = (12, 8)

print("✅ Librerie ML importate correttamente!")
print("📊 Librerie disponibili:")
print(f"  • NumPy: {np.__version__}")
print(f"  • Pandas: {pd.__version__}")
print(f"  • Scikit-Learn: importato")

▶ Creazione Dataset Immobiliare

2
Crea il dataset di case per il training:
PYTHON
# 2. CREAZIONE DATASET IMMOBILIARE DI ESEMPIO
np.random.seed(42)  # Per risultati riproducibili

# Genera dati sintetici realistici
n_case = 100

# Caratteristiche (features)
metratura = np.random.randint(50, 300, n_case)  # m²
camere = np.random.randint(1, 6, n_case)        # numero camere
bagni = np.random.randint(1, 4, n_case)         # numero bagni
eta = np.random.randint(0, 50, n_case)          # anni costruzione
zona = np.random.choice([1, 2, 3], n_case, p=[0.3, 0.5, 0.2])  # 1=centro, 2=periferia, 3=suburbano

# Calcola prezzo base (target variable)
# Formula: prezzo = 2000*metratura + 30000*camere + 20000*bagni - 1000*eta + 50000*zona + rumore
prezzo_base = (2000 * metratura + 
               30000 * camere + 
               20000 * bagni - 
               1000 * eta + 
               50000 * zona)

# Aggiungi rumore casuale
rumore = np.random.randn(n_case) * 50000
prezzo = prezzo_base + rumore

# Crea DataFrame Pandas
df_case = pd.DataFrame({
    'metratura': metratura,
    'camere': camere,
    'bagni': bagni,
    'eta': eta,
    'zona': zona,
    'prezzo': prezzo
})

# Converti zona in categorie
df_case['zona_desc'] = df_case['zona'].map({1: 'Centro', 2: 'Periferia', 3: 'Suburbano'})

print("🏠 DATASET IMMOBILIARE CREATO")
print("="*50)
print(f"Numero case nel dataset: {len(df_case)}")
print("\nPrime 5 righe del dataset:")
print(df_case.head())
print("\n📊 Statistiche descrittive:")
print(df_case.describe())

Parte 2: Analisi Esplorativa dei Dati (EDA)

▶ Visualizzazione Relazioni

3
Analizza le relazioni tra variabili:
PYTHON
# 3. ANALISI ESPLORATIVA DEI DATI (EDA)
print("🔍 ANALISI ESPLORATIVA DATI IMMOBILIARI")
print("="*50)

# 3.1 Distribuzione prezzi
print("\n📈 DISTRIBUZIONE PREZZI:")
print(f"Prezzo medio: €{df_case['prezzo'].mean():,.0f}")
print(f"Prezzo mediano: €{df_case['prezzo'].median():,.0f}")
print(f"Prezzo minimo: €{df_case['prezzo'].min():,.0f}")
print(f"Prezzo massimo: €{df_case['prezzo'].max():,.0f}")
print(f"Deviazione standard: €{df_case['prezzo'].std():,.0f}")

# 3.2 Correlazioni tra variabili
print("\n📊 MATRICE DI CORRELAZIONE:")
correlation_matrix = df_case[['metratura', 'camere', 'bagni', 'eta', 'zona', 'prezzo']].corr()
print(correlation_matrix.round(2))

# 3.3 Visualizzazione grafica
print("\n🎨 CREAZIONE GRAFICI DI ANALISI...")

# Configura subplots
fig, axes = plt.subplots(2, 3, figsize=(15, 10))
fig.suptitle('Analisi Dataset Immobiliare', fontsize=16, fontweight='bold')

# 1. Distribuzione prezzi
axes[0, 0].hist(df_case['prezzo'], bins=20, edgecolor='black', alpha=0.7, color='skyblue')
axes[0, 0].set_title('Distribuzione Prezzi Case')
axes[0, 0].set_xlabel('Prezzo (€)')
axes[0, 0].set_ylabel('Frequenza')

# 2. Prezzo vs Metratura
axes[0, 1].scatter(df_case['metratura'], df_case['prezzo'], alpha=0.6, color='green')
axes[0, 1].set_title('Prezzo vs Metratura')
axes[0, 1].set_xlabel('Metratura (m²)')
axes[0, 1].set_ylabel('Prezzo (€)')

# 3. Prezzo vs Numero Camere
box_data = [df_case[df_case['camere'] == i]['prezzo'] for i in sorted(df_case['camere'].unique())]
axes[0, 2].boxplot(box_data, labels=sorted(df_case['camere'].unique()))
axes[0, 2].set_title('Prezzo vs Numero Camere')
axes[0, 2].set_xlabel('Numero Camere')
axes[0, 2].set_ylabel('Prezzo (€)')

# 4. Prezzo vs Zona
zone_prezzi = df_case.groupby('zona_desc')['prezzo'].mean()
colors = ['gold', 'lightcoral', 'lightgreen']
axes[1, 0].bar(zone_prezzi.index, zone_prezzi.values, color=colors)
axes[1, 0].set_title('Prezzo Medio per Zona')
axes[1, 0].set_xlabel('Zona')
axes[1, 0].set_ylabel('Prezzo Medio (€)')
axes[1, 0].tick_params(axis='x', rotation=45)

# 5. Heatmap Correlazioni
im = axes[1, 1].imshow(correlation_matrix.values, cmap='coolwarm', aspect='auto')
axes[1, 1].set_title('Matrice di Correlazione')
axes[1, 1].set_xticks(range(len(correlation_matrix.columns)))
axes[1, 1].set_yticks(range(len(correlation_matrix.columns)))
axes[1, 1].set_xticklabels(correlation_matrix.columns, rotation=45)
axes[1, 1].set_yticklabels(correlation_matrix.columns)
plt.colorbar(im, ax=axes[1, 1])

# 6. Prezzo vs Età Costruzione
axes[1, 2].scatter(df_case['eta'], df_case['prezzo'], alpha=0.6, color='purple')
axes[1, 2].set_title('Prezzo vs Età Costruzione')
axes[1, 2].set_xlabel('Età (anni)')
axes[1, 2].set_ylabel('Prezzo (€)')

plt.tight_layout()
plt.show()

print("✅ Analisi EDA completata con successo!")

Parte 3: Preparazione Dati per Machine Learning

▶ Split Train/Test e Preprocessing

4
Prepara i dati per il modello ML:
PYTHON
# 4. PREPARAZIONE DATI PER MACHINE LEARNING
print("⚙️  PREPARAZIONE DATI PER IL MODELLO")
print("="*50)

# 4.1 Definizione Features (X) e Target (y)
# Selezioniamo le caratteristiche più rilevanti
features = ['metratura', 'camere', 'bagni', 'eta', 'zona']
X = df_case[features]
y = df_case['prezzo']

print(f"\nFeatures selezionate: {features}")
print(f"Dimensione X (features): {X.shape}")
print(f"Dimensione y (target): {y.shape}")

# 4.2 Split in Train e Test set
# Usiamo 80% per training e 20% per testing
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, random_state=42
)

print(f"\n📊 SPLIT DATI COMPLETATO:")
print(f"  Training set: {X_train.shape[0]} case ({X_train.shape[0]/len(df_case)*100:.0f}%)")
print(f"  Test set: {X_test.shape[0]} case ({X_test.shape[0]/len(df_case)*100:.0f}%)")

# 4.3 Mostra esempio dati di training
print("\n📋 ESEMPIO DATI DI TRAINING (prime 3 righe):")
train_sample = pd.concat([X_train.head(3), y_train.head(3)], axis=1)
print(train_sample)

# 4.4 Normalizzazione delle features (opzionale per regressione lineare)
# Per regressione lineare, spesso non serve normalizzazione
# ma la mostriamo per completezza
from sklearn.preprocessing import StandardScaler

scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)

print("\n🔢 NORMALIZZAZIONE COMPLETATA")
print("  Features scalate con media=0 e deviazione=1")

Parte 4: Addestramento Modello di Regressione

▶ Creazione e Training Modello

5
Crea e addestra il modello di regressione:
PYTHON
# 5. ADDESTRAMENTO MODELLO DI REGRESSIONE LINEARE
print("🤖 ADDESTRAMENTO MODELLO ML")
print("="*50)

# 5.1 Creazione modello
model = LinearRegression()
print("✅ Modello LinearRegression creato")

# 5.2 Addestramento con dati di training
print("\n⚡ Addestramento modello in corso...")
model.fit(X_train_scaled, y_train)
print("✅ Modello addestrato con successo!")

# 5.3 Coefficienti del modello (importanza features)
coefficients = pd.DataFrame({
    'feature': features,
    'coefficient': model.coef_
}).sort_values('coefficient', ascending=False)

print("\n📊 COEFFICIENTI DEL MODELLO (importanza features):")
print(coefficients)
print(f"\nIntercetta (bias): €{model.intercept_:,.2f}")

# 5.4 Interpretazione coefficienti
print("\n🔍 INTERPRETAZIONE COEFFICIENTI:")
for idx, row in coefficients.iterrows():
    segno = "+" if row['coefficient'] > 0 else "-"
    effetto = "aumenta" if row['coefficient'] > 0 else "diminuisce"
    print(f"  • {row['feature']}: {segno}€{abs(row['coefficient']):,.0f} per unità → {effetto} il prezzo")

▶ Valutazione Modello

6
Valuta le performance del modello:
PYTHON
# 6. VALUTAZIONE DEL MODELLO
print("\n📈 VALUTAZIONE PERFORMANCE MODELLO")
print("="*50)

# 6.1 Predizioni sui set di training e test
y_pred_train = model.predict(X_train_scaled)
y_pred_test = model.predict(X_test_scaled)

# 6.2 Calcolo metriche di valutazione
def calculate_metrics(y_true, y_pred, dataset_name):
    mae = mean_absolute_error(y_true, y_pred)
    mse = mean_squared_error(y_true, y_pred)
    rmse = np.sqrt(mse)
    r2 = r2_score(y_true, y_pred)
    
    print(f"\n📊 METRICHE {dataset_name.upper()}:")
    print(f"  • MAE (Mean Absolute Error): €{mae:,.0f}")
    print(f"  • MSE (Mean Squared Error): €{mse:,.0f}")
    print(f"  • RMSE (Root Mean Squared Error): €{rmse:,.0f}")
    print(f"  • R² Score: {r2:.3f}")
    
    return mae, rmse, r2

# Calcola metriche per training e test
mae_train, rmse_train, r2_train = calculate_metrics(y_train, y_pred_train, "training")
mae_test, rmse_test, r2_test = calculate_metrics(y_test, y_pred_test, "test")

# 6.3 Visualizzazione predizioni vs valori reali
print("\n🎨 VISUALIZZAZIONE RISULTATI...")

fig, axes = plt.subplots(1, 2, figsize=(15, 6))

# Training set
axes[0].scatter(y_train, y_pred_train, alpha=0.6, color='blue')
axes[0].plot([y_train.min(), y_train.max()], [y_train.min(), y_train.max()], 'r--', lw=2)
axes[0].set_title('Training Set: Valori Reali vs Predetti')
axes[0].set_xlabel('Prezzo Reale (€)')
axes[0].set_ylabel('Prezzo Predetto (€)')
axes[0].grid(True, alpha=0.3)

# Test set
axes[1].scatter(y_test, y_pred_test, alpha=0.6, color='green')
axes[1].plot([y_test.min(), y_test.max()], [y_test.min(), y_test.max()], 'r--', lw=2)
axes[1].set_title('Test Set: Valori Reali vs Predetti')
axes[1].set_xlabel('Prezzo Reale (€)')
axes[1].set_ylabel('Prezzo Predetto (€)')
axes[1].grid(True, alpha=0.3)

plt.tight_layout()
plt.show()

# 6.4 Analisi residui
print("\n🔍 ANALISI RESIDUI (errori di predizione):")
residui_test = y_test - y_pred_test

plt.figure(figsize=(12, 5))

plt.subplot(1, 2, 1)
plt.scatter(y_pred_test, residui_test, alpha=0.6, color='purple')
plt.axhline(y=0, color='r', linestyle='--')
plt.title('Residui vs Predizioni')
plt.xlabel('Prezzo Predetto (€)')
plt.ylabel('Residuo (€)')
plt.grid(True, alpha=0.3)

plt.subplot(1, 2, 2)
plt.hist(residui_test, bins=20, edgecolor='black', alpha=0.7, color='orange')
plt.title('Distribuzione Residui')
plt.xlabel('Residuo (€)')
plt.ylabel('Frequenza')
plt.grid(True, alpha=0.3)

plt.tight_layout()
plt.show()

print("✅ Valutazione modello completata!")

Parte 5: Utilizzo Pratico del Modello

▶ Previsioni su Nuove Case

7
Usa il modello per fare previsioni:
PYTHON
# 7. UTILIZZO MODELLO PER PREVISIONI
print("🔮 PREVISIONI SU NUOVE CASE")
print("="*50)

# 7.1 Crea nuove case per la previsione
nuove_case = pd.DataFrame({
    'metratura': [120, 85, 200, 150, 90],
    'camere': [3, 2, 4, 3, 2],
    'bagni': [2, 1, 3, 2, 1],
    'eta': [10, 25, 5, 15, 30],
    'zona': [2, 1, 3, 2, 1]  # 1=centro, 2=periferia, 3=suburbano
})

print("🏠 NUOVE CASE DA VALUTARE:")
nuove_case_display = nuove_case.copy()
nuove_case_display['zona_desc'] = nuove_case_display['zona'].map({1: 'Centro', 2: 'Periferia', 3: 'Suburbano'})
print(nuove_case_display[['metratura', 'camere', 'bagni', 'eta', 'zona_desc']])

# 7.2 Preprocessing nuove case (usando lo stesso scaler)
X_nuove_scaled = scaler.transform(nuove_case)

# 7.3 Fai previsioni
previsioni = model.predict(X_nuove_scaled)

# 7.4 Mostra risultati
print("\n💰 PREZZI PREVISTI:")
risultati = nuove_case.copy()
risultati['zona_desc'] = risultati['zona'].map({1: 'Centro', 2: 'Periferia', 3: 'Suburbano'})
risultati['prezzo_previsto'] = previsioni

for idx, row in risultati.iterrows():
    print(f"\nCasa #{idx + 1}:")
    print(f"  • Metratura: {row['metratura']} m²")
    print(f"  • Camere: {row['camere']}")
    print(f"  • Bagni: {row['bagni']}")
    print(f"  • Età: {row['eta']} anni")
    print(f"  • Zona: {row['zona_desc']}")
    print(f"  • 💰 Prezzo stimato: €{row['prezzo_previsto']:,.0f}")

# 7.5 Analisi sensibilità: come cambia il prezzo con le caratteristiche
print("\n📊 ANALISI DI SENSIBILITÀ:")
print("Come cambia il prezzo al variare delle caratteristiche:")

# Casa di riferimento
casa_base = pd.DataFrame({
    'metratura': [100],
    'camere': [3],
    'bagni': [2],
    'eta': [10],
    'zona': [2]
})

prezzo_base = model.predict(scaler.transform(casa_base))[0]
print(f"\nCasa base (100m², 3 camere, 2 bagni, 10 anni, periferia): €{prezzo_base:,.0f}")

# Variazioni
variazioni = [
    ("+20m²", {"metratura": 120}),
    ("+1 camera", {"camere": 4}),
    ("+1 bagno", {"bagni": 3}),
    ("+10 anni", {"eta": 20}),
    ("Centro città", {"zona": 1}),
    ("Suburbano", {"zona": 3})
]

for desc, cambiamenti in variazioni:
    casa_variazione = casa_base.copy()
    for key, value in cambiamenti.items():
        casa_variazione[key] = value
    
    prezzo_variazione = model.predict(scaler.transform(casa_variazione))[0]
    differenza = prezzo_variazione - prezzo_base
    segno = "+" if differenza > 0 else ""
    
    print(f"  {desc}: €{prezzo_variazione:,.0f} ({segno}€{abs(differenza):,.0f})")

print("\n✅ Sistema di previsione prezzi completato con successo!")

Concetti di Machine Learning Appresi

Congratulazioni! Ora conosci:

  • Regressione Lineare: Modello ML per previsioni numeriche
  • Scikit-Learn: Libreria Python più usata per ML
  • EDA (Exploratory Data Analysis): Analisi preliminare dei dati
  • Train/Test Split: Separazione dati per valutazione modelli
  • Feature Scaling: Normalizzazione dati per ML
  • Metriche di Valutazione: MAE, MSE, RMSE, R² Score
  • Interpretazione Modelli: Coefficienti e loro significato
  • Pipeline ML Completa: Dati → Preprocessing → Training → Valutazione → Previsioni

Prossimi Passi nel Machine Learning

Nella prossima esercitazione imparerai:

  • 🌺 Classificazione con dataset Iris
  • 📊 Regressione multipla avanzata
  • 🔍 Feature engineering e selezione
  • 🤖 Algoritmi di ensemble (Random Forest)
  • 🧠 Reti neurali per regressione

Hai costruito il tuo primo modello di Machine Learning professionale!

Torna in alto