From 23395b0335ec836a652034d97aae51cda86deea0 Mon Sep 17 00:00:00 2001 From: "thibault.capt" <thibault.capt@etu.hesge.ch> Date: Thu, 28 Sep 2023 10:19:18 +0200 Subject: [PATCH] update --- main.py | 92 +++++++++++++++++++++++++++++++++------------------------ 1 file changed, 53 insertions(+), 39 deletions(-) diff --git a/main.py b/main.py index e421229..7c39f34 100644 --- a/main.py +++ b/main.py @@ -3,60 +3,50 @@ import numpy as np import matplotlib.pyplot as plt -def import_csv(filename: str, h: int = None) -> pd.DataFrame: - """ - Imports a CSV file and returns a pandas DataFrame. +def import_csv(filename: str): + return pd.read_csv(filename, header=None) - Args: - filename (str): The path to the CSV file. - h (int or list of int, default 0): The row(s) to use as the column names. - Returns: - pandas.DataFrame: The imported data as a DataFrame. - """ - return pd.read_csv(filename, header=h) +def manhattan_distance(x1, x2): + return np.sum(np.abs(x1 - x2)) -def euclidian_distance(x1, x2): - return np.sqrt(np.sum((x1 - x2) ** 2)) +def assign_clusters(X, centroids): + distances = np.array([[manhattan_distance(x, centroid) for centroid in centroids] for x in X]) + return np.argmin(distances, axis=1) -if __name__ == "__main__": - df = import_csv("Data/iris.csv") - # Sélectionner les caractéristiques (colonnes) que vous voulez utiliser pour le clustering - X = df.iloc[:, :-1].values # Sélectionner toutes les colonnes sauf la dernière (caratéristique) - k = 3 # Nombre de clusters - - # Initialisation des k-centroïdes de manière aleatoire +def k_means(X, k, max_iterations=100): + # Initialisation des k-centroïdes de manière aléatoire np.random.seed(0) centroids = X[np.random.choice(X.shape[0], k, replace=False)] - # Initialisation des variables pour stocker les anciens et nouveaux centroïdes old_centroids = np.zeros(centroids.shape) new_centroids = centroids.copy() - # Initialisation d'une liste pour stocker la somme des distances au sein de chaque cluster à chaque itération - distances = [] + distances_history = [] # Pour stocker la somme des distances à chaque itération iteration = 0 - while not np.array_equal(old_centroids, new_centroids): + while not np.array_equal(old_centroids, new_centroids) and iteration < max_iterations: iteration += 1 - distances_to_centroids = np.array([[euclidian_distance(x, centroid) for centroid in new_centroids] for x in X]) - # Attribution des points aux centroïdes les plus proches - labels = np.argmin(distances_to_centroids, axis=1) + labels = assign_clusters(X, new_centroids) + + old_centroids = new_centroids.copy() - # Calcul des nouveaux centroïdes comme la moyenne des points de chaque cluster for i in range(k): new_centroids[i] = np.mean(X[labels == i], axis=0) - # Calcul des distances au sein de chaque cluster - cluster_distances = [np.sum([euclidian_distance(X[j], new_centroids[i]) - for j in range(len(X)) if labels[j] == i]) for i in range(k)] - total_distance = np.sum(cluster_distances) - distances.append(total_distance) + # Calcul de la somme des distances au sein de chaque cluster (fonction objectif) + total_distance = 0 + for i in range(k): + cluster_points = X[labels == i] + cluster_distance = np.sum([manhattan_distance(point, new_centroids[i]) for point in cluster_points]) + total_distance += cluster_distance - # Affichage des clusters à cette iteration + distances_history.append(total_distance) + + # Affichage des clusters à cette itération plt.figure(figsize=(8, 6)) for i in range(k): cluster_points = X[labels == i] @@ -68,12 +58,36 @@ if __name__ == "__main__": plt.title(f"Iteration {iteration}") plt.show() - # Mettre à jour les anciens et les nouveaux centroïdes - old_centroids = new_centroids.copy() - + # Tracer la somme des distances à chaque itération plt.figure(figsize=(8, 6)) - plt.plot(range(1, iteration + 1), distances, marker='o') + plt.plot(range(1, iteration + 1), distances_history, marker='o') plt.xlabel("Iteration") - plt.ylabel("Somme des distances au carré") - plt.title("Evolution de la somme des distances au carré") + plt.ylabel("Somme des distances") + plt.title("Evolution de la somme des distances") plt.show() + + return labels, new_centroids + + +if __name__ == "__main__": + # Initialiser k-centroides + # attribuer les points aux centroïde le plus proche (Manhattan / L2) + # Tant que les centroïdes bougent : + # Pour chaque cluster, calculer le point central du cluster (moyenne des coordonnées) + # noter si ancien centroïde ~= nouveau centroïde + # attribution des points aux nouveaux centroïdes + # calcul de la somme des distances au sein d'un cluster + # fonction objectif à minimiser + # plot la somme de la somme des distances à chaque itération + # afficher les nouveaux cluster à chaque itérations + + # Charger les données depuis le fichier CSV + df = import_csv("Data/iris.csv") + X = df.iloc[:, :-1].values + + k = 3 + + labels, centroids = k_means(X, k) + + print("Nouveaux centroïdes finaux:") + print(centroids) -- GitLab