PROGETTO FINALE • CAPSTONE PROJECT

Sistema di Previsione Medica Completo

Dalla raccolta dati alla predizione: un progetto AI end-to-end

Metti in pratica tutto ciò che hai imparato: Machine Learning, Reti Neurali, Database MySQL, Documentazione. Costruiamo insieme un sistema per predire malattie cardiache usando dati reali!

🎯 Panoramica del Progetto

🏥 Scenario Reale: Assistenza Sanitaria Predittiva

Un ospedale vuole identificare pazienti a rischio di malattie cardiache prima che si manifestino.

Problema: Come prevedere il rischio cardiaco basandosi su dati clinici?

Soluzione: Sistema AI che analizza dati pazienti e fornisce valutazioni di rischio.

Impatto: Diagnosi precoce, trattamenti tempestivi, vite salvate.

🎯
85%
Accuracy Target
Precisione minima per deployment
🤖
3+
Modelli AI
Confrontati e combinati
📊
13
Features Mediche
Età, colesterolo, pressione, etc.
🗄️
5
Tabelle Database
Pazienti, esami, predizioni, etc.

🎯 OBIETTIVI DI APPRENDIMENTO

Competenze Tecniche:

• Implementare modelli di classificazione (Alberi, Foreste, Reti Neurali)

• Comprendere basi reti neurali e loro addestramento

• Collegare applicazioni Python a database MySQL

• Applicare modelli di Machine Learning a problemi reali

Competenze Trasversali:

• Realizzare progetti AI completi end-to-end

• Documentare e presentare i risultati

• Integrare progetti AI con dati strutturati

• Collaborare e versionare codice (Git)

📅 Timeline del Progetto (2 Settimane)

Giorno 1-2

🎯 Analisi del Problema e Raccolta Dati

• Comprensione dataset malattie cardiache

• Analisi esplorativa dei dati (EDA)

• Definizione metriche di successo

• Setup ambiente di sviluppo

Giorno 3-4

🔧 Progettazione Database e Preprocessing

• Design schema database medico

• Implementazione MySQL con Python

• Pulizia e preparazione dati

• Feature engineering e selection

Giorno 5-7

🤖 Sviluppo Modelli Machine Learning

• Implementazione modelli baseline

• Addestramento e validazione

• Ottimizzazione iperparametri

• Confronto performance modelli

Giorno 8-10

🧠 Reti Neurali e Integrazione

• Design architettura rete neurale

• Addestramento con TensorFlow/Keras

• Integrazione modelli con database

• Sistema predittivo end-to-end

Giorno 11-12

📊 Valutazione e Documentazione

• Test approfonditi su dataset

• Analisi errori e miglioramenti

• Documentazione codice e risultati

• Preparazione presentazione

Giorno 13-14

🎓 Presentazione Finale

• Demo sistema funzionante

• Presentazione risultati alla classe

• Q&A e feedback

• Reflective learning e miglioramenti

💡 CONSIGLI PER IL SUCCESSO

Pianifica: Dividi il progetto in task giornalieri

Versiona: Usa Git dall'inizio (commit frequenti)

Testa: Verifica ogni componente separatamente

Documenta: Scrivi commenti e README mentre lavori

Collabora: Chiedi aiuto e discuti problemi

Celebra: Riconosci i progressi quotidiani

📊 Fase 1: Dataset Malattie Cardiache

🏥 Il Dataset Cleveland Heart Disease

Dataset reale dalla Cleveland Clinic Foundation, usato in ricerca medica mondiale.

303 pazienti con 13 features cliniche ciascuno

Target: Presenza di malattia cardiaca (0 = no, 1-4 = severità)

Caratteristiche uniche: Dati reali, clinicamente rilevanti, benchmark mondiale

🚫 COPIA BLOCCATA
# PROGETTO FINALE: SISTEMA DIAGNOSTICO CARDIACO AI # FASE 1: ANALISI E PREPARAZIONE DATI print("🎓 PROGETTO FINALE: SISTEMA DI PREVISIONE MALATTIE CARDIACHE") print("=" * 80) print("FASE 1: ANALISI DATASET E PREPARAZIONE") print("=" * 80) 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.preprocessing import StandardScaler, LabelEncoder import warnings warnings.filterwarnings('ignore') # Configurazione visualizzazione plt.style.use('seaborn-v0_8-darkgrid') sns.set_palette("husl") # 1. CARICAMENTO E ANALISI DATASET print("\n📥 1. CARICAMENTO DATASET CLEVELAND HEART DISEASE") print("-" * 60) # Carica dataset (disponibile su UCI Machine Learning Repository) # Dataset reale con 303 pazienti e 14 colonne try: # Prova diversi percorsi per il dataset try: df = pd.read_csv('heart_disease.csv') except: try: df = pd.read_csv('data/heart.csv') except: # Dataset di esempio se non trovato print("⚠️ Dataset non trovato, creazione dataset simulato...") np.random.seed(42) n_samples = 303 data = { 'age': np.random.randint(29, 78, n_samples), 'sex': np.random.choice([0, 1], n_samples, p=[0.68, 0.32]), 'cp': np.random.choice([0, 1, 2, 3], n_samples, p=[0.48, 0.16, 0.16, 0.20]), 'trestbps': np.random.randint(94, 201, n_samples), 'chol': np.random.randint(126, 565, n_samples), 'fbs': np.random.choice([0, 1], n_samples, p=[0.85, 0.15]), 'restecg': np.random.choice([0, 1, 2], n_samples, p=[0.48, 0.50, 0.02]), 'thalach': np.random.randint(71, 203, n_samples), 'exang': np.random.choice([0, 1], n_samples, p=[0.66, 0.34]), 'oldpeak': np.round(np.random.uniform(0, 6.2, n_samples), 1), 'slope': np.random.choice([0, 1, 2], n_samples, p=[0.46, 0.36, 0.18]), 'ca': np.random.choice([0, 1, 2, 3], n_samples, p=[0.58, 0.24, 0.13, 0.05]), 'thal': np.random.choice([1, 2, 3], n_samples, p=[0.03, 0.50, 0.47]), 'target': np.random.choice([0, 1], n_samples, p=[0.46, 0.54]) } df = pd.DataFrame(data) print("✅ Dataset caricato con successo!") except Exception as e: print(f"❌ Errore caricamento dataset: {e}") print("Continueremo con spiegazioni concettuali...") df = pd.DataFrame() if not df.empty: # 2. ANALISI ESPLORATIVA DEI DATI (EDA) print(f"\n📊 2. ANALISI ESPLORATIVA DATI (EDA)") print("-" * 60) print(f"📈 DIMENSIONI DATASET: {df.shape[0]} pazienti, {df.shape[1]} features") print(f"🎯 VARIABILE TARGET: 'target' (0 = no disease, 1 = disease)") # Informazioni base print("\n📋 INFORMAZIONI DATASET:") print(df.info()) # Statistiche descrittive print("\n📊 STATISTICHE DESCRITTIVE:") print(df.describe().round(2)) # Controllo valori nulli print("\n🔍 VALORI NULLI:") null_counts = df.isnull().sum() for col, count in null_counts.items(): if count > 0: print(f" • {col}: {count} valori nulli ({count/len(df)*100:.1f}%)") if null_counts.sum() == 0: print(" ✅ Nessun valore nullo trovato!") # Distribuzione target print(f"\n🎯 DISTRIBUZIONE TARGET (malattia cardiaca):") target_dist = df['target'].value_counts() for val, count in target_dist.items(): percentage = count / len(df) * 100 disease_status = "NO malattia" if val == 0 else "CON malattia" print(f" • {disease_status}: {count} pazienti ({percentage:.1f}%)") # Visualizzazioni (scommenta per vedere su Colab) """ print("\n🎨 VISUALIZZAZIONI DATASET:") # 1. Distribuzione età plt.figure(figsize=(10, 6)) plt.hist(df['age'], bins=20, edgecolor='black', alpha=0.7) plt.title('Distribuzione Età Pazienti', fontsize=14) plt.xlabel('Età (anni)') plt.ylabel('Numero Pazienti') plt.grid(True, alpha=0.3) plt.show() # 2. Distribuzione target per sesso plt.figure(figsize=(10, 6)) cross_tab = pd.crosstab(df['sex'], df['target']) cross_tab.plot(kind='bar', stacked=True) plt.title('Distribuzione Malattia per Sesso', fontsize=14) plt.xlabel('Sesso (0=F, 1=M)') plt.ylabel('Numero Pazienti') plt.legend(['No Malattia', 'Malattia']) plt.xticks(rotation=0) plt.grid(True, alpha=0.3) plt.show() # 3. Matrice di correlazione plt.figure(figsize=(12, 8)) correlation_matrix = df.corr() sns.heatmap(correlation_matrix, annot=True, fmt='.2f', cmap='coolwarm', square=True, linewidths=0.5) plt.title('Matrice di Correlazione Features', fontsize=14) plt.tight_layout() plt.show() # 4. Boxplot per features numeriche numeric_features = ['age', 'trestbps', 'chol', 'thalach', 'oldpeak'] fig, axes = plt.subplots(2, 3, figsize=(15, 10)) axes = axes.flatten() for i, feature in enumerate(numeric_features[:6]): axes[i].boxplot([df[df['target']==0][feature], df[df['target']==1][feature]], labels=['No Disease', 'Disease']) axes[i].set_title(f'Boxplot {feature}') axes[i].set_ylabel(feature) axes[i].grid(True, alpha=0.3) plt.tight_layout() plt.show() """ # 3. SPIEGAZIONE FEATURES CLINICHE print("\n🏥 3. SPIEGAZIONE FEATURES CLINICHE") print("-" * 60) feature_descriptions = { 'age': 'Età in anni', 'sex': 'Sesso (1 = maschio, 0 = femmina)', 'cp': 'Tipo dolore toracico (0-3): 0=tipico angina, 1=atipico angina, 2=non-angina, 3=asintomatico', 'trestbps': 'Pressione sanguigna a riposo (mmHg)', 'chol': 'Colesterolo sierico (mg/dl)', 'fbs': 'Glicemia a digiuno > 120 mg/dl (1=true, 0=false)', 'restecg': 'Risultati elettrocardiogramma a riposo (0-2)', 'thalach': 'Frequenza cardiaca massima raggiunta', 'exang': 'Angina indotta da esercizio (1=si, 0=no)', 'oldpeak': 'Depressione ST indotta da esercizio', 'slope': 'Pendenza segmento ST peak exercise (0-2)', 'ca': 'Numero di vasi principali colorati (0-3)', 'thal': 'Thalassemia (1=normale, 2=difetto fisso, 3=difetto reversibile)', 'target': 'Malattia cardiaca (0=no, 1=si)' } print("📋 DESCRIZIONE COMPLETA FEATURES:") for feature, description in feature_descriptions.items(): if feature in df.columns: print(f"\n🎯 {feature}:") print(f" {description}") # Statistiche per feature if df[feature].dtype in ['int64', 'float64']: print(f" Range: {df[feature].min()} - {df[feature].max()}") print(f" Media: {df[feature].mean():.1f}, Deviazione: {df[feature].std():.1f}") # Valori unici per feature categoriche if df[feature].nunique() < 10: print(f" Valori: {sorted(df[feature].unique())}") # 4. PREPROCESSING DEI DATI print("\n🔧 4. PREPROCESSING DEI DATI") print("-" * 60) # Copia dataset per preprocessing df_clean = df.copy() # Gestione outlier (semplificata) print("📊 GESTIONE OUTLIER:") numeric_cols = df_clean.select_dtypes(include=[np.number]).columns for col in numeric_cols: if col != 'target': # Non toccare target Q1 = df_clean[col].quantile(0.25) Q3 = df_clean[col].quantile(0.75) IQR = Q3 - Q1 lower_bound = Q1 - 1.5 * IQR upper_bound = Q3 + 1.5 * IQR outliers = ((df_clean[col] < lower_bound) | (df_clean[col] > upper_bound)).sum() if outliers > 0: # Winsorizzazione: sostituisci outlier con limiti df_clean[col] = np.where(df_clean[col] < lower_bound, lower_bound, df_clean[col]) df_clean[col] = np.where(df_clean[col] > upper_bound, upper_bound, df_clean[col]) print(f" • {col}: {outliers} outlier gestiti") # Codifica variabili categoriche print("\n🔤 CODIFICA VARIABILI CATEGORICHE:") categorical_cols = df_clean.select_dtypes(include=['object']).columns if len(categorical_cols) > 0: for col in categorical_cols: df_clean[col] = LabelEncoder().fit_transform(df_clean[col]) print(f" • {col}: codificata in numerico") else: print(" ✅ Nessuna variabile categorica da codificare") # Normalizzazione features print("\n📏 NORMALIZZAZIONE FEATURES:") features_to_scale = [col for col in numeric_cols if col != 'target'] scaler = StandardScaler() df_clean[features_to_scale] = scaler.fit_transform(df_clean[features_to_scale]) print(f" • Features scalate: {len(features_to_scale)}") print(" • Metodo: StandardScaler (media=0, deviazione=1)") # Split train/test print("\n📊 SPLIT DATI TRAINING/TEST:") X = df_clean.drop('target', axis=1) y = df_clean['target'] X_train, X_test, y_train, y_test = train_test_split( X, y, test_size=0.2, random_state=42, stratify=y ) print(f" • Dati totali: {len(df_clean)}") print(f" • Training set: {len(X_train)} ({len(X_train)/len(df_clean)*100:.1f}%)") print(f" • Test set: {len(X_test)} ({len(X_test)/len(df_clean)*100:.1f}%)") print(f" • Features: {X_train.shape[1]}") # Verifica distribuzione target print("\n🎯 VERIFICA DISTRIBUZIONE TARGET:") print(f" • Training - Malattia: {y_train.mean()*100:.1f}%") print(f" • Test - Malattia: {y_test.mean()*100:.1f}%") print(f" • Distribuzione mantenuta (stratificata)") # Salva dataset preparato print("\n💾 SALVATAGGIO DATI PREPARATI:") # Creiamo directory se non esiste import os os.makedirs('data', exist_ok=True) # Salva in CSV df_clean.to_csv('data/heart_disease_cleaned.csv', index=False) print(" ✅ Dataset salvato come 'data/heart_disease_cleaned.csv'") # Salva split in numpy per ML np.save('data/X_train.npy', X_train.values) np.save('data/X_test.npy', X_test.values) np.save('data/y_train.npy', y_train.values) np.save('data/y_test.npy', y_test.values) print(" ✅ Split training/test salvati in formato numpy") # Report finale fase 1 print("\n" + "=" * 80) print("✅ FASE 1 COMPLETATA: ANALISI E PREPARAZIONE DATI") print("=" * 80) print(f"\n📋 RIEPILOGO:") print(f"• Dataset originale: {df.shape[0]} pazienti, {df.shape[1]} colonne") print(f"• Dataset pulito: {df_clean.shape[0]} pazienti, {df_clean.shape[1]} colonne") print(f"• Features: {X_train.shape[1]} dopo preprocessing") print(f"• Training set: {X_train.shape[0]} campioni") print(f"• Test set: {X_test.shape[0]} campioni") print(f"• Target distribuzione: {y_train.mean()*100:.1f}% con malattia") print("\n🎯 PROSSIMA FASE: Progettazione Database MySQL") else: print("\n📝 SPIEGAZIONE CONCETTUALE DATASET:") print("Il dataset Cleveland Heart Disease contiene:") print("• 303 pazienti con sospetta malattia coronarica") print("• 13 features cliniche per ogni paziente") print("• Target: presenza e severità malattia (0-4)") print("\nFeatures principali:") print("1. Demografiche: età, sesso") print("2. Sintomi: tipo dolore toracico") print("3. Esami: pressione, colesterolo, ECG") print("4. Test da sforzo: frequenza max, angina, depressione ST") print("\n🎯 Obiettivo: Predire malattia basandosi su queste features")

🗄️ Fase 2: Database Medicale MySQL

🏥 Perché un Database per la Medicina?

In un contesto reale, i dati medici devono essere:

Sicuri: Accesso controllato, dati sensibili

Persistenti: Conservati oltre l'esecuzione programma

Storici: Tracciamento evoluzione pazienti

Condivisibili: Multipli medici accedono agli stessi dati

Backuppati: Prevenzione perdita dati critici

👤 Tabella: pazienti
Colonna
Tipo
Descrizione
id
INT AI PK
ID univoco
codice_fiscale
VARCHAR(16)
Identificativo
data_nascita
DATE
Età calcolata
sesso
ENUM('M','F')
M/F
data_creazione
TIMESTAMP
Auto
🏥 Tabella: esami_clinici
Colonna
Tipo
Descrizione
id
INT AI PK
ID esame
paziente_id
INT FK
Riferimento
data_esame
DATE
Quando
pressione
INT
mmHg
colesterolo
INT
mg/dl
🚫 COPIA BLOCCATA
# FASE 2: DATABASE MEDICALE MYSQL print("\n" + "=" * 80) print("FASE 2: PROGETTAZIONE E IMPLEMENTAZIONE DATABASE") print("=" * 80) import mysql.connector from mysql.connector import Error import pandas as pd from datetime import datetime, date import json import pickle class MedicalDatabase: """Database per sistema diagnostico cardiaco""" def __init__(self, host='localhost', user='root', password='', database='heart_disease_db'): self.host = host self.user = user self.password = password self.database = database self.connection = None def connect(self, create_if_not_exists=True): """Connette al database, creandolo se necessario""" try: # Prima connessione senza database specificato initial_conn = mysql.connector.connect( host=self.host, user=self.user, password=self.password ) cursor = initial_conn.cursor() # Crea database se non esiste if create_if_not_exists: cursor.execute(f"CREATE DATABASE IF NOT EXISTS {self.database}") print(f"✅ Database '{self.database}' creato/verificato") cursor.close() initial_conn.close() # Connessione al database specifico self.connection = mysql.connector.connect( host=self.host, user=self.user, password=self.password, database=self.database ) print(f"✅ Connesso a database: {self.database}") return True except Error as e: print(f"❌ Errore connessione database: {e}") return False def create_tables(self): """Crea tutte le tabelle del sistema medicale""" if not self.connection: print("❌ Non connesso al database") return False cursor = self.connection.cursor() # 1. Tabella pazienti patients_table = """ CREATE TABLE IF NOT EXISTS pazienti ( id INT AUTO_INCREMENT PRIMARY KEY, codice_fiscale VARCHAR(16) UNIQUE NOT NULL, nome VARCHAR(100) NOT NULL, cognome VARCHAR(100) NOT NULL, data_nascita DATE NOT NULL, sesso ENUM('M', 'F') NOT NULL, indirizzo VARCHAR(255), telefono VARCHAR(20), email VARCHAR(255), gruppo_sanguigno ENUM('A+', 'A-', 'B+', 'B-', 'AB+', 'AB-', '0+', '0-'), allergie TEXT, note_mediche TEXT, data_creazione TIMESTAMP DEFAULT CURRENT_TIMESTAMP, data_aggiornamento TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, INDEX idx_cognome (cognome), INDEX idx_data_nascita (data_nascita), INDEX idx_sesso (sesso) ) """ # 2. Tabella esami clinici exams_table = """ CREATE TABLE IF NOT EXISTS esami_clinici ( id INT AUTO_INCREMENT PRIMARY KEY, paziente_id INT NOT NULL, data_esame DATE NOT NULL, tipo_dolore_toracico ENUM('0', '1', '2', '3') COMMENT '0=tipico angina, 1=atipico, 2=non-angina, 3=asintomatico', pressione_riposo INT COMMENT 'mmHg', colesterolo INT COMMENT 'mg/dl', glicemia_digiuno BOOLEAN COMMENT '> 120 mg/dl', risultato_ecg ENUM('0', '1', '2'), frequenza_cardiaca_max INT, angina_esercizio BOOLEAN, depressione_st DECIMAL(3,1), pendenza_st ENUM('0', '1', '2'), vasi_principali INT CHECK (vasi_principali BETWEEN 0 AND 3), thalassemia ENUM('1', '2', '3') COMMENT '1=normale, 2=fisso, 3=reversibile', medico_referente VARCHAR(100), struttura VARCHAR(100), note TEXT, data_inserimento TIMESTAMP DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (paziente_id) REFERENCES pazienti(id) ON DELETE CASCADE, INDEX idx_paziente_data (paziente_id, data_esame), INDEX idx_data_esame (data_esame), INDEX idx_colesterolo (colesterolo), INDEX idx_pressione (pressione_riposo) ) """ # 3. Tabella diagnosi diagnoses_table = """ CREATE TABLE IF NOT EXISTS diagnosi ( id INT AUTO_INCREMENT PRIMARY KEY, paziente_id INT NOT NULL, data_diagnosi DATE NOT NULL, tipo_malattia ENUM('cardiopatia_iscemica', 'ipertensione', 'aritmia', 'altro'), severita INT CHECK (severita BETWEEN 0 AND 4) COMMENT '0=nessuna, 4=massima', confermata_da_test BOOLEAN DEFAULT FALSE, medico_diagnosta VARCHAR(100), note_cliniche TEXT, trattamento_prescritto TEXT, data_inserimento TIMESTAMP DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (paziente_id) REFERENCES pazienti(id) ON DELETE CASCADE, INDEX idx_paziente_malattia (paziente_id, tipo_malattia), INDEX idx_data_diagnosi (data_diagnosi), INDEX idx_severita (severita) ) """ # 4. Tabella modelli AI (per storage modelli addestrati) ai_models_table = """ CREATE TABLE IF NOT EXISTS modelli_ai ( id INT AUTO_INCREMENT PRIMARY KEY, nome_modello VARCHAR(100) NOT NULL, tipo_modello ENUM('albero', 'foresta', 'rete_neurale', 'svm') NOT NULL, algoritmo VARCHAR(100), versione VARCHAR(20) DEFAULT '1.0', modello_binario LONGBLOB, parametri_addestramento JSON, accuracy_training DECIMAL(5,4), precision_training DECIMAL(5,4), recall_training DECIMAL(5,4), f1_score_training DECIMAL(5,4), data_addestramento DATETIME NOT NULL, dati_addestramento_inizio DATE, dati_addestramento_fine DATE, numero_campioni_training INT, features_usate JSON, stato ENUM('attivo', 'deprecato', 'testing') DEFAULT 'testing', note TEXT, data_creazione TIMESTAMP DEFAULT CURRENT_TIMESTAMP, INDEX idx_tipo_modello (tipo_modello), INDEX idx_data_addestramento (data_addestramento), INDEX idx_stato (stato), INDEX idx_accuracy (accuracy_training) ) """ # 5. Tabella predizioni AI predictions_table = """ CREATE TABLE IF NOT EXISTS predizioni_ai ( id INT AUTO_INCREMENT PRIMARY KEY, paziente_id INT NOT NULL, esame_id INT, modello_ai_id INT NOT NULL, data_predizione DATETIME DEFAULT CURRENT_TIMESTAMP, probabilita_malattia DECIMAL(5,4) COMMENT '0-1, probabilità malattia', classe_predetta ENUM('sano', 'malato') NOT NULL, threshold_usato DECIMAL(3,2) DEFAULT 0.5, features_input JSON NOT NULL, spiegazione_predizione JSON COMMENT 'Feature importance, SHAP values', accuratezza_effettiva BOOLEAN COMMENT 'NULL=non ancora verificato, TRUE=corretta, FALSE=errata', data_verifica DATE, note TEXT, FOREIGN KEY (paziente_id) REFERENCES pazienti(id) ON DELETE CASCADE, FOREIGN KEY (esame_id) REFERENCES esami_clinici(id) ON DELETE SET NULL, FOREIGN KEY (modello_ai_id) REFERENCES modelli_ai(id) ON DELETE CASCADE, INDEX idx_paziente_predizione (paziente_id, data_predizione), INDEX idx_modello_predizione (modello_ai_id, data_predizione), INDEX idx_classe_predetta (classe_predetta), INDEX idx_probabilita (probabilita_malattia), INDEX idx_accuratezza (accuratezza_effettiva) ) """ # 6. Tabella audit log (tracciamento operazioni) audit_log_table = """ CREATE TABLE IF NOT EXISTS audit_log ( id INT AUTO_INCREMENT PRIMARY KEY, utente VARCHAR(100), azione VARCHAR(50) NOT NULL COMMENT 'CREATE, READ, UPDATE, DELETE, PREDICTION', tabella VARCHAR(50), record_id INT, dati_prima JSON, dati_dopo JSON, ip_address VARCHAR(45), user_agent VARCHAR(255), data_operazione TIMESTAMP DEFAULT CURRENT_TIMESTAMP, INDEX idx_azione (azione), INDEX idx_tabella (tabella), INDEX idx_data_operazione (data_operazione), INDEX idx_utente (utente) ) """ tables = [ ('pazienti', patients_table), ('esami_clinici', exams_table), ('diagnosi', diagnoses_table), ('modelli_ai', ai_models_table), ('predizioni_ai', predictions_table), ('audit_log', audit_log_table) ] print("\n🏗️ CREAZIONE TABELLE DATABASE:") print("-" * 40) for table_name, table_sql in tables: try: cursor.execute(table_sql) print(f"✅ Tabella '{table_name}' creata/verificata") except Error as e: print(f"❌ Errore creazione tabella '{table_name}': {e}") # Viste per reporting print("\n📊 CREAZIONE VISTE REPORTING:") # Vista: Pazienti a rischio (probabilità > 70%) risk_view = """ CREATE OR REPLACE VIEW vw_pazienti_rischio AS SELECT p.id as paziente_id, p.codice_fiscale, p.nome, p.cognome, p.data_nascita, TIMESTAMPDIFF(YEAR, p.data_nascita, CURDATE()) as eta, p.sesso, pa.probabilita_malattia, pa.classe_predetta, pa.data_predizione, m.nome_modello, m.accuracy_training FROM pazienti p JOIN predizioni_ai pa ON p.id = pa.paziente_id JOIN modelli_ai m ON pa.modello_ai_id = m.id WHERE pa.probabilita_malattia > 0.7 AND pa.data_predizione >= DATE_SUB(CURDATE(), INTERVAL 30 DAY) AND m.stato = 'attivo' ORDER BY pa.probabilita_malattia DESC """ # Vista: Performance modelli performance_view = """ CREATE OR REPLACE VIEW vw_performance_modelli AS SELECT m.nome_modello, m.tipo_modello, m.accuracy_training, m.precision_training, m.recall_training, m.f1_score_training, m.data_addestramento, COUNT(pa.id) as numero_predizioni, AVG(CASE WHEN pa.accuratezza_effettiva = TRUE THEN 1 WHEN pa.accuratezza_effettiva = FALSE THEN 0 ELSE NULL END) * 100 as percentuale_corrette FROM modelli_ai m LEFT JOIN predizioni_ai pa ON m.id = pa.modello_ai_id WHERE m.stato = 'attivo' GROUP BY m.id ORDER BY m.data_addestramento DESC """ views = [ ('vw_pazienti_rischio', risk_view), ('vw_performance_modelli', performance_view) ] for view_name, view_sql in views: try: cursor.execute(view_sql) print(f"✅ Vista '{view_name}' creata/aggiornata") except Error as e: print(f"⚠️ Errore creazione vista '{view_name}': {e}") # Stored Procedure: Calcola statistiche paziente procedures_sql = """ DELIMITER $$ CREATE PROCEDURE IF NOT EXISTS sp_statistiche_paziente( IN p_paziente_id INT ) BEGIN -- Statistiche base paziente SELECT p.*, TIMESTAMPDIFF(YEAR, p.data_nascita, CURDATE()) as eta_attuale, COUNT(DISTINCT e.id) as numero_esami, COUNT(DISTINCT d.id) as numero_diagnosi, MAX(e.data_esame) as ultimo_esame, MAX(d.data_diagnosi) as ultima_diagnosi FROM pazienti p LEFT JOIN esami_clinici e ON p.id = e.paziente_id LEFT JOIN diagnosi d ON p.id = d.paziente_id WHERE p.id = p_paziente_id GROUP BY p.id; -- Ultime predizioni AI SELECT pa.*, m.nome_modello, m.accuracy_training FROM predizioni_ai pa JOIN modelli_ai m ON pa.modello_ai_id = m.id WHERE pa.paziente_id = p_paziente_id ORDER BY pa.data_predizione DESC LIMIT 5; END$$ DELIMITER ; """ try: cursor.execute(procedures_sql) print("✅ Stored procedure 'sp_statistiche_paziente' creata") except Error as e: print(f"⚠️ Errore creazione stored procedure: {e}") cursor.close() self.connection.commit() print(f"\n✅ DATABASE COMPLETAMENTE CONFIGURATO") print(f"• 6 tabelle principali") print(f"• 2 viste analitiche") print(f"• 1 stored procedure") print(f"• Relazioni e vincoli implementati") return True def insert_sample_data(self): """Inserisce dati di esempio per testing""" if not self.connection: print("❌ Non connesso al database") return False cursor = self.connection.cursor() print("\n📥 INSERIMENTO DATI DI ESEMPIO:") print("-" * 40) # 1. Inserimento pazienti di esempio patients_data = [ ('RSSMRA80A01H501U', 'Mario', 'Rossi', '1980-01-01', 'M', 'Roma', '3331234567', 'mario.rossi@email.com', 'A+', 'Penicillina', 'Iperteso leggero'), ('BNCLRA75B42H501V', 'Laura', 'Bianchi', '1975-02-12', 'F', 'Milano', '3337654321', 'laura.bianchi@email.com', '0-', 'Nessuna', 'Controllo annuale'), ('VRDGSP70C12H501W', 'Giuseppe', 'Verdi', '1970-03-22', 'M', 'Napoli', '3339876543', 'giuseppe.verdi@email.com', 'B+', 'Aspirina', 'Fumatore'), ('NRRNNA85D04H501X', 'Anna', 'Neri', '1985-04-04', 'F', 'Torino', '3334567890', 'anna.neri@email.com', 'AB+', 'Nessuna', 'Sportiva'), ('GLLLCA90E15H501Y', 'Luca', 'Gialli', '1990-05-25', 'M', 'Bologna', '3330987654', 'luca.gialli@email.com', '0+', 'Noci', 'Controllo routine') ] insert_patient = """ INSERT INTO pazienti (codice_fiscale, nome, cognome, data_nascita, sesso, indirizzo, telefono, email, gruppo_sanguigno, allergie, note_mediche) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s) """ patient_ids = [] for patient in patients_data: try: cursor.execute(insert_patient, patient) patient_ids.append(cursor.lastrowid) except Error as e: print(f"⚠️ Errore inserimento paziente: {e}") self.connection.commit() print(f"✅ {len(patient_ids)} pazienti inseriti") # 2. Inserimento esami clinici if patient_ids: exams_data = [] for i, patient_id in enumerate(patient_ids): # Ogni paziente ha 1-3 esami num_exams = np.random.randint(1, 4) for j in range(num_exams): exam_date = date(2023, np.random.randint(1, 13), np.random.randint(1, 28)) exam = ( patient_id, exam_date, str(np.random.choice(['0', '1', '2', '3'])), np.random.randint(120, 180), np.random.randint(180, 300), np.random.choice([True, False]), str(np.random.choice(['0', '1', '2'])), np.random.randint(140, 190), np.random.choice([True, False]), round(np.random.uniform(0, 4), 1), str(np.random.choice(['0', '1', '2'])), np.random.randint(0, 4), str(np.random.choice(['1', '2', '3'])), 'Dr. Smith', 'Ospedale Civile' ) exams_data.append(exam) insert_exam = """ INSERT INTO esami_clinici (paziente_id, data_esame, tipo_dolore_toracico, pressione_riposo, colesterolo, glicemia_digiuno, risultato_ecg, frequenza_cardiaca_max, angina_esercizio, depressione_st, pendenza_st, vasi_principali, thalassemia, medico_referente, struttura) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s) """ try: cursor.executemany(insert_exam, exams_data) print(f"✅ {cursor.rowcount} esami clinici inseriti") except Error as e: print(f"⚠️ Errore inserimento esami: {e}") self.connection.commit() # 3. Inserimento modelli AI di esempio models_data = [ ('Heart Disease RF v1', 'foresta', 'RandomForest', '1.0', pickle.dumps({'dummy': 'model'}), # Modello dummy serializzato '{"n_estimators": 100, "max_depth": 10}', 0.85, 0.82, 0.87, 0.84, datetime.now(), '2023-01-01', '2023-12-01', 1000, '["age", "sex", "cp", "trestbps", "chol"]', 'attivo'), ('Heart Disease NN v1', 'rete_neurale', 'NeuralNetwork', '1.0', pickle.dumps({'dummy': 'model'}), '{"layers": [64, 32], "activation": "relu"}', 0.88, 0.85, 0.90, 0.87, datetime.now(), '2023-01-01', '2023-12-01', 1000, '["age", "sex", "cp", "trestbps", "chol", "thalach"]', 'testing') ] insert_model = """ INSERT INTO modelli_ai (nome_modello, tipo_modello, algoritmo, versione, modello_binario, parametri_addestramento, accuracy_training, precision_training, recall_training, f1_score_training, data_addestramento, dati_addestramento_inizio, dati_addestramento_fine, numero_campioni_training, features_usate, stato) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s) """ model_ids = [] for model in models_data: try: cursor.execute(insert_model, model) model_ids.append(cursor.lastrowid) except Error as e: print(f"⚠️ Errore inserimento modello AI: {e}") self.connection.commit() print(f"✅ {len(model_ids)} modelli AI inseriti") # 4. Inserimento predizioni di esempio if patient_ids and model_ids: predictions_data = [] for patient_id in patient_ids: for model_id in model_ids: prediction_date = datetime.now() probability = round(np.random.uniform(0.1, 0.9), 4) predicted_class = 'malato' if probability > 0.5 else 'sano' prediction = ( patient_id, None, # esame_id (opzionale) model_id, prediction_date, probability, predicted_class, 0.5, json.dumps({'age': 45, 'sex': 'M', 'cp': 1}), json.dumps({'feature_importance': {'age': 0.3, 'chol': 0.4}}), np.random.choice([True, False, None]), date.today() if np.random.random() > 0.5 else None ) predictions_data.append(prediction) insert_prediction = """ INSERT INTO predizioni_ai (paziente_id, esame_id, modello_ai_id, data_predizione, probabilita_malattia, classe_predetta, threshold_usato, features_input, spiegazione_predizione, accuratezza_effettiva, data_verifica) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s) """ try: cursor.executemany(insert_prediction, predictions_data) print(f"✅ {cursor.rowcount} predizioni AI inserite") except Error as e: print(f"⚠️ Errore inserimento predizioni: {e}") self.connection.commit() cursor.close() print("\n📋 RIEPILOGO DATI INSERITI:") print(f"• Pazienti: {len(patient_ids)}") print(f"• Esami clinici: {len(exams_data) if 'exams_data' in locals() else 0}") print(f"• Modelli AI: {len(model_ids)}") print(f"• Predizioni: {len(predictions_data) if 'predictions_data' in locals() else 0}") return True def query_database(self): """Esegue query di esempio per dimostrare funzionalità""" if not self.connection: print("❌ Non connesso al database") return cursor = self.connection.cursor(dictionary=True) print("\n🔍 QUERY DIMOSTRATIVE:") print("-" * 40) # 1. Conta pazienti per sesso print("\n1️⃣ PAZIENTI PER SESSO:") cursor.execute(""" SELECT sesso, COUNT(*) as conteggio FROM pazienti GROUP BY sesso ORDER BY conteggio DESC """) for row in cursor.fetchall(): sesso = 'Maschio' if row['sesso'] == 'M' else 'Femmina' print(f" • {sesso}: {row['conteggio']} pazienti") # 2. Pazienti con rischio alto (probabilità > 70%) print("\n2️⃣ PAZIENTI AD ALTO RISCHIO:") cursor.execute(""" SELECT p.nome, p.cognome, p.data_nascita, pa.probabilita_malattia, pa.classe_predetta, m.nome_modello FROM vw_pazienti_rischio pa JOIN pazienti p ON pa.paziente_id = p.id JOIN modelli_ai m ON pa.nome_modello = m.nome_modello WHERE pa.probabilita_malattia > 0.7 ORDER BY pa.probabilita_malattia DESC LIMIT 5 """) for row in cursor.fetchall(): eta = (date.today() - row['data_nascita']).days // 365 print(f" • {row['nome']} {row['cognome']} ({eta} anni)") print(f" Probabilità: {row['probabilita_malattia']*100:.1f}%") print(f" Predizione: {row['classe_predetta']}") print(f" Modello: {row['nome_modello']}") print() # 3. Performance modelli print("\n3️⃣ PERFORMANCE MODELLI AI:") cursor.execute("SELECT * FROM vw_performance_modelli") for row in cursor.fetchall(): print(f" • {row['nome_modello']} ({row['tipo_modello']})") print(f" Accuracy: {row['accuracy_training']:.3f}") print(f" Precision: {row['precision_training']:.3f}") print(f" Recall: {row['recall_training']:.3f}") print(f" Predizioni: {row['numero_predizioni']}") if row['percentuale_corrette']: print(f" Accuratezza reale: {row['percentuale_corrette']:.1f}%") print() # 4. Statistiche esami print("\n4️⃣ STATISTICHE ESAMI CLINICI:") cursor.execute(""" SELECT MIN(pressione_riposo) as pressione_min, MAX(pressione_riposo) as pressione_max, AVG(pressione_riposo) as pressione_media, MIN(colesterolo) as colesterolo_min, MAX(colesterolo) as colesterolo_max, AVG(colesterolo) as colesterolo_media, COUNT(*) as totale_esami FROM esami_clinici """) stats = cursor.fetchone() if stats: print(f" • Pressione: {stats['pressione_min']}-{stats['pressione_max']} mmHg") print(f" Media: {stats['pressione_media']:.1f} mmHg") print(f" • Colesterolo: {stats['colesterolo_min']}-{stats['colesterolo_max']} mg/dl") print(f" Media: {stats['colesterolo_media']:.1f} mg/dl") print(f" • Esami totali: {stats['totale_esami']}") cursor.close() print("\n✅ QUERY COMPLETATE") print("Il database è operativo e pronto per integrazione AI!") def export_to_dataframe(self, table_name, limit=1000): """Esporta dati da tabella a DataFrame pandas""" if not self.connection: print("❌ Non connesso al database") return pd.DataFrame() query = f"SELECT * FROM {table_name} LIMIT {limit}" try: df = pd.read_sql(query, self.connection) print(f"✅ Esportati {len(df)} record da '{table_name}'") return df except Error as e: print(f"❌ Errore esportazione: {e}") return pd.DataFrame() def close(self): """Chiude connessione database""" if self.connection and self.connection.is_connected(): self.connection.close() print("🔌 Connessione database chiusa") # DEMOSTRAZIONE DATABASE print("\n🚀 IMPLEMENTAZIONE DATABASE MEDICALE") print("=" * 60) # Crea istanza database (modifica credenziali se necessario) medical_db = MedicalDatabase( host='localhost', user='root', password='password', database='heart_disease_final' ) # 1. Connetti e crea database if medical_db.connect(): # 2. Crea tabelle medical_db.create_tables() # 3. Inserisci dati di esempio (commenta se non vuoi dati fake) medical_db.insert_sample_data() # 4. Esegui query dimostrative medical_db.query_database() # 5. Esporta dati per analisi AI print("\n📤 ESPORTAZIONE DATI PER ANALISI AI:") print("-" * 40) # Esporta pazienti patients_df = medical_db.export_to_dataframe('pazienti') if not patients_df.empty: print(f"• Pazienti: {patients_df.shape[0]} record, {patients_df.shape[1]} colonne") # Esporta esami clinici exams_df = medical_db.export_to_dataframe('esami_clinici') if not exams_df.empty: print(f"• Esami: {exams_df.shape[0]} record, {exams_df.shape[1]} colonne") # 6. Chiudi connessione medical_db.close() print("\n" + "=" * 80) print("✅ FASE 2 COMPLETATA: DATABASE IMPLEMENTATO") print("=" * 80) print("\n🎯 PROSSIMA FASE: Sviluppo Modelli Machine Learning")

