diff --git a/TP05/tp05.py b/TP05/tp05.py deleted file mode 100644 index b3beed4..0000000 --- a/TP05/tp05.py +++ /dev/null @@ -1,390 +0,0 @@ -""" -Projet de Machine Learning : Prédiction de Maladies Cardiaques (Version corrigée) -Dataset : UCI Heart Disease Dataset -Objectif : Comparer deux architectures de réseaux de neurones pour la prédiction de maladies cardiaques -""" - -import pandas as pd -import numpy as np -import urllib.request -import ssl -from sklearn.model_selection import train_test_split -from sklearn.preprocessing import StandardScaler -from tensorflow.keras.models import Sequential -from tensorflow.keras.layers import Dense, Dropout, BatchNormalization -from tensorflow.keras.optimizers import Adam -from tensorflow.keras.callbacks import EarlyStopping -import matplotlib.pyplot as plt - -# 1. Chargement des données avec gestion du SSL -def load_data(): - try: - # Créer un contexte SSL non-vérifié (à utiliser avec précaution) - ssl._create_default_https_context = ssl._create_unverified_context - - # URL du dataset - url = "https://archive.ics.uci.edu/ml/machine-learning-databases/heart-disease/processed.cleveland.data" - - # Définir les noms des colonnes - columns = ['age', 'sex', 'cp', 'trestbps', 'chol', 'fbs', 'restecg', 'thalach', - 'exang', 'oldpeak', 'slope', 'ca', 'thal', 'target'] - - print("Téléchargement des données...") - - # Télécharger directement dans un DataFrame - data = pd.read_csv(url, names=columns) - - # En cas d'erreur, utiliser un dataset de démonstration - if data.empty: - raise Exception("Le dataset est vide") - - except Exception as e: - print(f"Erreur lors du téléchargement des données: {e}") - print("Utilisation d'un dataset de démonstration...") - - # Créer un petit dataset de démonstration - np.random.seed(42) - n_samples = 300 - - data = pd.DataFrame({ - 'age': np.random.normal(55, 10, n_samples), - 'sex': np.random.binomial(1, 0.5, n_samples), - 'cp': np.random.randint(0, 4, n_samples), - 'trestbps': np.random.normal(130, 20, n_samples), - 'chol': np.random.normal(240, 40, n_samples), - 'fbs': np.random.binomial(1, 0.2, n_samples), - 'restecg': np.random.randint(0, 3, n_samples), - 'thalach': np.random.normal(150, 20, n_samples), - 'exang': np.random.binomial(1, 0.3, n_samples), - 'oldpeak': np.random.normal(1, 1, n_samples), - 'slope': np.random.randint(0, 3, n_samples), - 'ca': np.random.randint(0, 4, n_samples), - 'thal': np.random.randint(0, 3, n_samples), - 'target': np.random.binomial(1, 0.4, n_samples) - }) - - # Nettoyer les données - data = data.replace('?', np.nan) - data = data.dropna() - - # Convertir les colonnes en nombres - for column in data.columns: - data[column] = pd.to_numeric(data[column]) - - # Binariser la target (0 pour pas de maladie, 1 pour maladie) - data['target'] = (data['target'] > 0).astype(int) - - return data - -# 2. Prétraitement des données -def preprocess_data(data): - # Séparer features et target - X = data.drop('target', axis=1) - y = data['target'] - - # Split train/test - X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42) - - # Standardisation - scaler = StandardScaler() - X_train_scaled = scaler.fit_transform(X_train) - X_test_scaled = scaler.transform(X_test) - - return X_train_scaled, X_test_scaled, y_train, y_test - -# 3. Premier modèle : Réseau dense classique -def create_model_1(input_shape): - model = Sequential([ - Dense(64, activation='relu', input_shape=input_shape), - BatchNormalization(), - Dense(32, activation='relu'), - Dropout(0.3), - Dense(16, activation='relu'), - Dense(1, activation='sigmoid') - ]) - - model.compile(optimizer=Adam(learning_rate=0.001), - loss='binary_crossentropy', - metrics=['accuracy']) - - return model - -# 4. Second modèle : Réseau plus profond avec régularisation plus forte -def create_model_2(input_shape): - model = Sequential([ - Dense(128, activation='relu', input_shape=input_shape), - BatchNormalization(), - Dropout(0.3), - Dense(64, activation='relu'), - BatchNormalization(), - Dropout(0.3), - Dense(32, activation='relu'), - BatchNormalization(), - Dense(16, activation='relu'), - Dense(1, activation='sigmoid') - ]) - - model.compile(optimizer=Adam(learning_rate=0.001), - loss='binary_crossentropy', - metrics=['accuracy']) - - return model - -# 5. Fonction d'entraînement et d'évaluation -def train_and_evaluate(model, X_train, X_test, y_train, y_test, model_name): - # Early stopping pour éviter le surapprentissage - early_stopping = EarlyStopping( - monitor='val_loss', - patience=10, - restore_best_weights=True, - verbose=1 - ) - - # Entraînement - history = model.fit( - X_train, y_train, - validation_split=0.2, - epochs=50, # Réduit pour la démonstration - batch_size=32, - callbacks=[early_stopping], - verbose=1 - ) - - # Évaluation - test_loss, test_accuracy = model.evaluate(X_test, y_test, verbose=0) - print(f"\n{model_name} - Test Accuracy: {test_accuracy:.4f}") - - return history - -# 6. Visualisation des résultats -def plot_training_history(history1, history2): - plt.figure(figsize=(12, 4)) - - # Plot accuracy - plt.subplot(1, 2, 1) - plt.plot(history1.history['accuracy'], label='Model 1 accuracy') - plt.plot(history1.history['val_accuracy'], label='Model 1 val accuracy') - plt.plot(history2.history['accuracy'], label='Model 2 accuracy') - plt.plot(history2.history['val_accuracy'], label='Model 2 val accuracy') - plt.title('Model Accuracy') - plt.xlabel('Epoch') - plt.ylabel('Accuracy') - plt.legend() - - # Plot loss - plt.subplot(1, 2, 2) - plt.plot(history1.history['loss'], label='Model 1 loss') - plt.plot(history1.history['val_loss'], label='Model 1 val loss') - plt.plot(history2.history['loss'], label='Model 2 loss') - plt.plot(history2.history['val_loss'], label='Model 2 val loss') - plt.title('Model Loss') - plt.xlabel('Epoch') - plt.ylabel('Loss') - plt.legend() - - plt.tight_layout() - plt.show() - -# 7. Programme principal -def main(): - print("Loading data...") - data = load_data() - print("Data shape:", data.shape) - - print("\nPreprocessing data...") - X_train, X_test, y_train, y_test = preprocess_data(data) - input_shape = (X_train.shape[1],) - - print("\nTraining Model 1...") - model1 = create_model_1(input_shape) - history1 = train_and_evaluate(model1, X_train, X_test, y_train, y_test, "Model 1") - - print("\nTraining Model 2...") - model2 = create_model_2(input_shape) - history2 = train_and_evaluate(model2, X_train, X_test, y_train, y_test, "Model 2") - - print("\nPlotting results...") - plot_training_history(history1, history2) - -if __name__ == "__main__": - main() - - - -''' -Modèle 1 : Réseau Dense Classique -- C'est une architecture relativement simple et légère avec 4 couches : -1. Première couche : 64 neurones avec activation ReLU - - Cette couche initiale capture les patterns de base dans les données - - Suivie d'une normalisation par lots (BatchNormalization) pour stabiliser l'apprentissage -2. Deuxième couche : 32 neurones avec activation ReLU - - Suivie d'un Dropout de 30% pour éviter le surapprentissage -3. Troisième couche : 16 neurones avec activation ReLU - - Réduit progressivement la dimensionnalité -4. Couche de sortie : 1 neurone avec activation sigmoid - - Pour la prédiction binaire (malade/non malade) - -Modèle 2 : Réseau Plus Profond -- C'est une architecture plus complexe avec 5 couches et plus de régularisation : -1. Première couche : 128 neurones avec activation ReLU - - Commence avec plus de neurones pour capturer des patterns plus complexes - - Suivie de BatchNormalization et Dropout 30% -2. Deuxième couche : 64 neurones avec activation ReLU - - Également suivie de BatchNormalization et Dropout -3. Troisième couche : 32 neurones avec activation ReLU - - Avec BatchNormalization -4. Quatrième couche : 16 neurones avec activation ReLU -5. Couche de sortie : 1 neurone avec activation sigmoid - -Les principales différences sont : -1. Complexité : Le modèle 2 a plus de paramètres et de couches -2. Régularisation : Le modèle 2 utilise plus de BatchNormalization et de Dropout -3. Capacité d'apprentissage : Le modèle 2 peut capturer des relations plus complexes dans les données - -L'idée est de comparer : -- Une approche simple qui pourrait suffire pour ce problème médical relativement simple -- Une approche plus complexe qui pourrait potentiellement capturer des patterns plus subtils - -Les deux modèles utilisent le même optimiseur (Adam) avec le même learning rate (0.001) pour une comparaison équitable. - -Cette configuration permet d'observer si la complexité supplémentaire du deuxième modèle apporte réellement un avantage en termes de performances, ou si le modèle plus simple est suffisant. - -- ReLU (Rectified Linear Unit) est une fonction d'activation très populaire en deep learning : ReLu (x) = max (0,x) - -- Le Dropout est une technique de régularisation cruciale en deep learning. Voici une explication détaillée : -Principe de base : -Pendant l'entraînement, à chaque itération -Désactive aléatoirement un certain pourcentage de neurones -Ces neurones sont temporairement "éteints" avec toutes leurs connexions -Le pourcentage est défini par le paramètre de dropout (ex: 0.3 = 30% des neurones) - -- La BatchNormalization (ou normalisation par lots) est une technique très importante en deep learning. Voici une explication détaillée : -Principe fondamental : -Normalise les activations d'une couche pour chaque batch -Maintient la moyenne proche de 0 et l'écart-type proche de 1 -S'applique avant la fonction d'activation -''' - -''' -## Exercice 1 : -adapter le programme sur les données suivantes : -https://archive.ics.uci.edu/ml/machine-learning-databases/breast-cancer-wisconsin/wdbc.data - - -## Exercice 2 : -On vous demande d'implémenter 2 autres modèles en suivant le schéma du programme donné. Sur les 2 data-set. - -L'objectif est de rendre un rapport explicatif complet sur au moins un des modèles ; le code doit être commenté et des tests (changement de paramètres : itération, taux, couches réseaux) doivent être fait. - -### Premier Modèle : Random Forest Classifier - -Ce modèle est particulièrement intéressant car il offre : -- Une excellente performance sur les données médicales -- Une interprétabilité des résultats -- Une facilité relative d'implémentation - -Voici un exemple de structure pour l'implémentation : - -```python -from sklearn.ensemble import RandomForestClassifier -from sklearn.model_selection import GridSearchCV - -def create_model_rf(X_train, y_train): - # Création du modèle avec des hyperparamètres de base - rf_model = RandomForestClassifier( - n_estimators=100, - max_depth=10, - random_state=42 - ) - - # Définition des paramètres à optimiser - param_grid = { - 'n_estimators': [50, 100, 200], - 'max_depth': [5, 10, 15], - 'min_samples_split': [2, 5, 10] - } - - # Recherche des meilleurs paramètres - grid_search = GridSearchCV( - rf_model, - param_grid, - cv=5, - scoring='accuracy', - n_jobs=-1 - ) - - # Entraînement avec recherche des meilleurs paramètres - grid_search.fit(X_train, y_train) - - return grid_search.best_estimator_ -``` - -### Deuxième Modèle : XGBoost - -XGBoost est un algorithme de boosting très performant qui permet souvent d'obtenir d'excellents résultats. Voici une structure d'implémentation : - -```python -import xgboost as xgb -from sklearn.model_selection import cross_val_score - -def create_model_xgb(X_train, y_train): - # Création du modèle avec des paramètres de base - xgb_model = xgb.XGBClassifier( - learning_rate=0.1, - n_estimators=100, - max_depth=5, - random_state=42 - ) - - # Paramètres à optimiser - param_grid = { - 'learning_rate': [0.01, 0.1, 0.3], - 'n_estimators': [50, 100, 200], - 'max_depth': [3, 5, 7] - } - - # Optimisation des hyperparamètres - grid_search = GridSearchCV( - xgb_model, - param_grid, - cv=5, - scoring='accuracy', - n_jobs=-1 - ) - - grid_search.fit(X_train, y_train) - - return grid_search.best_estimator_ -``` - -Pour faciliter l'implémentation, voici les points essentiels à comprendre : - -Pour le Random Forest : -- C'est un ensemble d'arbres de décision -- Chaque arbre est entraîné sur un sous-ensemble aléatoire des données -- La prédiction finale est obtenue par vote majoritaire des arbres -- Les paramètres clés sont le nombre d'arbres (n_estimators) et la profondeur maximale (max_depth) - -Pour XGBoost : -- C'est un algorithme de boosting qui construit les arbres séquentiellement -- Chaque nouvel arbre corrige les erreurs des arbres précédents -- Le learning_rate contrôle la contribution de chaque arbre -- La profondeur des arbres (max_depth) limite la complexité du modèle - -Pour l'évaluation des modèles, on peut réutiliser les fonctions de visualisation existantes en les adaptant légèrement. Par exemple : - -```python -def plot_model_comparison(models_results): - plt.figure(figsize=(10, 6)) - - for model_name, scores in models_results.items(): - plt.plot(scores['val_accuracy'], label=f'{model_name} validation accuracy') - - plt.title('Model Comparison') - plt.xlabel('Iteration') - plt.ylabel('Accuracy') - plt.legend() - plt.show() -``` - -''' \ No newline at end of file