🏠 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.
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
Crea una nuova cella su Google Colab e importa le librerie:
# 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
Crea il dataset di case per il training:
# 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
Analizza le relazioni tra variabili:
# 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
Prepara i dati per il modello ML:
# 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
Crea e addestra il modello di regressione:
# 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
Valuta le performance del modello:
# 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
Usa il modello per fare previsioni:
# 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!