🤖 Fase 3: Modelli di Classificazione

🔬 Approccio Scientifico: Il Metodo Comparativo

Nella ricerca medica, si testano diverse terapie per trovare la migliore.

Nel nostro progetto:

Albero Decisionale: Terapia semplice, interpretabile

Foresta Casuale: Comitato di esperti, più robusta

Rete Neurale: Approccio complesso, potenti pattern

Comparazione: Quale modello ha le migliori performance cliniche?

🔍 Confronto Modelli in Tempo Reale

🤖

Clicca un pulsante per vedere il confronto tra modelli

Verrai guidato passo-passo nell'analisi delle performance

🚫 COPIA BLOCCATA
# FASE 3: MODELLI DI CLASSIFICAZIONE print("\n" + "=" * 80) print("FASE 3: SVILUPPO E CONFRONTO MODELLI MACHINE LEARNING") print("=" * 80) 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, cross_val_score, GridSearchCV from sklearn.preprocessing import StandardScaler from sklearn.metrics import (accuracy_score, precision_score, recall_score, f1_score, confusion_matrix, classification_report, roc_auc_score, roc_curve, precision_recall_curve) from sklearn.tree import DecisionTreeClassifier, plot_tree from sklearn.ensemble import RandomForestClassifier from sklearn.svm import SVC from sklearn.neighbors import KNeighborsClassifier from sklearn.linear_model import LogisticRegression from xgboost import XGBClassifier import warnings warnings.filterwarnings('ignore') # Configurazione visualizzazioni plt.style.use('seaborn-v0_8-darkgrid') sns.set_palette("husl") class HeartDiseaseClassifier: """Sistema completo di classificazione per malattie cardiache""" def __init__(self): self.X_train = None self.X_test = None self.y_train = None self.y_test = None self.models = {} self.results = {} self.best_model = None self.feature_importance = {} def load_data(self): """Carica dati dal database o file""" print("\n📥 1. CARICAMENTO E PREPARAZIONE DATI") print("-" * 60) try: # Prova a caricare dati preparati dalla Fase 1 X_train = np.load('data/X_train.npy', allow_pickle=True) X_test = np.load('data/X_test.npy', allow_pickle=True) y_train = np.load('data/y_train.npy', allow_pickle=True) y_test = np.load('data/y_test.npy', allow_pickle=True) print("✅ Dati caricati da file locali") except: print("⚠️ File locali non trovati, carichiamo dataset simulato...") # Dataset simulato per dimostrazione np.random.seed(42) n_samples = 1000 # Genera features realistiche per malattie cardiache X = np.random.randn(n_samples, 13) # Aggiungi relazioni realistiche con target # Età, pressione, colesterolo influenzano rischio X[:, 0] = np.random.normal(54, 9, n_samples) # age X[:, 3] = np.random.normal(131, 18, n_samples) # trestbps X[:, 4] = np.random.normal(247, 52, n_samples) # chol # Genera target con logica realistica y = np.zeros(n_samples) for i in range(n_samples): risk_score = ( 0.3 * (X[i, 0] - 54) / 9 + # età 0.2 * (X[i, 3] - 131) / 18 + # pressione 0.2 * (X[i, 4] - 247) / 52 + # colesterolo 0.1 * X[i, 1] + # sesso 0.2 * np.random.randn() # random ) y[i] = 1 if risk_score > 0.5 else 0 # Split X_train, X_test, y_train, y_test = train_test_split( X, y, test_size=0.2, random_state=42, stratify=y ) self.X_train = X_train self.X_test = X_test self.y_train = y_train self.y_test = y_test print(f"\n📊 DIMENSIONI DATASET:") print(f" • Training: {X_train.shape[0]} campioni, {X_train.shape[1]} features") print(f" • Test: {X_test.shape[0]} campioni") print(f" • Distribuzione target (train): {y_train.mean()*100:.1f}% malattia") print(f" • Distribuzione target (test): {y_test.mean()*100:.1f}% malattia") return True def train_models(self): """Addestra multipli modelli di classificazione""" print("\n🤖 2. ADDESTRAMENTO MODELLI") print("-" * 60) # Definizione modelli con parametri ragionevoli model_configs = { 'Decision Tree': { 'model': DecisionTreeClassifier( max_depth=5, min_samples_split=10, random_state=42 ), 'color': '#10b981' }, 'Random Forest': { 'model': RandomForestClassifier( n_estimators=100, max_depth=8, random_state=42, n_jobs=-1 ), 'color': '#3b82f6' }, 'Logistic Regression': { 'model': LogisticRegression( C=1.0, random_state=42, max_iter=1000 ), 'color': '#8b5cf6' }, 'SVM': { 'model': SVC( C=1.0, kernel='rbf', probability=True, random_state=42 ), 'color': '#ec4899' }, 'K-Neighbors': { 'model': KNeighborsClassifier( n_neighbors=5 ), 'color': '#f59e0b' }, 'XGBoost': { 'model': XGBClassifier( n_estimators=100, max_depth=6, learning_rate=0.1, random_state=42, use_label_encoder=False, eval_metric='logloss' ), 'color': '#ef4444' } } print("🎯 MODELLI IN ADDESTRAMENTO:") for name, config in model_configs.items(): print(f" • {name}") # Addestramento e valutazione per ogni modello print("\n📈 VALUTAZIONE MODELLI (cross-validation):") for name, config in model_configs.items(): model = config['model'] print(f"\n 🔄 {name}:") # Cross-validation per stima robusta cv_scores = cross_val_score( model, self.X_train, self.y_train, cv=5, scoring='accuracy', n_jobs=-1 ) # Addestra sul training completo model.fit(self.X_train, self.y_train) # Predizioni y_pred = model.predict(self.X_test) y_pred_proba = model.predict_proba(self.X_test)[:, 1] if hasattr(model, 'predict_proba') else None # Calcola metriche accuracy = accuracy_score(self.y_test, y_pred) precision = precision_score(self.y_test, y_pred) recall = recall_score(self.y_test, y_pred) f1 = f1_score(self.y_test, y_pred) # ROC-AUC se disponibili probabilità roc_auc = None if y_pred_proba is not None: roc_auc = roc_auc_score(self.y_test, y_pred_proba) # Salva risultati self.models[name] = { 'model': model, 'config': config, 'cv_mean': cv_scores.mean(), 'cv_std': cv_scores.std(), 'accuracy': accuracy, 'precision': precision, 'recall': recall, 'f1': f1, 'roc_auc': roc_auc, 'y_pred': y_pred, 'y_pred_proba': y_pred_proba } # Stampa risultati print(f" CV Accuracy: {cv_scores.mean():.3f} (+/- {cv_scores.std()*2:.3f})") print(f" Test Accuracy: {accuracy:.3f}") print(f" Precision: {precision:.3f}, Recall: {recall:.3f}, F1: {f1:.3f}") if roc_auc: print(f" ROC-AUC: {roc_auc:.3f}") # Feature importance per modelli che la supportano if hasattr(model, 'feature_importances_'): importance = model.feature_importances_ self.feature_importance[name] = importance # Identifica miglior modello self.find_best_model() return True def find_best_model(self): """Identifica il modello con le migliori performance""" print("\n🏆 3. IDENTIFICAZIONE MIGLIOR MODELLO") print("-" * 60) # Usa F1-score come metrica principale (bilancia precision e recall) best_score = -1 best_model_name = None print("📊 CONFRONTO FINALE MODELLI:") print(f"{'Modello':20s} {'Accuracy':>10s} {'Precision':>10s} {'Recall':>10s} {'F1':>10s} {'ROC-AUC':>10s}") print("-" * 80) for name, results in self.models.items(): print(f"{name:20s} {results['accuracy']:10.3f} {results['precision']:10.3f} " f"{results['recall']:10.3f} {results['f1']:10.3f} " f"{results['roc_auc'] if results['roc_auc'] else 'N/A':>10}") if results['f1'] > best_score: best_score = results['f1'] best_model_name = name self.best_model = { 'name': best_model_name, 'results': self.models[best_model_name] } print("-" * 80) print(f"\n🎯 MIGLIOR MODELLO: {best_model_name}") print(f" F1-Score: {best_score:.3f}") print(f" Accuracy: {self.models[best_model_name]['accuracy']:.3f}") return best_model_name def visualize_results(self): """Crea visualizzazioni complete dei risultati""" print("\n🎨 4. VISUALIZZAZIONI RISULTATI") print("-" * 60) # Preparazione dati per visualizzazioni model_names = list(self.models.keys()) metrics = ['accuracy', 'precision', 'recall', 'f1'] # 1. Confronto metriche tra modelli print("\n📈 1. CONFRONTO METRICHE MODELLI:") # Crea DataFrame per confronto comparison_data = [] for name in model_names: row = {'Model': name} for metric in metrics: row[metric.capitalize()] = self.models[name][metric] comparison_data.append(row) df_comparison = pd.DataFrame(comparison_data) # Visualizzazione (scommenta per vedere su Colab) """ fig, axes = plt.subplots(2, 2, figsize=(15, 10)) axes = axes.flatten() for i, metric in enumerate(metrics): ax = axes[i] data = df_comparison[['Model', metric.capitalize()]].sort_values(metric.capitalize()) bars = ax.barh(data['Model'], data[metric.capitalize()], color=[self.models[name]['config']['color'] for name in data['Model']]) ax.set_title(f'{metric.capitalize()} per Modello') ax.set_xlabel(metric.capitalize()) ax.set_xlim(0, 1) # Aggiungi valori sulle barre for bar in bars: width = bar.get_width() ax.text(width + 0.01, bar.get_y() + bar.get_height()/2, f'{width:.3f}', ha='left', va='center') plt.tight_layout() plt.show() """ # 2. Matrice di confusione per miglior modello print("\n📊 2. MATRICE DI CONFUSIONE (miglior modello):") best_name = self.best_model['name'] y_pred = self.models[best_name]['y_pred'] cm = confusion_matrix(self.y_test, y_pred) print(f"Modello: {best_name}") print(f"Matrice di confusione:") print(f"[[{cm[0,0]:3d} {cm[0,1]:3d}] ← Predette SANE") print(f" [{cm[1,0]:3d} {cm[1,1]:3d}]] ← Predette MALATE") print(f"\nInterpretazione:") print(f"• True Negatives (TN): {cm[0,0]} - Correttamente predette sane") print(f"• False Positives (FP): {cm[0,1]} - Sane predette come malate (tipo 1)") print(f"• False Negatives (FN): {cm[1,0]} - Malate predette come sane (tipo 2)") print(f"• True Positives (TP): {cm[1,1]} - Correttamente predette malate") # 3. Feature importance (se disponibile) if self.feature_importance: print("\n🎯 3. FEATURE IMPORTANCE:") best_model_name = self.best_model['name'] if best_model_name in self.feature_importance: importance = self.feature_importance[best_model_name] # Nomi features (ipotetici per demo) feature_names = [ 'Age', 'Sex', 'CP', 'Trestbps', 'Chol', 'Fbs', 'Restecg', 'Thalach', 'Exang', 'Oldpeak', 'Slope', 'Ca', 'Thal' ] # Crea DataFrame per importanza importance_df = pd.DataFrame({ 'Feature': feature_names[:len(importance)], 'Importance': importance }).sort_values('Importance', ascending=False) print(f"\nTop 5 features più importanti per {best_model_name}:") for i, row in importance_df.head(5).iterrows(): print(f" {i+1}. {row['Feature']}: {row['Importance']:.3f}") # 4. Curve ROC e Precision-Recall print("\n📉 4. CURVE DI VALUTAZIONE:") # ROC Curve print("• ROC Curve (Receiver Operating Characteristic):") print(" Mostra trade-off tra True Positive Rate e False Positive Rate") print(" Area sotto la curva (AUC) ideale: 1.0") # Precision-Recall Curve print("\n• Precision-Recall Curve:") print(" Importante per dataset sbilanciati") print(" Mostra trade-off tra precision e recall") # Visualizzazione (scommenta per vedere su Colab) """ fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(15, 6)) # ROC Curve for name in model_names: if self.models[name]['y_pred_proba'] is not None: fpr, tpr, _ = roc_curve(self.y_test, self.models[name]['y_pred_proba']) roc_auc = self.models[name]['roc_auc'] ax1.plot(fpr, tpr, label=f'{name} (AUC = {roc_auc:.3f})', color=self.models[name]['config']['color'], linewidth=2) ax1.plot([0, 1], [0, 1], 'k--', label='Random Classifier') ax1.set_xlabel('False Positive Rate') ax1.set_ylabel('True Positive Rate') ax1.set_title('ROC Curves') ax1.legend(loc='lower right') ax1.grid(True, alpha=0.3) # Precision-Recall Curve for name in model_names: if self.models[name]['y_pred_proba'] is not None: precision, recall, _ = precision_recall_curve( self.y_test, self.models[name]['y_pred_proba'] ) ax2.plot(recall, precision, label=name, color=self.models[name]['config']['color'], linewidth=2) ax2.set_xlabel('Recall') ax2.set_ylabel('Precision') ax2.set_title('Precision-Recall Curves') ax2.legend(loc='lower left') ax2.grid(True, alpha=0.3) plt.tight_layout() plt.show() """ print("\n✅ Visualizzazioni preparate (scommenta per vedere)") def optimize_best_model(self): """Ottimizza iperparametri del miglior modello""" print("\n⚙️ 5. OTTIMIZZAZIONE IPERPARAMETRI") print("-" * 60) best_name = self.best_model['name'] print(f"Ottimizzazione per: {best_name}") if best_name == 'Random Forest': # Grid search per Random Forest param_grid = { 'n_estimators': [50, 100, 200], 'max_depth': [5, 8, 10, None], 'min_samples_split': [2, 5, 10], 'min_samples_leaf': [1, 2, 4] } grid_search = GridSearchCV( RandomForestClassifier(random_state=42), param_grid, cv=5, scoring='f1', n_jobs=-1, verbose=1 ) print("🔍 Grid Search in corso...") grid_search.fit(self.X_train, self.y_train) print(f"\n🎯 Migliori parametri trovati:") for param, value in grid_search.best_params_.items(): print(f" • {param}: {value}") print(f"🎯 Miglior F1-score: {grid_search.best_score_:.3f}") # Aggiorna miglior modello con parametri ottimizzati self.models[best_name]['model'] = grid_search.best_estimator_ self.best_model['results']['model'] = grid_search.best_estimator_ # Ri-valutazione y_pred = grid_search.predict(self.X_test) new_f1 = f1_score(self.y_test, y_pred) print(f"🎯 F1-score su test set: {new_f1:.3f}") elif best_name == 'Decision Tree': # Ottimizzazione albero decisionale print("🔍 Ricerca miglior profondità...") depths = range(2, 15) train_scores = [] test_scores = [] for depth in depths: tree = DecisionTreeClassifier(max_depth=depth, random_state=42) tree.fit(self.X_train, self.y_train) train_scores.append(tree.score(self.X_train, self.y_train)) test_scores.append(tree.score(self.X_test, self.y_test)) best_depth = depths[np.argmax(test_scores)] print(f"🎯 Miglior profondità: {best_depth}") print(f"🎯 Accuracy corrispondente: {max(test_scores):.3f}") else: print(f"⚠️ Ottimizzazione per {best_name} non implementata in questa demo") print(" Puoi implementarla come esercizio aggiuntivo!") return True def save_models(self): """Salva modelli addestrati per uso futuro""" print("\n💾 6. SALVATAGGIO MODELLI") print("-" * 60) import pickle import os # Crea directory se non esiste os.makedirs('models', exist_ok=True) # Salva ogni modello for name, data in self.models.items(): filename = f'models/{name.lower().replace(" ", "_")}.pkl' with open(filename, 'wb') as f: pickle.dump(data['model'], f) print(f"✅ Modello salvato: {filename}") # Salva risultati comparativi results_df = pd.DataFrame({ 'Model': list(self.models.keys()), 'CV_Mean': [data['cv_mean'] for data in self.models.values()], 'CV_Std': [data['cv_std'] for data in self.models.values()], 'Accuracy': [data['accuracy'] for data in self.models.values()], 'Precision': [data['precision'] for data in self.models.values()], 'Recall': [data['recall'] for data in self.models.values()], 'F1': [data['f1'] for data in self.models.values()], 'ROC_AUC': [data['roc_auc'] for data in self.models.values()] }) results_df.to_csv('models/model_comparison.csv', index=False) print("✅ Risultati comparativi salvati: models/model_comparison.csv") # Salva miglior modello separatamente best_filename = f'models/best_model.pkl' with open(best_filename, 'wb') as f: pickle.dump(self.best_model['results']['model'], f) print(f"✅ Miglior modello salvato: {best_filename}") print(f" Modello: {self.best_model['name']}") print(f" F1-Score: {self.best_model['results']['f1']:.3f}") return True # ESECUZIONE COMPLETA FASE 3 print("\n🚀 AVVIO FASE 3: ADDESTRAMENTO MODELLI") print("=" * 60) # Crea classificatore classifier = HeartDiseaseClassifier() # 1. Carica dati if classifier.load_data(): # 2. Addestra modelli classifier.train_models() # 3. Visualizza risultati classifier.visualize_results() # 4. Ottimizza miglior modello classifier.optimize_best_model() # 5. Salva modelli classifier.save_models() # Report finale print("\n" + "=" * 80) print("✅ FASE 3 COMPLETATA: MODELLI ADDESTRATI E VALUTATI") print("=" * 80) best_model = classifier.best_model print(f"\n🎯 RISULTATI FINALI:") print(f"• Miglior modello: {best_model['name']}") print(f"• F1-Score: {best_model['results']['f1']:.3f}") print(f"• Accuracy: {best_model['results']['accuracy']:.3f}") print(f"• Precision: {best_model['results']['precision']:.3f}") print(f"• Recall: {best_model['results']['recall']:.3f}") print(f"\n📊 PERFORMANCE SU TEST SET:") print(f"• Campioni test: {classifier.X_test.shape[0]}") print(f"• Malattia reale: {classifier.y_test.mean()*100:.1f}%") print(f"• Malattia predetta: {best_model['results']['y_pred'].mean()*100:.1f}%") print(f"\n💡 ANALISI CLINICA:") if best_model['results']['recall'] > 0.8: print("✅ Buon recall: Poche false negative (malati non diagnosticati)") else: print("⚠️ Recall basso: Rischio di non diagnosticare malati") if best_model['results']['precision'] > 0.8: print("✅ Buona precision: Poche false positive (sani diagnosticati come malati)") else: print("⚠️ Precision bassa: Rischio di falsi allarmi") print(f"\n🎯 PROSSIMA FASE: Integrazione con Database e Reti Neurali") else: print("❌ Errore nel caricamento dati")

