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