# =================================================================== # Jean-Michel Richer 2026 # =================================================================== import sys import os # Désactive les avertissements d'information généraux de TensorFlow # repasser cette valeur à '0' pour les erreurs os.environ['TF_CPP_MIN_LOG_LEVEL'] = '3' # Désactive spécifiquement le message d'avertissement de oneDNN os.environ['TF_ENABLE_ONEDNN_OPTS'] = '0' # ================================================================= # packages python # ================================================================= import pandas as pd # pour les données import numpy as np # pour les données import matplotlib.pyplot as plt # pour les graphiques import seaborn as sns # pour les graphiques import sklearn.model_selection as skms import sklearn.preprocessing as skpre # for StandardScaler import sklearn.svm as sksvm # for SVM (Support Vector Machine) import sklearn.metrics as skmet # for accuracy_score, classification_report import sklearn.decomposition as skdec # for PCA (Principal Components Analysis) import tensorflow.keras as tf # palette de couleurs (sans / avec diabète) pal = ['green', 'red'] """ ================================================================= Fonction qui affiche un titre ================================================================= """ def titre(s : str): print("\n"*3) print("="*50) print(f"{s.upper():^50}") print("="*50) """ ================================================================= Chargement du jeu de données relatif aux indiens pimas Affichage de statistiques concernant les colonnes de données ================================================================= """ def chargement(): titre("chargement des données") url = "https://raw.githubusercontent.com/jbrownlee/Datasets/master/pima-indians-diabetes.data.csv" df = pd.read_csv(url, names = ['grossesses', 'glucose', 'pression', 'epaisseur', 'insuline', 'IMC', 'fonction', 'age', 'diabete']) print(df.head()) print(df.describe()) diabete = df['diabete'].value_counts() print(f"- patientes sans diabète (0) : {diabete[0]}") print(f"- patientes avec diabète (1) : {diabete[1]}") print(f"-----------------------------------------") print(f"- total : {diabete.sum()}") return df """ ================================================================= Prétraitement des données - les colonnes contenant des 0 (absence de donnée) sont remplacées par la médiane ================================================================= """ def pretraitement(df, equalize): titre("prétaitrement") if equalize: print("- garde le même nombre de patientes avec et sans diabete") df_avec_diabete = df[df['diabete'] == 1] df_sans_diabete = df[df['diabete'] == 0] size = df_avec_diabete['diabete'].size print(f"size={size}") df_echantillon = df_sans_diabete.sample(n = size, random_state=42) df_equilibre = pd.concat([df_avec_diabete, df_echantillon]) df = df_equilibre.sample(frac=1, random_state=42).reset_index(drop=True) median = df.median() colonnes_avec_zeros = ['glucose', 'pression', 'epaisseur', 'insuline', 'IMC'] df[colonnes_avec_zeros] = df[colonnes_avec_zeros].replace(0, np.nan) df.fillna(df.median(), inplace=True) print(df[:5]) return df """ ================================================================= Affichage de graphiques 1- répartition du diabète 2- matrice de corrélation 3- diabète en fonction de l'âge et du taux de glucose 4- pairplot ================================================================= """ def plots(df): global pal titre("génération des graphiques") # répartition du diabète plt.figure(figsize = (5,5)) sns.countplot(x = 'diabete', data = df, hue = 'diabete', palette = pal, legend = False) plt.title("Répartition du diabète (0 = Non, 1 = Oui)") plt.savefig("repartition_diabete.png") plt.show() # matrice de corrélation plt.figure(figsize = (10,10)) correlation = df.corr() sns.heatmap(correlation, cmap = 'flare', annot = True, fmt = ".2f") plt.title('Matrice de corrélation') plt.savefig("matrice_de_correlation.png") plt.show() # diabète en fn du glucose et de l'âge plt.figure(figsize = (10,10)) sns.scatterplot(x = 'age', y = 'glucose', hue='diabete', data = df, palette = pal) plt.title("Diabète suivant âge et glucose") plt.savefig("diabete_age_glucose.png") plt.show() # pairplot en fonction des colonnes d'intérêt colonnes_interessantes = ['age', 'fonction', 'glucose', 'IMC', 'diabete'] df_interet = df[colonnes_interessantes] sns.pairplot(df_interet, hue = 'diabete', palette = pal) plt.title("Analyse croisée des variables d'intérêt") plt.savefig("pair_plot.png") plt.show() """ ================================================================= Séparation et normalisation - séparation des données en lot d'entraînement (80%) et lot de test (20%) - normalisation avec un StandardScaler pour empêcher l'influence des grandes valeurs ================================================================= """ def separation_normalisation(df): titre("séparation et normalisation") # données en entrée tout sauf la colonne 'diabete' X = df.drop('diabete', axis = 1) # données en sortie : la colonne 'diabete' y = df['diabete'] X_train, X_tests, y_train, y_tests = skms.train_test_split(X, y, test_size=0.2, random_state = 23, stratify = y) scaler = skpre.StandardScaler() X_train_scaled = scaler.fit_transform(X_train) X_tests_scaled = scaler.fit_transform(X_tests) print("\n- données initiales (5 premières lignes)") print("-"*60) print(X_train[:5]) print("\n- données normalisées (5 premières lignes)") print("-"*60) print(X_train_scaled[:5]) return X_train_scaled, X_tests_scaled, y_train, y_tests """ ================================================================= Prédiction avec Support Vector Machine - création de la SVM - apprentissage de la SVM - analyse du résultat (rapport de classification) - généère un graphique comparatif ================================================================= """ def prediction_svm(df, X_train, X_tests, y_train, y_tests): global pal titre("prédiction avec SVM") # création du prédicteur, entraînement et prédiction model = sksvm.SVC(kernel = 'rbf', C = 1.0, gamma = 'scale', class_weight='balanced') # apprentissage model.fit(X_train, y_train) # prédiction avec le classifier y_predict = model.predict(X_tests) # taux de prédiction model_accuracy = skmet.accuracy_score(y_tests, y_predict) # rapport d'analyse print(f"- précision de la SVM = {model_accuracy:.2f}") print("- rapport de classification") print(skmet.classification_report(y_tests, y_predict)) # graphique comparatif pca = skdec.PCA(n_components = 2) print(pca) X_test_2d = pca.fit_transform(X_tests) plt.figure(figsize=(14, 6)) # on positionne deux graphiques sur la même figure # celui de gauche correspond à la réalité # celui de droite correspond à la prédiction plt.subplot(1,2,1) sns.scatterplot(x = X_test_2d[:,0], y = X_test_2d[:,1], hue = y_tests, palette = pal) plt.title("Réalité") plt.xlabel("composante principale 1") plt.ylabel("composante principale 2") plt.legend(title='Diabète réel') plt.subplot(1,2,2) sns.scatterplot(x = X_test_2d[:,0], y = X_test_2d[:,1], hue = y_predict, palette = pal) plt.title("Prédiction") plt.xlabel("composante principale 1") plt.ylabel("composante principale 2") plt.legend(title='Diabète prédit') # affichage des graphiques plt.tight_layout() plt.savefig("svm.png") plt.show() """ ================================================================= Prédiction avec Réseau de Neurones - création du réseau - entraînement du réseau - analyse du résultat (rapport de classification) - génère un graphique comparatif ================================================================= """ def prediction_rn(df, X_train, X_tests, y_train, y_tests): global pal # palette titre("réseau de neurones") # création du réseau model = tf.Sequential([ tf.layers.Input(shape=(8,)), tf.layers.Dense(12, activation = 'relu'), tf.layers.Dense(8, activation = 'relu'), tf.layers.Dense(1, activation='sigmoid') ]) model.compile(optimizer = 'adam', loss = 'binary_crossentropy', metrics=['accuracy']) # apprentissage du réseau print("- apprentissage, soyez patient") history = model.fit(X_train, y_train, epochs = 150, batch_size=32, verbose=0) # évaluation de la prédiction loss, accuracy = model.evaluate(X_tests, y_tests, verbose=0) print(f"- précision du réseau = {accuracy:.2f}") print(f"- perte = {loss:.2f}") print("- rapport de classification") y_predict_probabilite = model.predict(X_tests) y_predict = (y_predict_probabilite > 0.5).astype(int) y_predict = y_predict.flatten() print(skmet.classification_report(y_tests, y_predict)) # sauvegarde des paramètres du réseau de neurones nom_fichier_keras = f"rn_model_{accuracy*100:.4f}.keras" model.save(nom_fichier_keras) # graphique comparatif pca = skdec.PCA(n_components = 2) print(pca) X_test_2d = pca.fit_transform(X_tests) plt.figure(figsize=(14, 6)) # on positionne deux graphiques sur la même figure # celui de gauche correspond à la réalité # celui de droite correspond à la prédiction plt.subplot(1,2,1) sns.scatterplot(x = X_test_2d[:,0], y = X_test_2d[:,1], hue = y_tests, palette = pal) plt.title("Réalité") plt.xlabel("composante principale 1") plt.ylabel("composante principale 2") plt.legend(title='Diabète réel') plt.subplot(1,2,2) sns.scatterplot(x = X_test_2d[:,0], y = X_test_2d[:,1], hue = y_predict, palette = pal) plt.title("Prédiction") plt.xlabel("composante principale 1") plt.ylabel("composante principale 2") plt.legend(title='Diabète prédit') # affichage des graphiques plt.tight_layout() plt.savefig("rn.png") plt.show() """ ================================================================= Fonction principale - le programme accepte un éventuel paramètre "equalize" qui permet d'avoir un rapport 50/50 entre patientes avec ou sans diabète ================================================================= """ def main(): equalize = False if len(sys.argv) > 1: if sys.argv[1] == "equalize": equalize = True pimas = chargement() pimas = pretraitement(pimas, equalize) plots(pimas) X_train_scaled, X_tests_scaled, y_train, y_tests = separation_normalisation(pimas) prediction_svm(pimas, X_train_scaled, X_tests_scaled, y_train, y_tests) prediction_rn(pimas, X_train_scaled, X_tests_scaled, y_train, y_tests) if __name__ == "__main__": main()