🧠 Fase 4: Reti Neurali per Diagnosi

🧬 L'Analogia del Cervello Medico

Un medico esperto riconosce pattern complessi che sfuggono a regole semplici:

Neuroni: Come sinapsi che si attivano

Pesi: Esperienza accumulata

Backpropagation: Apprendimento dagli errori

Dropout: Non fare troppo affidamento su singoli sintomi

Regularization: Evitare diagnosi troppo specifiche (overfitting)

📈 Loss durante Training
📉

Training Loss vs Validation Loss

Monitoraggio convergenza rete

🎯 Accuracy durante Training
📊

Training Accuracy vs Validation

Verifica apprendimento

🤖 Confronto Modelli
⚖️

ML vs Neural Networks

Quale approccio è migliore?

🚫 COPIA BLOCCATA
# FASE 4: RETI NEURALI PER DIAGNOSI print("\n" + "=" * 80) print("FASE 4: RETI NEURALI ARTIFICIALI PER DIAGNOSI CARDIACA") print("=" * 80) 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.preprocessing import StandardScaler from sklearn.metrics import (accuracy_score, precision_score, recall_score, f1_score, confusion_matrix, classification_report, roc_auc_score, roc_curve) import tensorflow as tf from tensorflow import keras from tensorflow.keras import layers, models, callbacks import warnings warnings.filterwarnings('ignore') # Configurazione TensorFlow per performance tf.config.threading.set_intra_op_parallelism_threads(2) tf.config.threading.set_inter_op_parallelism_threads(2) class NeuralNetworkDiagnostic: """Rete neurale per diagnosi malattie cardiache""" def __init__(self): self.X_train = None self.X_test = None self.y_train = None self.y_test = None self.model = None self.history = None self.scaler = StandardScaler() def load_and_prepare_data(self): """Carica e prepara dati per rete neurale""" print("\n📥 1. PREPARAZIONE DATI PER RETE NEURALE") print("-" * 60) try: # Carica dati dalla Fase 1 X_train = np.load('data/X_train.npy', allow_pickle=True) X_test = np.load('data/X_test.npy', allow_pickle=True) y_train = np.load('data/y_train.npy', allow_pickle=True) y_test = np.load('data/y_test.npy', allow_pickle=True) print("✅ Dati caricati da file locali") except: print("⚠️ File non trovati, generazione dati simulati...") np.random.seed(42) n_samples = 1000 n_features = 13 X = np.random.randn(n_samples, n_features) # Aggiungi pattern complessi per rete neurale X[:, 0] = np.random.normal(54, 9, n_samples) # age X[:, 3] = np.random.normal(131, 18, n_samples) # trestbps X[:, 4] = np.random.normal(247, 52, n_samples) # chol # Target con pattern non-lineare (ideale per NN) y = np.zeros(n_samples) for i in range(n_samples): # Pattern complesso che ML semplice non cattura bene non_linear_pattern = ( np.sin(X[i, 0] / 10) * 0.3 + # Non-lineare età np.exp(-((X[i, 3] - 130) ** 2) / 500) * 0.2 + # Gaussiana pressione np.tanh(X[i, 4] / 100) * 0.2 + # Non-lineare colesterolo X[i, 1] * 0.1 + # Lineare sesso np.random.randn() * 0.2 # Rumore ) y[i] = 1 if non_linear_pattern > 0.3 else 0 X_train, X_test, y_train, y_test = train_test_split( X, y, test_size=0.2, random_state=42, stratify=y ) # Scaling per rete neurale self.X_train = self.scaler.fit_transform(X_train) self.X_test = self.scaler.transform(X_test) self.y_train = y_train self.y_test = y_test print(f"\n📊 DATASET PER RETE NEURALE:") print(f" • Training: {self.X_train.shape[0]} campioni") print(f" • Test: {self.X_test.shape[0]} campioni") print(f" • Features: {self.X_train.shape[1]} (scalate)") print(f" • Malattia (train): {self.y_train.mean()*100:.1f}%") print(f" • Malattia (test): {self.y_test.mean()*100:.1f}%") return True def build_models(self): """Costruisce diverse architetture di rete neurale""" print("\n🏗️ 2. COSTRUZIONE ARCHITETTURE RETE NEURALE") print("-" * 60) models_dict = {} # 1. Rete semplice (baseline) print("🧠 1. Rete Neurale Semplice (1 layer nascosto):") simple_model = keras.Sequential([ layers.Dense(32, activation='relu', input_shape=(self.X_train.shape[1],)), layers.Dropout(0.2), layers.Dense(16, activation='relu'), layers.Dropout(0.2), layers.Dense(1, activation='sigmoid') ]) simple_model.compile( optimizer='adam', loss='binary_crossentropy', metrics=['accuracy', keras.metrics.Precision(name='precision'), keras.metrics.Recall(name='recall')] ) models_dict['Simple NN'] = simple_model print(" • Architettura: 32 → 16 → 1") print(" • Dropout: 0.2 per prevenire overfitting") print(" • Attivazione: ReLU (nascosti), Sigmoid (output)") # 2. Rete profonda (deep learning) print("\n🧠 2. Rete Neurale Profonda (3 layer nascosti):") deep_model = keras.Sequential([ layers.Dense(64, activation='relu', input_shape=(self.X_train.shape[1],)), layers.BatchNormalization(), layers.Dropout(0.3), layers.Dense(32, activation='relu'), layers.BatchNormalization(), layers.Dropout(0.3), layers.Dense(16, activation='relu'), layers.Dropout(0.2), layers.Dense(1, activation='sigmoid') ]) deep_model.compile( optimizer=keras.optimizers.Adam(learning_rate=0.001), loss='binary_crossentropy', metrics=['accuracy', keras.metrics.Precision(name='precision'), keras.metrics.Recall(name='recall'), keras.metrics.AUC(name='auc')] ) models_dict['Deep NN'] = deep_model print(" • Architettura: 64 → 32 → 16 → 1") print(" • Batch Normalization: Stabilizza training") print(" • Learning rate: 0.001 (ottimizzato)") # 3. Rete con regularizzazione avanzata print("\n🧠 3. Rete con Regularizzazione (L2 + Dropout):") regularized_model = keras.Sequential([ layers.Dense(48, activation='relu', kernel_regularizer=keras.regularizers.l2(0.001), input_shape=(self.X_train.shape[1],)), layers.Dropout(0.4), layers.Dense(24, activation='relu', kernel_regularizer=keras.regularizers.l2(0.001)), layers.Dropout(0.3), layers.Dense(12, activation='relu'), layers.Dropout(0.2), layers.Dense(1, activation='sigmoid') ]) regularized_model.compile( optimizer='adam', loss='binary_crossentropy', metrics=['accuracy', keras.metrics.Precision(name='precision'), keras.metrics.Recall(name='recall'), keras.metrics.AUC(name='auc')] ) models_dict['Regularized NN'] = regularized_model print(" • Regularizzazione L2: 0.001") print(" • Dropout: 0.4 → 0.3 → 0.2") print(" • Previene overfitting su dataset piccolo") self.models = models_dict return models_dict def train_models(self, epochs=100, batch_size=32): """Addestra tutte le architetture di rete""" print("\n🚀 3. ADDESTRAMENTO RETI NEURALI") print("-" * 60) # Callbacks per miglior training callbacks_list = [ callbacks.EarlyStopping( monitor='val_loss', patience=20, restore_best_weights=True, verbose=1 ), callbacks.ReduceLROnPlateau( monitor='val_loss', factor=0.5, patience=10, min_lr=0.00001, verbose=1 ), callbacks.ModelCheckpoint( 'models/best_nn_model.h5', monitor='val_accuracy', save_best_only=True, verbose=1 ) ] histories = {} trained_models = {} for name, model in self.models.items(): print(f"\n🎯 Addestramento: {name}") print(f" Epoche: {epochs}, Batch size: {batch_size}") history = model.fit( self.X_train, self.y_train, validation_split=0.2, epochs=epochs, batch_size=batch_size, callbacks=callbacks_list, verbose=0 ) histories[name] = history trained_models[name] = model # Valutazione su test set test_results = model.evaluate(self.X_test, self.y_test, verbose=0) print(f" 📊 Risultati test:") print(f" • Loss: {test_results[0]:.4f}") print(f" • Accuracy: {test_results[1]:.4f}") if len(test_results) > 2: print(f" • Precision: {test_results[2]:.4f}") print(f" • Recall: {test_results[3]:.4f}") if len(test_results) > 4: print(f" • AUC: {test_results[4]:.4f}") self.histories = histories self.trained_models = trained_models # Identifica miglior modello self.find_best_nn_model() return histories def find_best_nn_model(self): """Identifica la migliore architettura di rete neurale""" print("\n🏆 4. IDENTIFICAZIONE MIGLIORE RETE NEURALE") print("-" * 60) best_val_accuracy = 0 best_model_name = None best_model = None print("📊 CONFRONTO PERFORMANCE RETI NEURALI:") print(f"{'Modello':20s} {'Val Accuracy':>12s} {'Val Loss':>10s}") print("-" * 50) for name, history in self.histories.items(): val_acc = max(history.history['val_accuracy']) val_loss = min(history.history['val_loss']) print(f"{name:20s} {val_acc:12.4f} {val_loss:10.4f}") if val_acc > best_val_accuracy: best_val_accuracy = val_acc best_model_name = name best_model = self.trained_models[name] print("-" * 50) print(f"\n🎯 MIGLIORE RETE NEURALE: {best_model_name}") print(f" Validation Accuracy: {best_val_accuracy:.4f}") self.best_nn_model = { 'name': best_model_name, 'model': best_model, 'val_accuracy': best_val_accuracy, 'history': self.histories[best_model_name] } return best_model_name def evaluate_best_model(self): """Valutazione approfondita del miglior modello""" print("\n🔍 5. VALUTAZIONE APPROFONDITA MIGLIOR MODELLO") print("-" * 60) best_model = self.best_nn_model['model'] model_name = self.best_nn_model['name'] # Predizioni y_pred_proba = best_model.predict(self.X_test) y_pred = (y_pred_proba > 0.5).astype(int) # Metriche dettagliate accuracy = accuracy_score(self.y_test, y_pred) precision = precision_score(self.y_test, y_pred) recall = recall_score(self.y_test, y_pred) f1 = f1_score(self.y_test, y_pred) roc_auc = roc_auc_score(self.y_test, y_pred_proba) print(f"🎯 MODELLO: {model_name}") print(f"\n📊 METRICHE DI PERFORMANCE:") print(f"• Accuracy: {accuracy:.4f}") print(f"• Precision: {precision:.4f}") print(f"• Recall: {recall:.4f}") print(f"• F1-Score: {f1:.4f}") print(f"• ROC-AUC: {roc_auc:.4f}") # Matrice di confusione cm = confusion_matrix(self.y_test, y_pred) print(f"\n📈 MATRICE DI CONFUSIONE:") print(f"[[{cm[0,0]:3d} {cm[0,1]:3d}] ← Predette SANE") print(f" [{cm[1,0]:3d} {cm[1,1]:3d}]] ← Predette MALATE") # Interpretazione clinica print(f"\n🏥 INTERPRETAZIONE CLINICA:") sensitivity = recall # True Positive Rate specificity = cm[0,0] / (cm[0,0] + cm[0,1]) if (cm[0,0] + cm[0,1]) > 0 else 0 print(f"• Sensibilità (Recall): {sensitivity:.1%}") print(f" → Percentuale di malati correttamente identificati") print(f"• Specificità: {specificity:.1%}") print(f" → Percentuale di sani correttamente identificati") # Analisi errori print(f"\n🔎 ANALISI ERRORI:") false_negatives = cm[1,0] # Malati predetti come sani false_positives = cm[0,1] # Sani predetti come malati print(f"• Falsi Negativi: {false_negatives} pazienti") print(f" → MALATI non diagnosticati (rischio clinico)") print(f"• Falsi Positivi: {false_positives} pazienti") print(f" → SANI diagnosticati come malati (stress inutile)") # Raccomandazioni basate su performance print(f"\n💡 RACCOMANDAZIONI PER USO CLINICO:") if sensitivity > 0.9: print("✅ Alta sensibilità: Buono per screening (pochi malati persi)") else: print("⚠️ Sensibilità moderata: Considerare test aggiuntivi") if specificity > 0.9: print("✅ Alta specificità: Pochi falsi allarmi") else: print("⚠️ Specificità moderata: Confermare diagnosi con altri test") if roc_auc > 0.9: print("✅ Eccellente capacità discriminativa") elif roc_auc > 0.8: print("✅ Buona capacità discriminativa") else: print("⚠️ Capacità discriminativa migliorabile") # Salva risultati self.nn_results = { 'accuracy': accuracy, 'precision': precision, 'recall': recall, 'f1': f1, 'roc_auc': roc_auc, 'confusion_matrix': cm, 'y_pred': y_pred, 'y_pred_proba': y_pred_proba } return self.nn_results def visualize_training(self): """Visualizza il training delle reti neurali""" print("\n🎨 6. VISUALIZZAZIONI ADDESTRAMENTO") print("-" * 60) best_history = self.best_nn_model['history'] model_name = self.best_nn_model['name'] print(f"📊 Visualizzazioni per: {model_name}") # Visualizzazioni (scommenta per vedere su Colab) """ fig, axes = plt.subplots(2, 3, figsize=(15, 10)) # 1. Loss durante training axes[0,0].plot(best_history.history['loss'], label='Training Loss') axes[0,0].plot(best_history.history['val_loss'], label='Validation Loss') axes[0,0].set_title('Loss durante Training') axes[0,0].set_xlabel('Epoca') axes[0,0].set_ylabel('Loss') axes[0,0].legend() axes[0,0].grid(True, alpha=0.3) # 2. Accuracy durante training axes[0,1].plot(best_history.history['accuracy'], label='Training Accuracy') axes[0,1].plot(best_history.history['val_accuracy'], label='Validation Accuracy') axes[0,1].set_title('Accuracy durante Training') axes[0,1].set_xlabel('Epoca') axes[0,1].set_ylabel('Accuracy') axes[0,1].legend() axes[0,1].grid(True, alpha=0.3) # 3. Precision durante training (se disponibile) if 'precision' in best_history.history: axes[0,2].plot(best_history.history['precision'], label='Training Precision') axes[0,2].plot(best_history.history['val_precision'], label='Validation Precision') axes[0,2].set_title('Precision durante Training') axes[0,2].set_xlabel('Epoca') axes[0,2].set_ylabel('Precision') axes[0,2].legend() axes[0,2].grid(True, alpha=0.3) # 4. Recall durante training (se disponibile) if 'recall' in best_history.history: axes[1,0].plot(best_history.history['recall'], label='Training Recall') axes[1,0].plot(best_history.history['val_recall'], label='Validation Recall') axes[1,0].set_title('Recall durante Training') axes[1,0].set_xlabel('Epoca') axes[1,0].set_ylabel('Recall') axes[1,0].legend() axes[1,0].grid(True, alpha=0.3) # 5. Learning Rate durante training (se disponibile) if 'lr' in best_history.history: axes[1,1].plot(best_history.history['lr']) axes[1,1].set_title('Learning Rate durante Training') axes[1,1].set_xlabel('Epoca') axes[1,1].set_ylabel('Learning Rate') axes[1,1].set_yscale('log') axes[1,1].grid(True, alpha=0.3) # 6. Confronto tra tutte le architetture for name, history in self.histories.items(): axes[1,2].plot(history.history['val_accuracy'], label=name) axes[1,2].set_title('Confronto Validation Accuracy') axes[1,2].set_xlabel('Epoca') axes[1,2].set_ylabel('Validation Accuracy') axes[1,2].legend() axes[1,2].grid(True, alpha=0.3) plt.tight_layout() plt.show() """ print("✅ Visualizzazioni preparate (scommenta per vedere)") # Stampa statistiche training print(f"\n📈 STATISTICHE TRAINING {model_name}:") final_epoch = len(best_history.history['accuracy']) - 1 print(f"• Epoche effettive: {final_epoch + 1}") print(f"• Training Accuracy finale: {best_history.history['accuracy'][-1]:.4f}") print(f"• Validation Accuracy finale: {best_history.history['val_accuracy'][-1]:.4f}") print(f"• Training Loss finale: {best_history.history['loss'][-1]:.4f}") print(f"• Validation Loss finale: {best_history.history['val_loss'][-1]:.4f}") # Controllo overfitting overfit_gap = best_history.history['accuracy'][-1] - best_history.history['val_accuracy'][-1] print(f"• Gap Training-Validation: {overfit_gap:.4f}") if overfit_gap > 0.1: print(" ⚠️ Possibile overfitting (gap > 0.1)") else: print(" ✅ Buona generalizzazione") def save_nn_model(self): """Salva il miglior modello di rete neurale""" print("\n💾 7. SALVATAGGIO MODELLO RETE NEURALE") print("-" * 60) import os # Crea directory se non esiste os.makedirs('models/nn', exist_ok=True) # Salva modello migliore best_model = self.best_nn_model['model'] model_name = self.best_nn_model['name'].replace(' ', '_').lower() # Salva in formato Keras model_path = f'models/nn/{model_name}.h5' best_model.save(model_path) print(f"✅ Modello salvato: {model_path}") # Salva scaler import pickle scaler_path = 'models/nn/scaler.pkl' with open(scaler_path, 'wb') as f: pickle.dump(self.scaler, f) print(f"✅ Scaler salvato: {scaler_path}") # Salva risultati results_path = 'models/nn/nn_results.pkl' with open(results_path, 'wb') as f: pickle.dump({ 'best_model_name': self.best_nn_model['name'], 'val_accuracy': self.best_nn_model['val_accuracy'], 'test_results': self.nn_results if hasattr(self, 'nn_results') else None, 'training_history': self.best_nn_model['history'].history }, f) print(f"✅ Risultati salvati: {results_path}") # Salva report di valutazione if hasattr(self, 'nn_results'): report_path = 'models/nn/evaluation_report.txt' with open(report_path, 'w') as f: f.write(f"RETE NEURALE - REPORT VALUTAZIONE\n") f.write("=" * 50 + "\n\n") f.write(f"Modello: {self.best_nn_model['name']}\n") f.write(f"Data valutazione: {pd.Timestamp.now()}\n\n") f.write("METRICHE DI PERFORMANCE:\n") f.write(f"• Accuracy: {self.nn_results['accuracy']:.4f}\n") f.write(f"• Precision: {self.nn_results['precision']:.4f}\n") f.write(f"• Recall: {self.nn_results['recall']:.4f}\n") f.write(f"• F1-Score: {self.nn_results['f1']:.4f}\n") f.write(f"• ROC-AUC: {self.nn_results['roc_auc']:.4f}\n\n") f.write("MATRICE DI CONFUSIONE:\n") cm = self.nn_results['confusion_matrix'] f.write(f"[[{cm[0,0]} {cm[0,1]}]\n") f.write(f" [{cm[1,0]} {cm[1,1]}]]\n\n") f.write("INTERPRETAZIONE CLINICA:\n") f.write(f"• Sensibilità: {self.nn_results['recall']:.1%}\n") specificity = cm[0,0] / (cm[0,0] + cm[0,1]) if (cm[0,0] + cm[0,1]) > 0 else 0 f.write(f"• Specificità: {specificity:.1%}\n") f.write(f"• Falsi Negativi: {cm[1,0]}\n") f.write(f"• Falsi Positivi: {cm[0,1]}\n") print(f"✅ Report di valutazione: {report_path}") return True # ESECUZIONE COMPLETA FASE 4 print("\n🚀 AVVIO FASE 4: RETI NEURALI PER DIAGNOSI") print("=" * 60) # Crea sistema neurale nn_diagnostic = NeuralNetworkDiagnostic() # 1. Carica e prepara dati if nn_diagnostic.load_and_prepare_data(): # 2. Costruisci modelli nn_diagnostic.build_models() # 3. Addestra modelli nn_diagnostic.train_models(epochs=100, batch_size=32) # 4. Valuta miglior modello nn_diagnostic.evaluate_best_model() # 5. Visualizza training nn_diagnostic.visualize_training() # 6. Salva modelli nn_diagnostic.save_nn_model() # Report finale print("\n" + "=" * 80) print("✅ FASE 4 COMPLETATA: RETI NEURALI ADDESTRATE") print("=" * 80) print(f"\n🎯 RISULTATI FINALI RETE NEURALE:") print(f"• Migliore architettura: {nn_diagnostic.best_nn_model['name']}") print(f"• Validation Accuracy: {nn_diagnostic.best_nn_model['val_accuracy']:.4f}") if hasattr(nn_diagnostic, 'nn_results'): print(f"• Test Accuracy: {nn_diagnostic.nn_results['accuracy']:.4f}") print(f"• F1-Score: {nn_diagnostic.nn_results['f1']:.4f}") print(f"• ROC-AUC: {nn_diagnostic.nn_results['roc_auc']:.4f}") print(f"\n💡 CONFRONTO CON MODELLI TRADIZIONALI:") print("Le reti neurali spesso catturano pattern non-lineari complessi") print("che i modelli ML tradizionali potrebbero perdere.") print("\n✅ Vantaggi reti neurali per diagnostica:") print("• Capacità di apprendere relazioni non-lineari complesse") print("• Feature engineering automatico (in reti profonde)") print("• Performance superiori con dati sufficienti") print("• Transfer learning possibile con modelli pre-addestrati") print(f"\n⚠️ Considerazioni pratiche:") print("• Richiedono più dati per training efficace") print("• Computazionalmente più costose") print("• Meno interpretabili (black box)") print("• Necessitano di tuning più sofisticato") print(f"\n🎯 PROSSIMA FASE: Integrazione Sistema Completo") else: print("❌ Errore nel caricamento dati")

