From 59c5897fbf7378b0a8440d4ce27f5c7040c0b27c Mon Sep 17 00:00:00 2001 From: leroso Date: Sat, 15 Nov 2025 12:57:44 +0100 Subject: [PATCH 1/8] Final Assignement --- numpy_questions.py | 44 +++++++++++++++++++----- sklearn_questions.py | 80 +++++++++++++++++++++++++++++++++++++------- 2 files changed, 103 insertions(+), 21 deletions(-) diff --git a/numpy_questions.py b/numpy_questions.py index 21fcec4b..65e7f6fe 100644 --- a/numpy_questions.py +++ b/numpy_questions.py @@ -18,7 +18,7 @@ import numpy as np -def max_index(X): +def max_index(X: np.ndarray) -> tuple: """Return the index of the maximum in a numpy array. Parameters @@ -37,12 +37,22 @@ def max_index(X): If the input is not a numpy array or if the shape is not 2D. """ - i = 0 - j = 0 + # 1. Contrôle du type d'entrée (Doit être un np.ndarray) + if not isinstance(X, np.ndarray): + raise ValueError(f"L'entrée doit être un np.ndarray, mais le type {type(X)} a été reçu.") + + # 2. Contrôle des dimensions (Doit être 2D) + if X.ndim != 2: + raise ValueError(f"Le tableau doit être 2D pour cette fonction (il a {X.ndim} dimensions).") + # 3. Recherche de l'indice du maximum + for i in range(X.shape[0]): + for j in range(X.shape[1]): + if X[i, j] == np.max(X): + return (i, j) + # La fonction retourne la première occurrence du maximum en parcourant les lignes puis les colonnnes. + - # TODO - return i, j def wallis_product(n_terms): @@ -62,6 +72,24 @@ def wallis_product(n_terms): pi : float The approximation of order `n_terms` of pi using the Wallis product. """ - # XXX : The n_terms is an int that corresponds to the number of - # terms in the product. For example 10000. - return 0. + if not isinstance(n_terms, int): + raise ValueError(f"Le paramètre doit être un entier, (il est du type {type(n_terms)}).") + if n_terms < 1: + return 0.0 + + product = 1.0 + + # Itère de k=1 à n_terms (inclus) + for k in range(1, n_terms + 1): + # Calcule le numérateur (2k) et les dénominateurs (2k-1, 2k+1) + # On utilise des flottants (2.0 * k) pour garantir une division flottante + numerator = 2.0 * k + denominator1 = numerator - 1.0 + denominator2 = numerator + 1.0 + + # Le terme d'ordre k est (2k / (2k - 1)) * (2k / (2k + 1)) + term = (numerator / denominator1) * (numerator / denominator2) + + product *= term + + return product * 2.0 # Le produit final est multiplié par 2 pour obtenir l'approximation de pi vu que l'intégrale donne pi/2. \ No newline at end of file diff --git a/sklearn_questions.py b/sklearn_questions.py index f65038c6..3a430e15 100644 --- a/sklearn_questions.py +++ b/sklearn_questions.py @@ -35,23 +35,53 @@ def __init__(self): # noqa: D107 pass def fit(self, X, y): - """Write docstring. - - And describe parameters + """Le but du fit est juste de stocker les données d'entraînement. + + Parameters + ---------- + X : array, shape (n_samples, n_features) + Les échantillons d'entraînement. + y : array, shape (n_samples,) + Les étiquettes cibles des échantillons d'entraînement. + + Returns + ------- + self : object + L'estimateur entraîné (c'est à dire contenant les données + d'entraînement). """ X, y = check_X_y(X, y) check_classification_targets(y) self.classes_ = np.unique(y) self.n_features_in_ = X.shape[1] - # XXX fix + # Rajout des données d'entraînement dans l'estimateur + self.X_train_ = X + self.y_train_ = y + + # Marquer l'estimateur comme "entraîné" + self.is_fitted_ = True + return self def predict(self, X): - """Write docstring. - - And describe parameters """ + Le but de la méthode predict est de prédire les étiquettes pour les + échantillons de test X en utilisant les données d'entraînement qui + ont précédemment été stockées dans l'estimateur lors de l'appel à fit. + + Parameters + ---------- + X : array-like, shape (n_samples, n_features) + Les échantillons de test pour lesquels prédire les étiquettes. + + Returns + ------- + y_pred : ndarray, shape (n_samples,) + Les étiquettes de classe prédites pour chaque échantillon de test. + """ + + # Vérification que l'estimateur a bien été entraîné check_is_fitted(self) X = check_array(X) y_pred = np.full( @@ -59,16 +89,40 @@ def predict(self, X): dtype=self.classes_.dtype ) - # XXX fix + # Itération sur chaque échantillon de test + for i in range(X.shape[0]): + x_test = X[i, :] + + # Calcul de la distance euclidienne entre x_test et tous les points + # d'entraînement (self.X_) + + distances = np.sum((self.X_train_ - x_test)**2, axis=1) + + # Trouver l'indice du point d'entraînement le plus proche + closest_index = np.argmin(distances) + + # L'étiquette prédite est celle du voisin le plus proche + y_pred[i] = self.y_train_[closest_index] + return y_pred def score(self, X, y): - """Write docstring. - - And describe parameters + """ + Retourne l'exactitude moyenne (accuracy) des prédictions sur X par rapport à y. + + Parameters + ---------- + X : array, shape (n_samples, n_features) + Les échantillons de test. + y : array, shape (n_samples,) + Les étiquettes cibles vraies pour X. + + Returns + ------- + score : float + Le pourcentage d'étiquettes bien pédites. """ X, y = check_X_y(X, y) y_pred = self.predict(X) - # XXX fix - return y_pred.sum() + return y_pred.sum()/y.shape[0] From d91138a1e71d7468575000f1b4d36a3e290cfe5d Mon Sep 17 00:00:00 2001 From: leroso Date: Sat, 15 Nov 2025 13:18:07 +0100 Subject: [PATCH 2/8] Final SORO Nangounon Mohamed --- numpy_questions.py | 34 ++++++++++++++++++---------------- sklearn_questions.py | 7 ++++--- 2 files changed, 22 insertions(+), 19 deletions(-) diff --git a/numpy_questions.py b/numpy_questions.py index 65e7f6fe..4cba4d56 100644 --- a/numpy_questions.py +++ b/numpy_questions.py @@ -39,21 +39,20 @@ def max_index(X: np.ndarray) -> tuple: """ # 1. Contrôle du type d'entrée (Doit être un np.ndarray) if not isinstance(X, np.ndarray): - raise ValueError(f"L'entrée doit être un np.ndarray, mais le type {type(X)} a été reçu.") - + raise ValueError(f"L'entrée doit être un np.ndarray, mais le type + {type(X)} a été reçu.") + # 2. Contrôle des dimensions (Doit être 2D) if X.ndim != 2: - raise ValueError(f"Le tableau doit être 2D pour cette fonction (il a {X.ndim} dimensions).") + raise ValueError(f"Le tableau doit être 2D pour cette fonction (il a + {X.ndim} dimensions).") # 3. Recherche de l'indice du maximum for i in range(X.shape[0]): for j in range(X.shape[1]): if X[i, j] == np.max(X): return (i, j) - # La fonction retourne la première occurrence du maximum en parcourant les lignes puis les colonnnes. - - - - + # La fonction retourne la première occurrence du maximum en parcourant les + # lignes puis les colonnnes. def wallis_product(n_terms): """Implement the Wallis product to compute an approximation of pi. @@ -73,23 +72,26 @@ def wallis_product(n_terms): The approximation of order `n_terms` of pi using the Wallis product. """ if not isinstance(n_terms, int): - raise ValueError(f"Le paramètre doit être un entier, (il est du type {type(n_terms)}).") + raise ValueError(f"Le paramètre doit être un entier, (il est du type + {type(n_terms)}).") if n_terms < 1: return 0.0 - + product = 1.0 - + # Itère de k=1 à n_terms (inclus) for k in range(1, n_terms + 1): # Calcule le numérateur (2k) et les dénominateurs (2k-1, 2k+1) - # On utilise des flottants (2.0 * k) pour garantir une division flottante + # On utilise des flottants (2.0 * k) pour garantir une division + # flottante numerator = 2.0 * k denominator1 = numerator - 1.0 denominator2 = numerator + 1.0 - + # Le terme d'ordre k est (2k / (2k - 1)) * (2k / (2k + 1)) term = (numerator / denominator1) * (numerator / denominator2) - + product *= term - - return product * 2.0 # Le produit final est multiplié par 2 pour obtenir l'approximation de pi vu que l'intégrale donne pi/2. \ No newline at end of file + # Le produit final est multiplié par 2 pour obtenir + # l'approximation de pi vu que l'intégrale donne pi/2. + return 2.0 *product \ No newline at end of file diff --git a/sklearn_questions.py b/sklearn_questions.py index 3a430e15..7019cff9 100644 --- a/sklearn_questions.py +++ b/sklearn_questions.py @@ -67,7 +67,7 @@ def fit(self, X, y): def predict(self, X): """ Le but de la méthode predict est de prédire les étiquettes pour les - échantillons de test X en utilisant les données d'entraînement qui + échantillons de test X en utilisant les données d'entraînement qui ont précédemment été stockées dans l'estimateur lors de l'appel à fit. Parameters @@ -93,7 +93,7 @@ def predict(self, X): for i in range(X.shape[0]): x_test = X[i, :] - # Calcul de la distance euclidienne entre x_test et tous les points + # Calcul de la distance euclidienne entre x_test et tous les points # d'entraînement (self.X_) distances = np.sum((self.X_train_ - x_test)**2, axis=1) @@ -108,7 +108,8 @@ def predict(self, X): def score(self, X, y): """ - Retourne l'exactitude moyenne (accuracy) des prédictions sur X par rapport à y. + Retourne l'exactitude moyenne (accuracy) des prédictions sur X + par rapport à y. Parameters ---------- From f6d9562c983e71145cb7202a7792cfbc1d5de039 Mon Sep 17 00:00:00 2001 From: leroso Date: Sat, 15 Nov 2025 13:25:51 +0100 Subject: [PATCH 3/8] Final SORO Nangounon Mohamed --- numpy_questions.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/numpy_questions.py b/numpy_questions.py index 4cba4d56..8fd7f1f0 100644 --- a/numpy_questions.py +++ b/numpy_questions.py @@ -72,8 +72,9 @@ def wallis_product(n_terms): The approximation of order `n_terms` of pi using the Wallis product. """ if not isinstance(n_terms, int): - raise ValueError(f"Le paramètre doit être un entier, (il est du type - {type(n_terms)}).") + raise ValueError( + f"""Le paramètre doit être un entier, + (il est du type{type(n_terms)}""") if n_terms < 1: return 0.0 From c5faa81252b092a3acd8cb44a7cdc2cc7e1de399 Mon Sep 17 00:00:00 2001 From: leroso Date: Sat, 15 Nov 2025 13:34:45 +0100 Subject: [PATCH 4/8] Final SORO Nangounon Mohamed --- numpy_questions.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/numpy_questions.py b/numpy_questions.py index 8fd7f1f0..0856c137 100644 --- a/numpy_questions.py +++ b/numpy_questions.py @@ -39,13 +39,15 @@ def max_index(X: np.ndarray) -> tuple: """ # 1. Contrôle du type d'entrée (Doit être un np.ndarray) if not isinstance(X, np.ndarray): - raise ValueError(f"L'entrée doit être un np.ndarray, mais le type - {type(X)} a été reçu.") + raise ValueError( + f"""L'entrée doit être un np.ndarray, mais le type + {type(X)} a été reçu.""") # 2. Contrôle des dimensions (Doit être 2D) if X.ndim != 2: - raise ValueError(f"Le tableau doit être 2D pour cette fonction (il a - {X.ndim} dimensions).") + raise ValueError( + f"""Le tableau doit être 2D pour cette fonction (il a + {X.ndim} dimensions).""") # 3. Recherche de l'indice du maximum for i in range(X.shape[0]): for j in range(X.shape[1]): From 15015733fe710d9de57758697f55a199f808ed81 Mon Sep 17 00:00:00 2001 From: leroso Date: Sat, 15 Nov 2025 13:45:00 +0100 Subject: [PATCH 5/8] Final SORO Nangounon Mohamed --- numpy_questions.py | 2 +- sklearn_questions.py | 8 +++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/numpy_questions.py b/numpy_questions.py index 0856c137..6f90ffe9 100644 --- a/numpy_questions.py +++ b/numpy_questions.py @@ -78,7 +78,7 @@ def wallis_product(n_terms): f"""Le paramètre doit être un entier, (il est du type{type(n_terms)}""") if n_terms < 1: - return 0.0 + return 1.0 product = 1.0 diff --git a/sklearn_questions.py b/sklearn_questions.py index 7019cff9..005ddcc5 100644 --- a/sklearn_questions.py +++ b/sklearn_questions.py @@ -16,7 +16,8 @@ calling `flake8` at the root of the repo. Finally, you need to write docstring similar to the one in `numpy_questions` -for the methods you code and for the class. The docstring will be checked using +for the methods you code and for the class. The docstring will be checked +using `pydocstyle` that you can also call at the root of the repo. """ import numpy as np @@ -93,7 +94,8 @@ def predict(self, X): for i in range(X.shape[0]): x_test = X[i, :] - # Calcul de la distance euclidienne entre x_test et tous les points + # Calcul de la distance euclidienne entre x_test et tous + # les points # d'entraînement (self.X_) distances = np.sum((self.X_train_ - x_test)**2, axis=1) @@ -126,4 +128,4 @@ def score(self, X, y): X, y = check_X_y(X, y) y_pred = self.predict(X) - return y_pred.sum()/y.shape[0] + return np.mean(y_pred == y) From 63134b9f84832901614f4cd0d46e9e578b94c82b Mon Sep 17 00:00:00 2001 From: leroso Date: Sat, 15 Nov 2025 13:49:43 +0100 Subject: [PATCH 6/8] Final SORO Nangounon Mohamed --- numpy_questions.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/numpy_questions.py b/numpy_questions.py index 6f90ffe9..8ae289c0 100644 --- a/numpy_questions.py +++ b/numpy_questions.py @@ -56,6 +56,7 @@ def max_index(X: np.ndarray) -> tuple: # La fonction retourne la première occurrence du maximum en parcourant les # lignes puis les colonnnes. + def wallis_product(n_terms): """Implement the Wallis product to compute an approximation of pi. @@ -97,4 +98,4 @@ def wallis_product(n_terms): product *= term # Le produit final est multiplié par 2 pour obtenir # l'approximation de pi vu que l'intégrale donne pi/2. - return 2.0 *product \ No newline at end of file + return 2.0 * product From 98f720d232e86010cf8bc1fd42ff5a8f38ffec9c Mon Sep 17 00:00:00 2001 From: leroso Date: Sat, 15 Nov 2025 13:54:21 +0100 Subject: [PATCH 7/8] Final SORO Nangounon Mohamed --- sklearn_questions.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/sklearn_questions.py b/sklearn_questions.py index 005ddcc5..fca73c74 100644 --- a/sklearn_questions.py +++ b/sklearn_questions.py @@ -30,7 +30,7 @@ class OneNearestNeighbor(BaseEstimator, ClassifierMixin): - "OneNearestNeighbor classifier." + """OneNearestNeighbor classifier.""" def __init__(self): # noqa: D107 pass @@ -66,8 +66,7 @@ def fit(self, X, y): return self def predict(self, X): - """ - Le but de la méthode predict est de prédire les étiquettes pour les + """ Le but de la méthode predict est de prédire les étiquettes pour les échantillons de test X en utilisant les données d'entraînement qui ont précédemment été stockées dans l'estimateur lors de l'appel à fit. @@ -81,7 +80,6 @@ def predict(self, X): y_pred : ndarray, shape (n_samples,) Les étiquettes de classe prédites pour chaque échantillon de test. """ - # Vérification que l'estimateur a bien été entraîné check_is_fitted(self) X = check_array(X) @@ -109,8 +107,7 @@ def predict(self, X): return y_pred def score(self, X, y): - """ - Retourne l'exactitude moyenne (accuracy) des prédictions sur X + """ Retourne l'exactitude moyenne (accuracy) des prédictions sur X par rapport à y. Parameters From 1b48524603c557eec566e40d453e80517806663c Mon Sep 17 00:00:00 2001 From: leroso Date: Sat, 15 Nov 2025 14:04:14 +0100 Subject: [PATCH 8/8] Final SORO Nangounon Mohamed --- sklearn_questions.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/sklearn_questions.py b/sklearn_questions.py index fca73c74..bf47eb6c 100644 --- a/sklearn_questions.py +++ b/sklearn_questions.py @@ -66,9 +66,11 @@ def fit(self, X, y): return self def predict(self, X): - """ Le but de la méthode predict est de prédire les étiquettes pour les - échantillons de test X en utilisant les données d'entraînement qui - ont précédemment été stockées dans l'estimateur lors de l'appel à fit. + """Le but de la méthode predict est de prédire les étiquettes. + + Pour les chantillons de test X en utilisant les données d'entraînement + qui ont précédemment été stockées dans l'estimateur lors de + l'appel à fit. Parameters ---------- @@ -107,8 +109,7 @@ def predict(self, X): return y_pred def score(self, X, y): - """ Retourne l'exactitude moyenne (accuracy) des prédictions sur X - par rapport à y. + """Retourne le pourcentage d'étiquettes bien pédites (Accuracy). Parameters ---------- @@ -116,7 +117,6 @@ def score(self, X, y): Les échantillons de test. y : array, shape (n_samples,) Les étiquettes cibles vraies pour X. - Returns ------- score : float