🚫 COPIA BLOCCATA
import numpy as np
import pandas as pd
from sklearn.model_selection import train_test_split, cross_val_score, KFold
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import (accuracy_score, precision_score, recall_score,
f1_score, confusion_matrix, classification_report,
roc_auc_score, roc_curve)
import matplotlib.pyplot as plt
print("🎯 METRICHE DI VALUTAZIONE ML")
print("=" * 70)
# Creiamo dati sintetici per dimostrazione
np.random.seed(42)
n_samples = 1000
# Features: età, reddito, spese_mensili
X = np.random.randn(n_samples, 3) * 10 + 50 # Media 50, dev std 10
# Target: approvato mutuo (1) o rifiutato (0)
# Logica: se reddito > spese*2 e età tra 25-60, approvato
y = ((X[:, 1] > X[:, 2] * 2) & (X[:, 0] > 25) & (X[:, 0] < 60)).astype(int)
# Aggiungiamo rumore
y = y ^ (np.random.random(n_samples) > 0.9) # 10% di rumore
df_mutui = pd.DataFrame(X, columns=['età', 'reddito', 'spese'])
df_mutui['mutuo_approvato'] = y
print("\n📊 DATASET MUTUI (prime 10 righe):")
print(df_mutui.head(10))
print(f"\nDistribuzione target: {df_mutui['mutuo_approvato'].value_counts().to_dict()}")
# 1. TRAIN/TEST SPLIT BASE
print("\n\n1. 🔀 TRAIN/TEST SPLIT BASE")
print("-" * 40)
X = df_mutui[['età', 'reddito', 'spese']]
y = df_mutui['mutuo_approvato']
# Split 70/30
X_train, X_test, y_train, y_test = train_test_split(
X, y,
test_size=0.3, # 30% test
random_state=42,
stratify=y # Mantiene proporzioni target
)
print(f"Training set: {X_train.shape} ({len(X_train)/len(X)*100:.0f}%)")
print(f"Test set: {X_test.shape} ({len(X_test)/len(X)*100:.0f}%)")
print(f"Distribuzione training: {pd.Series(y_train).value_counts().to_dict()}")
print(f"Distribuzione test: {pd.Series(y_test).value_counts().to_dict()}")
# 2. TRAINING MODELLO
print("\n\n2. 🤖 TRAINING LOGISTIC REGRESSION")
print("-" * 40)
model = LogisticRegression(random_state=42, max_iter=1000)
model.fit(X_train, y_train)
# Predizioni
y_pred = model.predict(X_test)
y_pred_proba = model.predict_proba(X_test)[:, 1] # Probabilità classe positiva
print("✅ Modello addestrato!")
print(f"Coefficienti: {model.coef_[0]}")
print(f"Intercetta: {model.intercept_[0]:.4f}")
# 3. METRICHE BASE DI CLASSIFICAZIONE
print("\n\n3. 📊 METRICHE DI VALUTAZIONE")
print("-" * 40)
# Calcola tutte le metriche
accuracy = accuracy_score(y_test, y_pred)
precision = precision_score(y_test, y_pred)
recall = recall_score(y_test, y_pred)
f1 = f1_score(y_test, y_pred)
print(f"🎯 Accuracy: {accuracy:.3f} ({accuracy*100:.1f}%)")
print(f"🎯 Precision: {precision:.3f}")
print(f"🎯 Recall (Sensitivity): {recall:.3f}")
print(f"🎯 F1-Score: {f1:.3f}")
# Matrice di confusione
cm = confusion_matrix(y_test, y_pred)
print("\n📋 MATRICE DI CONFUSIONE:")
print(f" Predetto NO Predetto SI")
print(f"Reale NO (TN): {cm[0,0]:8} (FP): {cm[0,1]:8}")
print(f"Reale SI (FN): {cm[1,0]:8} (TP): {cm[1,1]:8}")
# Classification report completo
print("\n📄 CLASSIFICATION REPORT:")
print(classification_report(y_test, y_pred,
target_names=['Rifiutato', 'Approvato']))
# 4. ROC-AUC (per problemi binari)
print("\n\n4. 📈 ROC-AUC CURVE")
print("-" * 40)
# Calcola AUC
auc_score = roc_auc_score(y_test, y_pred_proba)
print(f"🎯 AUC Score: {auc_score:.3f}")
# Calcola curve ROC
fpr, tpr, thresholds = roc_curve(y_test, y_pred_proba)
print("\n📊 SU GOOGLE COLAB, SCOMMENTA PER VEDERE IL GRAFICO:")
"""
plt.figure(figsize=(10, 6))
plt.plot(fpr, tpr, color='blue', lw=2, label=f'ROC curve (AUC = {auc_score:.3f})')
plt.plot([0, 1], [0, 1], color='gray', lw=1, linestyle='--', label='Random Classifier')
plt.xlim([0.0, 1.0])
plt.ylim([0.0, 1.05])
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate (Recall)')
plt.title('ROC Curve - Mutuo Approval')
plt.legend(loc="lower right")
plt.grid(True, alpha=0.3)
plt.show()
"""
# 5. CROSS-VALIDATION
print("\n\n5. 🔄 CROSS-VALIDATION")
print("-" * 40)
# 5-fold cross-validation
cv_scores = cross_val_score(
LogisticRegression(max_iter=1000),
X, y,
cv=5, # 5 folds
scoring='accuracy', # Metrica da valutare
n_jobs=-1 # Usa tutti i core CPU
)
print("🎯 CROSS-VALIDATION SCORES (5-fold):")
for i, score in enumerate(cv_scores, 1):
print(f" Fold {i}: {score:.3f}")
print(f"\n📊 Media CV Accuracy: {cv_scores.mean():.3f} (+/- {cv_scores.std()*2:.3f})")
print(f"📈 Accuracy su test set: {accuracy:.3f}")
# K-Fold esplicito
print("\n🎯 K-FOLD CROSS-VALIDATION DETTAGLIATO:")
kf = KFold(n_splits=5, shuffle=True, random_state=42)
fold_accuracies = []
for fold, (train_idx, val_idx) in enumerate(kf.split(X), 1):
X_train_fold, X_val_fold = X.iloc[train_idx], X.iloc[val_idx]
y_train_fold, y_val_fold = y.iloc[train_idx], y.iloc[val_idx]
fold_model = LogisticRegression(max_iter=1000, random_state=42)
fold_model.fit(X_train_fold, y_train_fold)
y_pred_fold = fold_model.predict(X_val_fold)
fold_accuracy = accuracy_score(y_val_fold, y_pred_fold)
fold_accuracies.append(fold_accuracy)
print(f" Fold {fold}: Accuracy = {fold_accuracy:.3f} "
f"(Train size: {len(X_train_fold)}, Val size: {len(X_val_fold)})")
print(f"\n📊 Media K-Fold Accuracy: {np.mean(fold_accuracies):.3f}")
# 6. STRATIFIED K-FOLD (per dataset sbilanciati)
print("\n\n6. ⚖️ STRATIFIED K-FOLD (per classi sbilanciate)")
print("-" * 40)
from sklearn.model_selection import StratifiedKFold
skf = StratifiedKFold(n_splits=5, shuffle=True, random_state=42)
stratified_scores = []
for train_idx, val_idx in skf.split(X, y):
X_train_fold, X_val_fold = X.iloc[train_idx], X.iloc[val_idx]
y_train_fold, y_val_fold = y.iloc[train_idx], y.iloc[val_idx]
# Verifica distribuzione
print(f" Train distribuzione: {pd.Series(y_train_fold).value_counts().to_dict()}")
print(f" Val distribuzione: {pd.Series(y_val_fold).value_counts().to_dict()}")
fold_model = LogisticRegression(max_iter=1000, random_state=42)
fold_model.fit(X_train_fold, y_train_fold)
y_pred_fold = fold_model.predict(X_val_fold)
fold_accuracy = accuracy_score(y_val_fold, y_pred_fold)
stratified_scores.append(fold_accuracy)
break # Mostra solo primo fold per brevità
# 7. LEARNING CURVE (semplificata)
print("\n\n7. 📚 LEARNING CURVE - Effetto dimensione training set")
print("-" * 40)
train_sizes = [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9]
train_scores = []
test_scores = []
for size in train_sizes:
X_train_frac, _, y_train_frac, _ = train_test_split(
X, y, train_size=size, random_state=42, stratify=y
)
temp_model = LogisticRegression(max_iter=1000, random_state=42)
temp_model.fit(X_train_frac, y_train_frac)
# Score su training
train_score = temp_model.score(X_train_frac, y_train_frac)
# Score su test (holdout)
test_score = temp_model.score(X_test, y_test)
train_scores.append(train_score)
test_scores.append(test_score)
print(f" Train size {size*100:.0f}%: Train Acc={train_score:.3f}, Test Acc={test_score:.3f}")
print("\n📊 SU GOOGLE COLAB, SCOMMENTA PER VEDERE LEARNING CURVE:")
"""
plt.figure(figsize=(10, 6))
plt.plot([s*100 for s in train_sizes], train_scores, 'o-', color='blue', label='Training Accuracy')
plt.plot([s*100 for s in train_sizes], test_scores, 's-', color='green', label='Test Accuracy')
plt.xlabel('Training Set Size (%)')
plt.ylabel('Accuracy')
plt.title('Learning Curve - Logistic Regression')
plt.legend(loc='best')
plt.grid(True, alpha=0.3)
plt.show()
"""
# 8. CONCLUSIONI E BEST PRACTICES
print("\n\n8. 🎓 BEST PRACTICES PER VALUTAZIONE ML")
print("-" * 40)
print("\n✅ COSA FARE:")
print("1. Usa sempre train/test split (minimo 70/30)")
print("2. Stratifica se le classi sono sbilanciate")
print("3. Usa cross-validation per stime robuste")
print("4. Guarda multiple metriche, non solo accuracy")
print("5. Confronta con baseline (modello semplice)")
print("\n❌ COSA EVITARE:")
print("1. Mai testare su dati usati per training")
print("2. Non guardare solo all'accuracy")
print("3. Non ignorare overfitting/underfitting")
print("4. Non dimenticare di standardizzare features")
print("\n🎯 METRICA GIUSTA PER IL PROBLEMA GIUSTO:")
print("• Accuracy: Classi bilanciate")
print("• Precision: Costo falsi positivi alto (es: spam detection)")
print("• Recall: Costo falsi negativi alto (es: diagnosi medica)")
print("• F1-Score: Balance tra precision e recall")
print("• AUC-ROC: Confronto modelli overall")
print("\n📊 PERFORMANCE SUMMARY:")
summary_df = pd.DataFrame({
'Metric': ['Accuracy', 'Precision', 'Recall', 'F1-Score', 'AUC'],
'Value': [accuracy, precision, recall, f1, auc_score],
'Interpretation': [
f"{accuracy*100:.1f}% delle predizioni corrette",
f"{precision*100:.1f}% degli approvati erano veri approvati",
f"{recall*100:.1f}% dei veri approvati sono stati identificati",
f"Media armonica tra precision e recall",
f"{auc_score*100:.1f}% di capacità discriminativa"
]
})
print(summary_df.to_string(index=False))
print("\n🎉 VALUTAZIONE COMPLETATA! ORA SAI COME MISURARE I MODELLI ML!")