🚀 Fase 5: Sistema Completo e Deployment

🏥 Il Sistema Ospedaliero Completo

Un ospedale reale ha molti componenti che lavorano insieme:

Database: Cartelle cliniche elettroniche

AI Models: Sistemi di supporto decisionale

API: Comunicazione tra reparti

Monitoraggio: Controllo qualità continuo

Backup: Sistema di emergenza

Interfaccia: Dashboard per medici

1
🏗️ Architettura del Sistema

Componenti Principali:

  1. Database MySQL: Storage pazienti, esami, predizioni
  2. Modelli ML: Alberi, Foreste, XGBoost addestrati
  3. Reti Neurali: Modelli deep learning TensorFlow
  4. API Flask/FastAPI: Interfaccia per medici
  5. Dashboard Streamlit: Visualizzazione risultati
  6. Sistema Monitoraggio: Logging e alert
  7. Backup System: Copie sicurezza automatiche

Flusso Dati: Paziente → Esami → Database → AI → Predizione → Dashboard

🚫 COPIA BLOCCATA
# FASE 5: SISTEMA COMPLETO E DEPLOYMENT print("\n" + "=" * 80) print("FASE 5: INTEGRAZIONE SISTEMA COMPLETO E DEPLOYMENT") print("=" * 80) import numpy as np import pandas as pd import mysql.connector from mysql.connector import Error import pickle import json from datetime import datetime import warnings warnings.filterwarnings('ignore') class CompleteMedicalAI: """Sistema completo di diagnostica AI end-to-end""" def __init__(self, db_config): self.db_config = db_config self.connection = None self.ml_models = {} self.nn_model = None self.scaler = None def setup_database_connection(self): """Stabilisce connessione al database""" print("\n🔌 1. CONNESSIONE DATABASE") print("-" * 60) try: self.connection = mysql.connector.connect(**self.db_config) if self.connection.is_connected(): print(f"✅ Connesso a database: {self.db_config['database']}") return True else: print("❌ Connessione fallita") return False except Error as e: print(f"❌ Errore connessione database: {e}") return False def load_trained_models(self): """Carica tutti i modelli addestrati""" print("\n🤖 2. CARICAMENTO MODELLI ADDESTRATI") print("-" * 60) models_loaded = 0 try: # Carica modelli ML tradizionali ml_models = ['decision_tree', 'random_forest', 'logistic_regression', 'xgboost'] for model_name in ml_models: try: with open(f'models/{model_name}.pkl', 'rb') as f: self.ml_models[model_name] = pickle.load(f) print(f"✅ Caricato: {model_name.replace('_', ' ').title()}") models_loaded += 1 except FileNotFoundError: print(f"⚠️ Non trovato: {model_name}") # Carica miglior modello ML try: with open('models/best_model.pkl', 'rb') as f: self.best_ml_model = pickle.load(f) print(f"✅ Caricato: Best ML Model") models_loaded += 1 except FileNotFoundError: print("⚠️ Best ML model non trovato") # Carica rete neurale try: import tensorflow as tf self.nn_model = tf.keras.models.load_model('models/nn/best_nn_model.h5') print(f"✅ Caricato: Neural Network Model") models_loaded += 1 # Carica scaler per NN with open('models/nn/scaler.pkl', 'rb') as f: self.scaler = pickle.load(f) print(f"✅ Caricato: Neural Network Scaler") except Exception as e: print(f"⚠️ Neural Network non caricata: {e}") print(f"\n📊 Totale modelli caricati: {models_loaded}") if models_loaded > 0: return True else: print("❌ Nessun modello caricato") return False except Exception as e: print(f"❌ Errore caricamento modelli: {e}") return False def predict_for_patient(self, patient_id): """Esegue predizioni per un paziente specifico""" print(f"\n🎯 3. PREDIZIONE PER PAZIENTE {patient_id}") print("-" * 60) if not self.connection: print("❌ Non connesso al database") return None # 1. Recupera dati paziente dal database cursor = self.connection.cursor(dictionary=True) query = """ SELECT TIMESTAMPDIFF(YEAR, p.data_nascita, CURDATE()) as age, CASE WHEN p.sesso = 'M' THEN 1 ELSE 0 END as sex, e.tipo_dolore_toracico as cp, e.pressione_riposo as trestbps, e.colesterolo as chol, e.glicemia_digiuno as fbs, e.risultato_ecg as restecg, e.frequenza_cardiaca_max as thalach, e.angina_esercizio as exang, e.depressione_st as oldpeak, e.pendenza_st as slope, e.vasi_principali as ca, e.thalassemia as thal FROM pazienti p JOIN esami_clinici e ON p.id = e.paziente_id WHERE p.id = %s ORDER BY e.data_esame DESC LIMIT 1 """ try: cursor.execute(query, (patient_id,)) patient_data = cursor.fetchone() if not patient_data: print(f"❌ Nessun dato trovato per paziente {patient_id}") return None print(f"✅ Dati paziente recuperati") # Converti in array numpy features = np.array([[ float(patient_data['age']), float(patient_data['sex']), float(patient_data['cp']), float(patient_data['trestbps']), float(patient_data['chol']), float(patient_data['fbs']), float(patient_data['restecg']), float(patient_data['thalach']), float(patient_data['exang']), float(patient_data['oldpeak']), float(patient_data['slope']), float(patient_data['ca']), float(patient_data['thal']) ]]) # 2. Esegui predizioni con tutti i modelli predictions = {} # Modelli ML tradizionali for model_name, model in self.ml_models.items(): try: proba = model.predict_proba(features)[0][1] pred = model.predict(features)[0] predictions[model_name] = { 'probability': float(proba), 'prediction': int(pred), 'class': 'malato' if pred == 1 else 'sano' } except Exception as e: print(f"⚠️ Errore predizione {model_name}: {e}") # Rete neurale if self.nn_model is not None and self.scaler is not None: try: # Scale features per NN features_scaled = self.scaler.transform(features) # Predizione NN nn_proba = self.nn_model.predict(features_scaled, verbose=0)[0][0] nn_pred = 1 if nn_proba > 0.5 else 0 predictions['neural_network'] = { 'probability': float(nn_proba), 'prediction': int(nn_pred), 'class': 'malato' if nn_pred == 1 else 'sano' } except Exception as e: print(f"⚠️ Errore predizione neural network: {e}") # 3. Calcola predizione ensemble (media delle probabilità) if predictions: avg_probability = np.mean([p['probability'] for p in predictions.values()]) ensemble_prediction = 1 if avg_probability > 0.5 else 0 predictions['ensemble'] = { 'probability': float(avg_probability), 'prediction': int(ensemble_prediction), 'class': 'malato' if ensemble_prediction == 1 else 'sano', 'model_count': len(predictions) } # 4. Salva predizioni nel database self.save_prediction_to_db(patient_id, predictions, features) # 5. Stampa risultati self.print_prediction_results(patient_id, patient_data, predictions) cursor.close() return predictions except Error as e: print(f"❌ Errore database: {e}") return None def save_prediction_to_db(self, patient_id, predictions, features): """Salva predizioni nel database""" if not self.connection: return False cursor = self.connection.cursor() try: # Per ogni modello, salva predizione for model_name, pred_data in predictions.items(): if model_name == 'ensemble': continue # Salva solo modelli individuali # Trova ID modello nel database cursor.execute( "SELECT id FROM modelli_ai WHERE nome_modello LIKE %s", (f'%{model_name}%',) ) model_result = cursor.fetchone() if model_result: model_id = model_result[0] insert_query = """ INSERT INTO predizioni_ai (paziente_id, modello_ai_id, data_predizione, probabilita_malattia, classe_predetta, features_input, spiegazione_predizione) VALUES (%s, %s, %s, %s, %s, %s, %s) """ values = ( patient_id, model_id, datetime.now(), pred_data['probability'], pred_data['class'], json.dumps(features.tolist()), json.dumps({'model': model_name, 'threshold': 0.5}) ) cursor.execute(insert_query, values) self.connection.commit() print(f"✅ Predizioni salvate nel database") return True except Error as e: print(f"❌ Errore salvataggio predizioni: {e}") self.connection.rollback() return False def print_prediction_results(self, patient_id, patient_data, predictions): """Stampa risultati predizione in formato leggibile""" print(f"\n📋 RISULTATI PREDIZIONE - Paziente ID: {patient_id}") print("=" * 60) # Informazioni paziente print(f"\n👤 INFORMAZIONI PAZIENTE:") print(f"• Età: {patient_data['age']} anni") print(f"• Sesso: {'Maschio' if patient_data['sex'] == 1 else 'Femmina'}") print(f"• Pressione: {patient_data['trestbps']} mmHg") print(f"• Colesterolo: {patient_data['chol']} mg/dl") # Risultati predizioni print(f"\n🎯 RISULTATI PREDIZIONI AI:") print(f"{'Modello':25s} {'Probabilità':>12s} {'Diagnosi':>10s}") print("-" * 50) for model_name, pred_data in predictions.items(): if model_name != 'ensemble': model_display = model_name.replace('_', ' ').title() prob_percent = f"{pred_data['probability']*100:.1f}%" diagnosis = pred_data['class'].upper() print(f"{model_display:25s} {prob_percent:>12s} {diagnosis:>10s}") print("-" * 50) # Risultato ensemble if 'ensemble' in predictions: ensemble = predictions['ensemble'] print(f"\n🏆 DIAGNOSI FINALE (ENSEMBLE):") print(f"• Probabilità media: {ensemble['probability']*100:.1f}%") print(f"• Diagnosi: {ensemble['class'].upper()}") print(f"• Basata su: {ensemble['model_count']} modelli") # Interpretazione clinica print(f"\n🏥 INTERPRETAZIONE CLINICA:") if ensemble['probability'] > 0.7: print("⚠️ ALTO RISCHIO - Raccomandazioni:") print(" • Consulto cardiologico urgente") print(" • ECG e test da sforzo") print(" • Monitoraggio pressione frequente") elif ensemble['probability'] > 0.3: print("⚠️ RISCHIO MODERATO - Raccomandazioni:") print(" • Controllo periodico") print(" • Stile di vita sano") print(" • Esami di routine annuali") else: print("✅ BASSO RISCHIO - Raccomandazioni:") print(" • Mantenere stile di vita sano") print(" • Controlli regolari") print(" • Attenzione a sintomi insoliti") def generate_daily_report(self): """Genera report giornaliero delle predizioni""" print("\n📊 4. REPORT GIORNALIERO") print("-" * 60) if not self.connection: print("❌ Non connesso al database") return None cursor = self.connection.cursor(dictionary=True) try: # Statistiche giornaliere query = """ SELECT DATE(data_predizione) as giorno, COUNT(*) as totale_predizioni, AVG(probabilita_malattia) as probabilita_media, SUM(CASE WHEN classe_predetta = 'malato' THEN 1 ELSE 0 END) as malati_predetti, SUM(CASE WHEN accuratezza_effettiva = TRUE THEN 1 ELSE 0 END) as predizioni_corrette, SUM(CASE WHEN accuratezza_effettiva = FALSE THEN 1 ELSE 0 END) as predizioni_errate FROM predizioni_ai WHERE data_predizione >= DATE_SUB(CURDATE(), INTERVAL 7 DAY) GROUP BY DATE(data_predizione) ORDER BY giorno DESC """ cursor.execute(query) daily_stats = cursor.fetchall() print(f"\n📈 STATISTICHE ULTIMI 7 GIORNI:") print(f"{'Giorno':12s} {'Predizioni':>10s} {'% Malati':>10s} {'Accuratezza':>12s}") print("-" * 60) for stat in daily_stats: giorno = stat['giorno'].strftime('%Y-%m-%d') total = stat['totale_predizioni'] malati_pct = (stat['malati_predetti'] / total * 100) if total > 0 else 0 # Calcola accuratezza se disponibili feedback if stat['predizioni_corrette'] is not None and stat['predizioni_errate'] is not None: correct = stat['predizioni_corrette'] wrong = stat['predizioni_errate'] if correct + wrong > 0: accuracy = correct / (correct + wrong) * 100 accuracy_str = f"{accuracy:.1f}%" else: accuracy_str = "N/A" else: accuracy_str = "N/A" print(f"{giorno:12s} {total:10d} {malati_pct:9.1f}% {accuracy_str:>12s}") # Performance modelli print(f"\n🤖 PERFORMANCE MODELLI (ultimi 30 giorni):") query = """ SELECT m.nome_modello, COUNT(pa.id) as predizioni_totali, AVG(pa.probabilita_malattia) as probabilita_media, AVG(CASE WHEN pa.accuratezza_effettiva = TRUE THEN 1 WHEN pa.accuratezza_effettiva = FALSE THEN 0 ELSE NULL END) * 100 as accuratezza_reale FROM modelli_ai m LEFT JOIN predizioni_ai pa ON m.id = pa.modello_ai_id WHERE pa.data_predizione >= DATE_SUB(CURDATE(), INTERVAL 30 DAY) GROUP BY m.id, m.nome_modello ORDER BY predizioni_totali DESC """ cursor.execute(query) model_stats = cursor.fetchall() for stat in model_stats: model_name = stat['nome_modello'] predictions = stat['predizioni_totali'] avg_prob = stat['probabilita_media'] * 100 if stat['probabilita_media'] else 0 accuracy = stat['accuratezza_reale'] if stat['accuratezza_reale'] else "N/A" print(f" • {model_name}:") print(f" Predizioni: {predictions}") print(f" Probabilità media: {avg_prob:.1f}%") if accuracy != "N/A": print(f" Accuratezza reale: {accuracy:.1f}%") cursor.close() return daily_stats except Error as e: print(f"❌ Errore generazione report: {e}") return None def create_api_endpoint(self): """Crea endpoint API semplice per il sistema""" print("\n🌐 5. API ENDPOINT PER IL SISTEMA") print("-" * 60) api_code = """ from flask import Flask, request, jsonify import numpy as np import pickle from datetime import datetime app = Flask(__name__) # Carica modelli all'avvio with open('models/best_model.pkl', 'rb') as f: model = pickle.load(f) with open('models/nn/scaler.pkl', 'rb') as f: scaler = pickle.load(f) # Endpoint principale @app.route('/predict', methods=['POST']) def predict(): '''Endpoint per predizione malattie cardiache''' try: # Ottieni dati dalla richiesta data = request.get_json() # Estrai features features = np.array([[ data['age'], data['sex'], data['cp'], data['trestbps'], data['chol'], data['fbs'], data['restecg'], data['thalach'], data['exang'], data['oldpeak'], data['slope'], data['ca'], data['thal'] ]]) # Predizione probability = model.predict_proba(features)[0][1] prediction = 1 if probability > 0.5 else 0 # Risposta response = { 'timestamp': datetime.now().isoformat(), 'patient_id': data.get('patient_id', 'unknown'), 'prediction': int(prediction), 'probability': float(probability), 'diagnosis': 'heart_disease' if prediction == 1 else 'healthy', 'confidence': 'high' if probability > 0.7 else 'moderate' if probability > 0.3 else 'low', 'recommendations': [ 'Consult cardiologist' if probability > 0.7 else 'Regular checkup', 'Maintain healthy lifestyle', 'Monitor blood pressure regularly' ] } return jsonify(response), 200 except Exception as e: return jsonify({'error': str(e)}), 400 # Endpoint di salute @app.route('/health', methods=['GET']) def health(): '''Health check endpoint''' return jsonify({ 'status': 'healthy', 'timestamp': datetime.now().isoformat(), 'model_loaded': True }), 200 if __name__ == '__main__': app.run(host='0.0.0.0', port=5000, debug=True) """ print("✅ Codice API Flask generato:") print("\nPer eseguire l'API:") print("1. Salva il codice come 'app.py'") print("2. Installa Flask: pip install flask") print("3. Esegui: python app.py") print("4. Accedi a: http://localhost:5000/predict") # Salva codice API with open('api_endpoint.py', 'w') as f: f.write(api_code) print("\n💾 Codice API salvato come 'api_endpoint.py'") return api_code def create_dashboard(self): """Crea dashboard Streamlit per visualizzazione""" print("\n📊 6. DASHBOARD STREAMLIT") print("-" * 60) dashboard_code = """ import streamlit as st import pandas as pd import numpy as np import matplotlib.pyplot as plt import seaborn as sns import mysql.connector from datetime import datetime, timedelta # Configurazione pagina st.set_page_config( page_title="Sistema Diagnostico Cardiaco AI", page_icon="❤️", layout="wide" ) # Titolo st.title("❤️ Sistema Diagnostico Cardiaco AI") st.markdown("Dashboard per monitoraggio predizioni malattie cardiache") # Sidebar per filtri st.sidebar.header("Filtri") date_range = st.sidebar.date_input( "Intervallo date", value=(datetime.now() - timedelta(days=30), datetime.now()) ) # Connessione database @st.cache_resource def get_connection(): return mysql.connector.connect( host='localhost', user='root', password='password', database='heart_disease_db' ) # Layout principale tab1, tab2, tab3 = st.tabs(["📈 Panoramica", "👤 Pazienti", "🤖 Modelli AI"]) with tab1: st.header("Panoramica Sistema") # Metriche chiave col1, col2, col3, col4 = st.columns(4) with col1: st.metric("Pazienti Totali", "1,234", "+12") with col2: st.metric("Predizioni Oggi", "56", "+3") with col3: st.metric("Accuracy Media", "87.5%", "+2.3%") with col4: st.metric("Rischio Alto", "23%", "-1.2%") # Grafico predizioni giornaliere st.subheader("Predizioni Giornaliere") # Dati di esempio (in produzione, query al database) dates = pd.date_range(start=date_range[0], end=date_range[1], freq='D') predictions = np.random.randint(20, 100, len(dates)) fig, ax = plt.subplots(figsize=(10, 4)) ax.plot(dates, predictions, marker='o', linewidth=2) ax.set_xlabel('Data') ax.set_ylabel('Numero Predizioni') ax.set_title('Predizioni Giornaliere') ax.grid(True, alpha=0.3) plt.xticks(rotation=45) st.pyplot(fig) with tab2: st.header("Gestione Pazienti") # Tabella pazienti st.subheader("Pazienti Recenti") patients_data = { 'ID': [101, 102, 103, 104, 105], 'Nome': ['Mario Rossi', 'Laura Bianchi', 'Giuseppe Verdi', 'Anna Neri', 'Luca Gialli'], 'Età': [54, 48, 62, 41, 57], 'Ultimo Esame': ['2023-12-01', '2023-11-28', '2023-11-25', '2023-11-20', '2023-11-18'], 'Rischio': ['Alto', 'Basso', 'Moderato', 'Basso', 'Alto'], 'Probabilità': [0.82, 0.23, 0.45, 0.19, 0.76] } df_patients = pd.DataFrame(patients_data) st.dataframe(df_patients, use_container_width=True) # Filtro per rischio risk_filter = st.selectbox( "Filtra per livello di rischio", ["Tutti", "Alto", "Moderato", "Basso"] ) if risk_filter != "Tutti": filtered_df = df_patients[df_patients['Rischio'] == risk_filter] st.write(f"Pazienti con rischio {risk_filter}: {len(filtered_df)}") with tab3: st.header("Performance Modelli AI") # Confronto modelli st.subheader("Confronto Modelli") models_data = { 'Modello': ['Random Forest', 'Neural Network', 'XGBoost', 'Logistic Regression'], 'Accuracy': [0.87, 0.85, 0.86, 0.82], 'Precision': [0.85, 0.83, 0.84, 0.80], 'Recall': [0.88, 0.86, 0.87, 0.83], 'F1-Score': [0.86, 0.84, 0.85, 0.81] } df_models = pd.DataFrame(models_data) # Metriche per modello selezionato selected_model = st.selectbox("Seleziona Modello", df_models['Modello']) model_metrics = df_models[df_models['Modello'] == selected_model].iloc[0] col1, col2, col3, col4 = st.columns(4) with col1: st.metric("Accuracy", f"{model_metrics['Accuracy']*100:.1f}%") with col2: st.metric("Precision", f"{model_metrics['Precision']*100:.1f}%") with col3: st.metric("Recall", f"{model_metrics['Recall']*100:.1f}%") with col4: st.metric("F1-Score", f"{model_metrics['F1-Score']*100:.1f}%") # Grafico a barre confronto fig, ax = plt.subplots(figsize=(10, 5)) x = np.arange(len(df_models)) width = 0.2 ax.bar(x - 1.5*width, df_models['Accuracy'], width, label='Accuracy') ax.bar(x - 0.5*width, df_models['Precision'], width, label='Precision') ax.bar(x + 0.5*width, df_models['Recall'], width, label='Recall') ax.bar(x + 1.5*width, df_models['F1-Score'], width, label='F1-Score') ax.set_xlabel('Modelli') ax.set_ylabel('Score') ax.set_title('Confronto Performance Modelli') ax.set_xticks(x) ax.set_xticklabels(df_models['Modello'], rotation=45) ax.legend() ax.grid(True, alpha=0.3) st.pyplot(fig) # Footer st.markdown("---") st.markdown("**Sistema Diagnostico Cardiaco AI** • Versione 1.0 • © 2023") """ print("✅ Codice dashboard Streamlit generato:") print("\nPer eseguire la dashboard:") print("1. Salva il codice come 'dashboard.py'") print("2. Installa Streamlit: pip install streamlit") print("3. Esegui: streamlit run dashboard.py") print("4. Accedi a: http://localhost:8501") # Salva codice dashboard with open('dashboard.py', 'w') as f: f.write(dashboard_code) print("\n💾 Codice dashboard salvato come 'dashboard.py'") return dashboard_code def close_connection(self): """Chiude connessione database""" if self.connection and self.connection.is_connected(): self.connection.close() print("🔌 Connessione database chiusa") # ESECUZIONE SISTEMA COMPLETO print("\n🚀 AVVIO SISTEMA COMPLETO DI DIAGNOSTICA AI") print("=" * 60) # Configurazione database db_config = { 'host': 'localhost', 'user': 'root', 'password': 'password', 'database': 'heart_disease_db' } # Crea sistema completo medical_system = CompleteMedicalAI(db_config) # 1. Connetti al database if medical_system.setup_database_connection(): # 2. Carica modelli addestrati if medical_system.load_trained_models(): # 3. Esegui predizione di esempio print("\n" + "=" * 80) print("DEMO: PREDIZIONE PER PAZIENTE DI ESEMPIO") print("=" * 80) # Predizione per paziente ID 1 (esempio) predictions = medical_system.predict_for_patient(1) # 4. Genera report giornaliero print("\n" + "=" * 80) print("REPORT SISTEMA COMPLETO") print("=" * 80) medical_system.generate_daily_report() # 5. Crea API endpoint print("\n" + "=" * 80) print("IMPLEMENTAZIONE API E DASHBOARD") print("=" * 80) medical_system.create_api_endpoint() medical_system.create_dashboard() # 6. Chiusura medical_system.close_connection() # Report finale print("\n" + "=" * 80) print("✅ SISTEMA COMPLETO IMPLEMENTATO CON SUCCESSO!") print("=" * 80) print(f"\n🎯 COMPONENTI IMPLEMENTATI:") print("1. ✅ Database MySQL per storage dati") print("2. ✅ Modelli ML tradizionali (Alberi, Foreste, etc.)") print("3. ✅ Reti Neurali per pattern complessi") print("4. ✅ Sistema di predizione ensemble") print("5. ✅ API Flask per integrazione esterna") print("6. ✅ Dashboard Streamlit per visualizzazione") print("7. ✅ Sistema di logging e monitoraggio") print("8. ✅ Reportistica automatica") print(f"\n🚀 PER METTERE IN PRODUZIONE:") print("1. Containerizzare con Docker") print("2. Deploy su cloud (AWS, GCP, Azure)") print("3. Implementare autenticazione sicura") print("4. Aggiungere monitoraggio avanzato") print("5. Testare con dati reali") print("6. Validazione clinica") print(f"\n💡 VALORE AGGIUNTO DEL SISTEMA:") print("• Diagnosi precoce malattie cardiache") print("• Supporto decisionale per medici") print("• Analisi dati in tempo reale") print("• Storico pazienti completo") print("• Sistema scalable e mantenibile") print(f"\n🏆 PROGETTO FINALE COMPLETATO!") print("Hai costruito un sistema AI enterprise-ready per diagnostica medica!") else: print("❌ Impossibile connettersi al database")

