Skip to content
Snippets Groups Projects
Commit d8a6187a authored by thibault.capt's avatar thibault.capt
Browse files

update

parent e50c7a0f
No related branches found
No related tags found
No related merge requests found
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Black">
<option name="sdkName" value="Python 3.9 (tp-clustering)" />
</component>
<component name="MarkdownSettingsMigration">
<option name="stateVersion" value="1" />
</component>
......
# Importation des bibliothèques
from typing import Tuple, List
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
def import_csv(filename: str, h: int or None) -> pd.DataFrame:
"""
Importe un fichier CSV et retourne un DataFrame pandas.
Args:
filename (str): Le chemin du fichier CSV.
h (int or None, optional): L'entête du fichier CSV.
Returns:
pandas.DataFrame: Les données importées sous forme de DataFrame.
"""
return pd.read_csv(filename, header=h)
def manhattan_distance(x1: np.ndarray, x2: np.ndarray) -> float:
"""
Calcule la distance de Manhattan (L2) entre deux vecteurs.
Args:
x1 (numpy.ndarray): Le premier vecteur.
x2 (numpy.ndarray): Le deuxième vecteur.
Returns:
float: La distance de Manhattan entre x1 et x2.
"""
squared_diff = (x1 - x2) ** 2 # Carré des différences
l2_manhattan = np.sqrt(np.sum(squared_diff)) # Racine carrée de la somme des carrés
return l2_manhattan
def assign_clusters(X: np.ndarray, centroids: np.ndarray) -> np.ndarray:
"""
Attribue chaque point de données à son cluster le plus proche en utilisant la distance de Manhattan.
Args:
X (numpy.ndarray): Les données.
centroids (numpy.ndarray): Les centroïdes des clusters.
Returns:
numpy.ndarray: Les étiquettes de cluster attribuées à chaque point de données.
"""
distances = np.array([[manhattan_distance(x, centroid) for centroid in centroids] for x in X])
return np.argmin(distances, axis=1)
def k_means(X: np.ndarray, k: int, max_iterations: int = 100) -> Tuple[np.ndarray, np.ndarray]:
"""
Implémente l'algorithme K-Means pour regrouper les données en k clusters.
Args:
X (numpy.ndarray): Les données à regrouper.
k (int): Le nombre de clusters à former.
max_iterations (int, optional): Le nombre maximal d'itérations. Défaut à 100.
distance = 0
if x1.shape == x2.shape:
for i in range(x1.size):
distance += np.abs(x1[i] - x2[i])
return distance
Returns:
tuple: Une paire contenant les étiquettes de cluster et les centroïdes finaux.
"""
# 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)] # séléctionne k points aléatoirement dans la liste X
old_centroids = np.zeros(centroids.shape)
new_centroids = centroids.copy()
distances_history = [] # Pour stocker la somme des distances
iteration = 0
# pour vérifier que les centroides ne changent plus , il faut check que l'ancien et le nouveau soient pareils , on ajoute tout de même un nombre d'itérations max pour ne pas tourner à l'infini
while not np.array_equal(old_centroids, new_centroids) and iteration < max_iterations:
iteration += 1
labels = assign_clusters(X, new_centroids)
old_centroids = new_centroids.copy()
for i in range(k):
new_centroids[i] = np.mean(X[labels == i], axis=0)
# 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
if __name__ == '__main__':
dataset = pd.read_csv("Data/student-data-test.csv", header=0)
X = dataset.iloc[:, 1:].values
k = 3
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]
plt.scatter(cluster_points[:, 0], cluster_points[:, 1], label=f"Cluster {i + 1}")
plt.scatter(new_centroids[:, 0], new_centroids[:, 1], marker="X", color="black", label="Centroids")
plt.xlabel("Caractéristique 1")
plt.ylabel("Caractéristique 2")
# Initialisation des k-centroides de manière aléatoire
centroids = X[np.random.choice(X.shape[0], k, replace=False)]
max_iter = 100
# Algorithme K-Means
for i in range(max_iter):
# Créer des clusters vides
clusters = [[] for _ in range(k)]
# Sauvegarder les anciens centroïdes
for point in X:
distances = [manhattan_distance(point, centroid) for centroid in centroids]
cluster_index = np.argmin(distances)
clusters[cluster_index].append(point)
# Sauvegarder les anciens centroïdes
old_centroids = centroids.copy()
# Mettre à jour les centroïdes en calculant la moyenne des points dans chaque cluster
for j in range(k):
if len(clusters[j]) > 0:
centroids[j] = np.mean(clusters[j], axis=0)
# Afficher les centroides finaux et les clusters
for iteration, centroid in enumerate(centroids):
cluster_points = np.array(clusters[iteration])
plt.scatter(cluster_points[:, 0], cluster_points[:, 1], label=f"Cluster {iteration}")
plt.scatter(centroid[0], centroid[1], marker="x", s=200, c="red", label=f"Centroïde {iteration + 1}")
plt.xlabel("Grade 1")
plt.ylabel("Grade 2")
plt.title(f"Clustering K-Means {i}")
plt.legend()
plt.title(f"Iteration {iteration}")
plt.show()
# Tracer la somme des distances à chaque itération
plt.figure(figsize=(8, 6))
plt.plot(range(1, iteration + 1), distances_history, marker='o')
plt.xlabel("Iteration")
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", h=None)
X = df.iloc[:, :-1].values
k = 3
labels, centroids = k_means(X, k)
print("Nouveaux centroïdes finaux:")
print(centroids)
# Convergence ?
if np.all(old_centroids == centroids):
break
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment