🌺 Classificazione con Iris Dataset e Scikit-Learn
Impara algoritmi di classificazione ML con il dataset più famoso
Introduzione
Benvenuto nel mondo della classificazione con Machine Learning! Useremo il famoso dataset Iris per imparare a classificare specie di fiori basandoci sulle dimensioni di petali e sepali. Questo è il dataset “Hello World” del ML ed è perfetto per imparare gli algoritmi di classificazione.
Lavorerai come botanico digitale che deve creare un sistema per identificare automaticamente specie di fiori Iris. Useremo SVM, KNN e altri algoritmi per costruire classificatori accurati.
⚠️ ATTENZIONE: COPIA BLOCCATA
Il codice è protetto da sistema anti-copia. Dovrai SCRIVERE manualmente tutto il codice per imparare veramente! 🚫📋
Parte 1: Caricamento e Esplorazione Dataset
▶ Importazione e Caricamento Iris Dataset
Crea una nuova cella su Google Colab e carica il dataset:
# IMPORT LIBRERIE PER CLASSIFICAZIONE ML
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn import datasets
from sklearn.model_selection import train_test_split, cross_val_score
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import accuracy_score, classification_report, confusion_matrix
# Algoritmi di classificazione che useremo
from sklearn.neighbors import KNeighborsClassifier
from sklearn.svm import SVC
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import RandomForestClassifier
from sklearn.naive_bayes import GaussianNB
# Configurazione visualizzazione
sns.set_style("whitegrid")
plt.rcParams['figure.figsize'] = (12, 8)
plt.rcParams['font.size'] = 12
print("✅ Librerie ML importate correttamente!")
print("📊 Algoritmi disponibili: KNN, SVM, Decision Tree, Random Forest, Naive Bayes")
▶ Caricamento e Analisi Dataset Iris
Carica e esplora il dataset Iris:
# 2. CARICAMENTO DATASET IRIS
print("🌺 CARICAMENTO DATASET IRIS")
print("="*50)
# Carica dataset Iris da Scikit-Learn
iris = datasets.load_iris()
X = iris.data # Features: [sepal_length, sepal_width, petal_length, petal_width]
y = iris.target # Target: 0=setosa, 1=versicolor, 2=virginica
feature_names = iris.feature_names
target_names = iris.target_names
# Converti in DataFrame per analisi più facile
df_iris = pd.DataFrame(X, columns=feature_names)
df_iris['species'] = y
df_iris['species_name'] = df_iris['species'].map({i: name for i, name in enumerate(target_names)})
print(f"📊 INFORMAZIONI DATASET:")
print(f" • Numero campioni: {X.shape[0]}")
print(f" • Numero features: {X.shape[1]}")
print(f" • Features: {', '.join(feature_names)}")
print(f" • Classi target: {', '.join(target_names)}")
print(f" • Valori target: 0={target_names[0]}, 1={target_names[1]}, 2={target_names[2]}")
print(f"\n📋 PRIME 10 RIGHE DEL DATASET:")
print(df_iris.head(10))
print(f"\n📈 STATISTICHE DESCRITTIVE:")
print(df_iris.describe())
print(f"\n🎯 DISTRIBUZIONE CLASSI:")
distribuzione = df_iris['species_name'].value_counts()
for specie, count in distribuzione.items():
percentuale = (count / len(df_iris)) * 100
print(f" • {specie}: {count} campioni ({percentuale:.1f}%)")
print(f"\n🔍 VALORI MANCANTI:")
print(df_iris.isnull().sum())
Parte 2: Visualizzazione e Analisi Dati
▶ Visualizzazioni per Capire i Dati
Visualizza le relazioni tra features e classi:
# 3. VISUALIZZAZIONE DATASET IRIS
print("🎨 VISUALIZZAZIONE COMPLETA DATASET IRIS")
print("="*50)
# Configura colori per le specie
colors = {'setosa': '#FF6B6B', 'versicolor': '#4ECDC4', 'virginica': '#45B7D1'}
markers = {'setosa': 'o', 'versicolor': 's', 'virginica': '^'}
print("Creazione visualizzazioni...")
# Creazione figura con multiple visualizzazioni
fig = plt.figure(figsize=(18, 12))
fig.suptitle('Analisi Visuale Dataset Iris', fontsize=20, fontweight='bold')
# 3.1 Pairplot (Scatter Matrix)
print("\n1. Pairplot - Relazioni tra tutte le features...")
import warnings
warnings.filterwarnings('ignore')
# Pairplot semplificato
axes = []
for i in range(4):
for j in range(4):
ax = plt.subplot(4, 4, i*4 + j + 1)
axes.append(ax)
if i == j:
# Diagonali: istogrammi
for idx, specie in enumerate(target_names):
data = df_iris[df_iris['species_name'] == specie][feature_names[i]]
ax.hist(data, alpha=0.5, label=specie, color=colors[specie])
ax.set_xlabel(feature_names[i])
if i == 0:
ax.legend(loc='upper right', fontsize=8)
else:
# Off-diagonal: scatter plots
for idx, specie in enumerate(target_names):
x_data = df_iris[df_iris['species_name'] == specie][feature_names[j]]
y_data = df_iris[df_iris['species_name'] == specie][feature_names[i]]
ax.scatter(x_data, y_data, alpha=0.6, label=specie,
color=colors[specie], marker=markers[specie], s=30)
ax.set_xlabel(feature_names[j])
ax.set_ylabel(feature_names[i])
if i == 0 and j == 3:
ax.legend(loc='upper right', fontsize=8)
plt.tight_layout()
plt.show()
# 3.2 Boxplot per feature
print("\n2. Boxplot - Distribuzione per specie...")
fig, axes = plt.subplots(2, 2, figsize=(14, 10))
fig.suptitle('Distribuzione Features per Specie di Iris', fontsize=16)
for idx, feature in enumerate(feature_names):
ax = axes[idx // 2, idx % 2]
box_data = [df_iris[df_iris['species_name'] == specie][feature] for specie in target_names]
bp = ax.boxplot(box_data, labels=target_names, patch_artist=True)
# Colori per i box
for patch, color in zip(bp['boxes'], [colors[s] for s in target_names]):
patch.set_facecolor(color)
patch.set_alpha(0.6)
ax.set_title(f'Distribuzione {feature}')
ax.set_ylabel('cm')
ax.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
# 3.3 Heatmap correlazioni
print("\n3. Heatmap - Correlazioni tra features...")
plt.figure(figsize=(10, 8))
correlation_matrix = df_iris[feature_names].corr()
sns.heatmap(correlation_matrix, annot=True, cmap='coolwarm', center=0,
square=True, linewidths=1, cbar_kws={"shrink": 0.8})
plt.title('Matrice di Correlazione tra Features', fontsize=14, pad=20)
plt.tight_layout()
plt.show()
print("✅ Visualizzazioni completate!")
Parte 3: Preparazione Dati per Classificazione
▶ Split Train/Test e Preprocessing
Prepara i dati per gli algoritmi di classificazione:
# 4. PREPARAZIONE DATI PER CLASSIFICAZIONE
print("⚙️ PREPARAZIONE DATI PER GLI ALGORITMI DI CLASSIFICAZIONE")
print("="*60)
# 4.1 Split in training e test set
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.3, random_state=42, stratify=y
)
print(f"📊 SPLIT DATI:")
print(f" • Dimensione dataset completo: {X.shape}")
print(f" • Training set: {X_train.shape[0]} campioni (70%)")
print(f" • Test set: {X_test.shape[0]} campioni (30%)")
# Verifica distribuzione classi nei due set
print(f"\n🎯 DISTRIBUZIONE CLASSI NEI SET:")
train_dist = np.bincount(y_train)
test_dist = np.bincount(y_test)
for i, specie in enumerate(target_names):
train_pct = (train_dist[i] / len(y_train)) * 100
test_pct = (test_dist[i] / len(y_test)) * 100
print(f" • {specie}:")
print(f" Training: {train_dist[i]} campioni ({train_pct:.1f}%)")
print(f" Test: {test_dist[i]} campioni ({test_pct:.1f}%)")
# 4.2 Normalizzazione delle features
print(f"\n🔢 NORMALIZZAZIONE FEATURES:")
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)
print(" Features scalate con StandardScaler (media=0, deviazione=1)")
print(f" Esempio prima riga training (originale): {X_train[0]}")
print(f" Esempio prima riga training (scalata): {X_train_scaled[0]}")
# 4.3 Visualizzazione dati dopo scaling
print(f"\n🎨 CONFRONTO DATI PRIMA E DOPO SCALING...")
fig, axes = plt.subplots(1, 2, figsize=(15, 6))
# Dati originali
for i, specie in enumerate(target_names):
mask = y_train == i
axes[0].scatter(X_train[mask, 2], X_train[mask, 3],
alpha=0.6, label=specie, color=colors[specie],
marker=markers[specie], s=50)
axes[0].set_title('Dati Originali (Training Set)')
axes[0].set_xlabel('Petal Length (cm)')
axes[0].set_ylabel('Petal Width (cm)')
axes[0].legend()
axes[0].grid(True, alpha=0.3)
# Dati scalati
for i, specie in enumerate(target_names):
mask = y_train == i
axes[1].scatter(X_train_scaled[mask, 2], X_train_scaled[mask, 3],
alpha=0.6, label=specie, color=colors[specie],
marker=markers[specie], s=50)
axes[1].set_title('Dati Scalati (Training Set)')
axes[1].set_xlabel('Petal Length (scalata)')
axes[1].set_ylabel('Petal Width (scalata)')
axes[1].legend()
axes[1].grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
print("✅ Preparazione dati completata!")
Parte 4: Implementazione Algoritmi di Classificazione
▶ Addestramento Multipli Algoritmi
Addestra e confronta diversi algoritmi di classificazione:
# 5. IMPLEMENTAZIONE ALGORITMI DI CLASSIFICAZIONE
print("🤖 ADDESTRAMENTO ALGORITMI DI CLASSIFICAZIONE")
print("="*60)
# Definizione dei modelli da testare
models = {
'K-Nearest Neighbors': KNeighborsClassifier(n_neighbors=5),
'Support Vector Machine': SVC(kernel='rbf', C=1.0, gamma='scale', probability=True),
'Decision Tree': DecisionTreeClassifier(max_depth=4, random_state=42),
'Random Forest': RandomForestClassifier(n_estimators=100, max_depth=4, random_state=42),
'Naive Bayes': GaussianNB()
}
# Dizionario per salvare risultati
results = {
'Model': [],
'Train Accuracy': [],
'Test Accuracy': [],
'Cross-Val Score': []
}
print("⚡ Addestramento modelli in corso...\n")
# Addestra e valuta ogni modello
for name, model in models.items():
# Addestramento
model.fit(X_train_scaled, y_train)
# Predizioni
y_train_pred = model.predict(X_train_scaled)
y_test_pred = model.predict(X_test_scaled)
# Calcolo accuracy
train_acc = accuracy_score(y_train, y_train_pred)
test_acc = accuracy_score(y_test, y_test_pred)
# Cross-validation score (5-fold)
cv_scores = cross_val_score(model, X_train_scaled, y_train, cv=5)
cv_mean = cv_scores.mean()
# Salva risultati
results['Model'].append(name)
results['Train Accuracy'].append(train_acc)
results['Test Accuracy'].append(test_acc)
results['Cross-Val Score'].append(cv_mean)
# Stampa risultati parziali
print(f"📊 {name}:")
print(f" • Training Accuracy: {train_acc:.3f}")
print(f" • Test Accuracy: {test_acc:.3f}")
print(f" • Cross-Val Mean: {cv_mean:.3f}")
print()
# Converti risultati in DataFrame
results_df = pd.DataFrame(results)
results_df = results_df.sort_values('Test Accuracy', ascending=False)
print("🏆 CLASSIFICA MODELLI PER TEST ACCURACY:")
print(results_df.to_string(index=False))
# Visualizzazione confronto modelli
print("\n🎨 VISUALIZZAZIONE CONFRONTO MODELLI...")
fig, ax = plt.subplots(figsize=(12, 8))
x = np.arange(len(results_df))
width = 0.25
bars1 = ax.bar(x - width, results_df['Train Accuracy'], width, label='Train Accuracy',
color='skyblue', alpha=0.8)
bars2 = ax.bar(x, results_df['Test Accuracy'], width, label='Test Accuracy',
color='lightgreen', alpha=0.8)
bars3 = ax.bar(x + width, results_df['Cross-Val Score'], width, label='Cross-Val Score',
color='salmon', alpha=0.8)
ax.set_xlabel('Modelli')
ax.set_ylabel('Accuracy')
ax.set_title('Confronto Performance Algoritmi di Classificazione')
ax.set_xticks(x)
ax.set_xticklabels(results_df['Model'], rotation=45, ha='right')
ax.legend(loc='lower right')
ax.grid(True, alpha=0.3, axis='y')
# Aggiungi valori sulle barre
for bars in [bars1, bars2, bars3]:
for bar in bars:
height = bar.get_height()
ax.annotate(f'{height:.3f}',
xy=(bar.get_x() + bar.get_width() / 2, height),
xytext=(0, 3), # 3 points vertical offset
textcoords="offset points",
ha='center', va='bottom', fontsize=9)
plt.tight_layout()
plt.show()
print("✅ Addestramento e valutazione modelli completati!")
Parte 5: Analisi Dettagliata e Utilizzo Pratico
▶ Analisi Modello Migliore e Previsioni
Analizza il miglior modello e usalo per previsioni:
# 6. ANALISI DETTAGLIATA MODELLO MIGLIORE
print("🏆 ANALISI MODELLO MIGLIORE: RANDOM FOREST")
print("="*60)
# Seleziona il modello migliore (Random Forest in questo caso)
best_model_name = results_df.iloc[0]['Model']
best_model = models[best_model_name]
print(f"Modello selezionato: {best_model_name}")
print(f"Test Accuracy: {results_df.iloc[0]['Test Accuracy']:.3f}")
# 6.1 Matrice di confusione dettagliata
print(f"\n📊 MATRICE DI CONFUSIONE DETTAGLIATA:")
y_pred_best = best_model.predict(X_test_scaled)
cm = confusion_matrix(y_test, y_pred_best)
# Visualizzazione matrice di confusione
plt.figure(figsize=(10, 8))
sns.heatmap(cm, annot=True, fmt='d', cmap='Blues',
xticklabels=target_names, yticklabels=target_names)
plt.title(f'Matrice di Confusione - {best_model_name}', fontsize=16, pad=20)
plt.xlabel('Predicted')
plt.ylabel('Actual')
plt.tight_layout()
plt.show()
# 6.2 Classification report
print(f"\n📋 CLASSIFICATION REPORT:")
cr = classification_report(y_test, y_pred_best, target_names=target_names)
print(cr)
# 6.3 Feature importance (solo per Random Forest e Decision Tree)
if hasattr(best_model, 'feature_importances_'):
print(f"\n🔍 FEATURE IMPORTANCE:")
importances = best_model.feature_importances_
feature_importance_df = pd.DataFrame({
'Feature': feature_names,
'Importance': importances
}).sort_values('Importance', ascending=False)
print(feature_importance_df.to_string(index=False))
# Visualizzazione feature importance
plt.figure(figsize=(10, 6))
bars = plt.barh(feature_importance_df['Feature'], feature_importance_df['Importance'],
color='steelblue')
plt.xlabel('Importance')
plt.title(f'Feature Importance - {best_model_name}', fontsize=14)
plt.gca().invert_yaxis() # Mostra la feature più importante in alto
# Aggiungi valori sulle barre
for bar in bars:
width = bar.get_width()
plt.text(width + 0.001, bar.get_y() + bar.get_height()/2,
f'{width:.3f}', va='center', fontsize=10)
plt.tight_layout()
plt.show()
# 6.4 Esempi di previsioni sul test set
print(f"\n🔮 ESEMPI DI PREVISIONI SUL TEST SET:")
print("="*50)
# Seleziona alcuni esempi dal test set
sample_indices = np.random.choice(len(X_test), 10, replace=False)
print("\n{:^5} | {:^25} | {:^25} | {:^8}".format(
"IDX", "Caratteristiche Reali", "Predizione", "Corretto?"))
print("-" * 70)
for idx in sample_indices:
features_real = X_test[idx]
features_scaled = X_test_scaled[idx]
true_label = y_test[idx]
pred_label = best_model.predict([features_scaled])[0]
pred_proba = best_model.predict_proba([features_scaled])[0]
# Formatta le caratteristiche
features_str = f"SL:{features_real[0]:.1f}, SW:{features_real[1]:.1f}, PL:{features_real[2]:.1f}, PW:{features_real[3]:.1f}"
# Formatta predizione con probabilità
pred_name = target_names[pred_label]
true_name = target_names[true_label]
proba = pred_proba[pred_label] * 100
correct = "✅" if pred_label == true_label else "❌"
print("{:^5} | {:^25} | {:^25} | {:^8}".format(
idx, features_str, f"{pred_name} ({proba:.1f}%)", correct))
# 6.5 Previsioni su nuovi dati (fiori sconosciuti)
print(f"\n🌺 PREVISIONI SU NUOVI FIORI SCONOSCIUTI:")
print("="*50)
# Crea nuovi fiori "sconosciuti" per la classificazione
nuovi_fiori = np.array([
[5.1, 3.5, 1.4, 0.2], # Sembra una setosa
[6.0, 2.9, 4.5, 1.5], # Sembra una versicolor
[7.2, 3.0, 5.8, 2.1], # Sembra una virginica
[5.8, 2.7, 3.9, 1.2], # Caso intermedio
[6.7, 3.1, 5.6, 2.4] # Caso estremo
])
# Normalizza i nuovi dati
nuovi_fiori_scaled = scaler.transform(nuovi_fiori)
# Fai previsioni
predizioni = best_model.predict(nuovi_fiori_scaled)
probabilita = best_model.predict_proba(nuovi_fiori_scaled)
print("\n{:^5} | {:^30} | {:^20} | {:^20}".format(
"Fiore", "Caratteristiche (SL,SW,PL,PW)", "Specie Predetta", "Probabilità"))
print("-" * 90)
for i, (fiore, pred, prob) in enumerate(zip(nuovi_fiori, predizioni, probabilita)):
caratteristiche = f"{fiore[0]:.1f}, {fiore[1]:.1f}, {fiore[2]:.1f}, {fiore[3]:.1f}"
specie_predetta = target_names[pred]
prob_max = prob[pred] * 100
# Mostra anche le altre probabilità
altre_probab = ", ".join([f"{target_names[j]}: {prob[j]*100:.1f}%"
for j in range(3) if j != pred])
print("{:^5} | {:^30} | {:^20} | {:^20}".format(
f"F{i+1}", caratteristiche, specie_predetta, f"{prob_max:.1f}%"))
print("{:^5} | {:^30} | {:^20} | {:^20}".format(
"", "", "", f"Altro: {altre_probab}"))
print(f"\n✅ Sistema di classificazione Iris completato con successo!")
print(f"🎯 Il modello {best_model_name} classifica correttamente il {results_df.iloc[0]['Test Accuracy']*100:.1f}% dei fiori!")
Concetti di Classificazione ML Appresi
Congratulazioni! Ora conosci:
- ✓ Classificazione ML: Algoritmi per categorizzare dati in classi
- ✓ Dataset Iris: Il benchmark standard per classificazione
- ✓ Algoritmi Multipli: KNN, SVM, Decision Tree, Random Forest, Naive Bayes
- ✓ StandardScaler: Normalizzazione features per ML
- ✓ Stratified Split: Mantenere distribuzione classi in train/test
- ✓ Metriche di Valutazione: Accuracy, Confusion Matrix, Classification Report
- ✓ Cross-Validation: Valutazione robusta dei modelli
- ✓ Feature Importance: Importanza delle variabili nei modelli
- ✓ Predizioni Probabilistiche: Probabilità associate a ogni classe
Prossimi Passi nella Classificazione ML
Nella prossima esercitazione imparerai:
- 🔍 Clustering con K-Means e DBSCAN
- 📊 Classificazione multi-classe avanzata
- 🤖 Ensemble methods e voting classifiers
- 🧠 Reti neurali per classificazione immagini
- 🎯 Hyperparameter tuning con GridSearch
Hai padroneggiato le basi della classificazione con Machine Learning!