📋 Checklist Finale del Progetto

🏆 Valutazione e Presentazione Finale

💻 Competenze Tecniche (60%)

Qualità codice e organizzazione 15 punti
Implementazione modelli ML 15 punti
Integrazione database 10 punti
Reti neurali e ottimizzazione 10 punti
Testing e validazione 10 punti

📚 Documentazione (25%)

README e commenti codice 10 punti
Report risultati e analisi 10 punti
Diagrammi architettura 5 punti

🎤 Presentazione (15%)

Chiarezza esposizione 5 punti
Demo sistema funzionante 5 punti
Risposte a domande 5 punti
🎓
Guida alla Presentazione Finale

Struttura Presentazione (10 minuti):

  1. Introduzione (1 min): Problema clinico e obiettivi
  2. Architettura (2 min): Diagramma sistema completo
  3. Demo Sistema (3 min): Predizione live + dashboard
  4. Risultati (2 min): Metriche performance e confronto modelli
  5. Conclusione (2 min): Limiti, miglioramenti, impatto potenziale

Preparati per domande su:

  • Scelte progettuali (perché quel modello/algoritmo?)
  • Gestione dati sensibili (privacy, sicurezza)
  • Scalabilità e deployment in produzione
  • Limitazioni del sistema e come migliorarle
  • Impatto etico dell'AI in medicina

🎉 Congratulazioni!

Hai completato il corso completo di Machine Learning e AI della Classe Quinta!

🎓 Cosa hai imparato in questi 5 moduli:

Modulo 1: Fondamenti Scikit-Learn e preprocessing dati

Modulo 2: Alberi Decisionali e Foreste Casuali

Modulo 3: Reti Neurali Artificiali e Deep Learning

Modulo 4: Database MySQL e integrazione con Python

Modulo 5: Progetto finale end-to-end su dataset reale

💼 Competenze acquisite:

• Implementare modelli di classificazione e regressione

• Comprendere e costruire reti neurali

• Collegare applicazioni AI a database

• Documentare e presentare progetti complessi

• Realizzare sistemi AI completi dalla A alla Z

🚀 Prossimi Passi nella tua Carriera AI:

1. Specializzazione: Computer Vision, NLP, Reinforcement Learning

2. Framework avanzati: PyTorch, TensorFlow Extended, MLflow

3. MLOps: Deployment, monitoraggio, CI/CD per ML

4. Cloud AI: AWS SageMaker, Google AI Platform, Azure ML

5. Progetti personali: Portfolio GitHub, competizioni Kaggle

6. Formazione continua: Corsi specializzati, conferenze, ricerca

🎓 Certificato di Completamento

Hai dimostrato competenze in Machine Learning, Reti Neurali, Database Integration e Sviluppo Progetti AI Completi

CLASSE QUINTA

Machine Learning & AI

Progetto Finale Completato con Successo

Sistemi di Previsione Medica - Diagnosi Cardiopatie

Il viaggio nell'AI è appena iniziato. Continua a esplorare, imparare e creare! 🚀

🏠 Torna alla Home del Corso