From 97b585a8dd5d499a3c980834ce320d92f8dd967a Mon Sep 17 00:00:00 2001 From: lugavt Date: Sat, 15 Nov 2025 14:28:21 +0100 Subject: [PATCH 1/2] Complete assignment questions --- numpy_questions.py | 17 ++++++-- sklearn_questions.py | 98 +++++++++++++++++++++++++++++++++++--------- 2 files changed, 91 insertions(+), 24 deletions(-) diff --git a/numpy_questions.py b/numpy_questions.py index 21fcec4b..135d546a 100644 --- a/numpy_questions.py +++ b/numpy_questions.py @@ -40,7 +40,12 @@ def max_index(X): i = 0 j = 0 - # TODO + if not (isinstance(X, np.ndarray)): + raise ValueError("the input is not a numpy array") + if (X.ndim != 2): + raise ValueError("the shape is not 2D") + + i, j = np.unravel_index(np.argmax(X), X.shape) return i, j @@ -62,6 +67,10 @@ 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. + wallis = 1 + if(n_terms == 0): + return wallis + else: + for i in range(1, n_terms+1): + wallis *= (2*i/(2*i - 1))*(2*i/(2*i+1)) + return 2*wallis diff --git a/sklearn_questions.py b/sklearn_questions.py index f65038c6..790a9290 100644 --- a/sklearn_questions.py +++ b/sklearn_questions.py @@ -28,47 +28,105 @@ from sklearn.utils.multiclass import check_classification_targets -class OneNearestNeighbor(BaseEstimator, ClassifierMixin): - "OneNearestNeighbor classifier." +class OneNearestNeighbor(ClassifierMixin, BaseEstimator): + """OneNearestNeighbor classifier. + + Implement a OneNearestNeighbor classifier to predict the label of a + point X_i based of the y_j label of the its closest neighbor X_j + + Attributes + ---------- + X_train_ : ndarray shaped (n_samples, n_features) + Training data + + y_train_ : ndarray shaped (n_samples,) + Target labels + + """ + def __init__(self): # noqa: D107 pass def fit(self, X, y): - """Write docstring. - - And describe parameters + """Fit the OneNearestNeighbor classifier according to the training set. + + Parameters + ---------- + X : ndarray of shape (n_samples, n_features) + The training data. + + y : ndarray of shape (n_samples,) + The target labels. + + Returns + ------- + self: OneNearestNeighbor + The OneNearestNeighbor classifier trained """ + 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 + self.X_train_ = X + self.y_train_ = y + return self def predict(self, X): - """Write docstring. + """Predict class label according to the fitted model. + + Parameters + ---------- + X : ndarray of shape (n_samples, n_features) + The data to predict the labels. - And describe parameters + Returns + ------- + y_pred: ndarray of shape (n_samples,) + The predicted labels for the data. """ + check_is_fitted(self) X = check_array(X) - y_pred = np.full( - shape=len(X), fill_value=self.classes_[0], - dtype=self.classes_.dtype - ) - - # XXX fix + + if X.shape[1] != self.n_features_in_: + n_features_X = X.shape[1] + raise ValueError( + f"X has {n_features_X} features, but " + f"{self.__class__.__name__} is expecting " + f"{self.n_features_in_} features as input") + + A2 = np.sum(X**2, axis=1, keepdims=True) + B2 = np.sum(self.X_train_**2, axis=1, keepdims=True).T + d2 = A2 - 2*(X @ self.X_train_.T) + B2 + + nearest = np.argmin(d2, axis=1) + y_pred = self.y_train_[nearest] + return y_pred def score(self, X, y): - """Write docstring. - - And describe parameters + """Return the accuracy of the test data under the fitted model + + Parameters + ---------- + X : ndarray of shape (n_samples, n_features) + The data to predict the labels. + + y : ndarray of shape (n_samples,) + The real labels + + Returns + ------- + score : float + The accuracy of the prediction. """ + X, y = check_X_y(X, y) y_pred = self.predict(X) - - # XXX fix - return y_pred.sum() + score = np.mean(y_pred == y) + + return score From 6be8d1ffcdca99961df8af4ff14633a36e4f53bf Mon Sep 17 00:00:00 2001 From: lugavt Date: Sat, 15 Nov 2025 14:51:41 +0100 Subject: [PATCH 2/2] Fixing issues in the PR --- numpy_questions.py | 6 +++--- sklearn_questions.py | 33 ++++++++++++++------------------- 2 files changed, 17 insertions(+), 22 deletions(-) diff --git a/numpy_questions.py b/numpy_questions.py index 135d546a..1fcdc363 100644 --- a/numpy_questions.py +++ b/numpy_questions.py @@ -44,7 +44,7 @@ def max_index(X): raise ValueError("the input is not a numpy array") if (X.ndim != 2): raise ValueError("the shape is not 2D") - + i, j = np.unravel_index(np.argmax(X), X.shape) return i, j @@ -68,9 +68,9 @@ def wallis_product(n_terms): The approximation of order `n_terms` of pi using the Wallis product. """ wallis = 1 - if(n_terms == 0): + if (n_terms == 0): return wallis else: for i in range(1, n_terms+1): - wallis *= (2*i/(2*i - 1))*(2*i/(2*i+1)) + wallis *= (2*i/(2*i - 1)) * (2*i/(2*i+1)) return 2*wallis diff --git a/sklearn_questions.py b/sklearn_questions.py index 790a9290..deebde69 100644 --- a/sklearn_questions.py +++ b/sklearn_questions.py @@ -30,8 +30,8 @@ class OneNearestNeighbor(ClassifierMixin, BaseEstimator): """OneNearestNeighbor classifier. - - Implement a OneNearestNeighbor classifier to predict the label of a + + Implement a OneNearestNeighbor classifier to predict the label of a point X_i based of the y_j label of the its closest neighbor X_j Attributes @@ -41,9 +41,8 @@ class OneNearestNeighbor(ClassifierMixin, BaseEstimator): y_train_ : ndarray shaped (n_samples,) Target labels - + """ - def __init__(self): # noqa: D107 pass @@ -55,7 +54,7 @@ def fit(self, X, y): ---------- X : ndarray of shape (n_samples, n_features) The training data. - + y : ndarray of shape (n_samples,) The target labels. @@ -64,7 +63,6 @@ def fit(self, X, y): self: OneNearestNeighbor The OneNearestNeighbor classifier trained """ - X, y = check_X_y(X, y) check_classification_targets(y) self.classes_ = np.unique(y) @@ -72,7 +70,7 @@ def fit(self, X, y): self.X_train_ = X self.y_train_ = y - + return self def predict(self, X): @@ -88,34 +86,32 @@ def predict(self, X): y_pred: ndarray of shape (n_samples,) The predicted labels for the data. """ - check_is_fitted(self) X = check_array(X) - + if X.shape[1] != self.n_features_in_: - n_features_X = X.shape[1] raise ValueError( - f"X has {n_features_X} features, but " + f"X has {X.shape[1]} features, but " f"{self.__class__.__name__} is expecting " f"{self.n_features_in_} features as input") - + A2 = np.sum(X**2, axis=1, keepdims=True) B2 = np.sum(self.X_train_**2, axis=1, keepdims=True).T d2 = A2 - 2*(X @ self.X_train_.T) + B2 - - nearest = np.argmin(d2, axis=1) + + nearest = np.argmin(d2, axis=1) y_pred = self.y_train_[nearest] - + return y_pred def score(self, X, y): - """Return the accuracy of the test data under the fitted model + """Return the accuracy of the test data under the fitted model. Parameters ---------- X : ndarray of shape (n_samples, n_features) The data to predict the labels. - + y : ndarray of shape (n_samples,) The real labels @@ -124,9 +120,8 @@ def score(self, X, y): score : float The accuracy of the prediction. """ - X, y = check_X_y(X, y) y_pred = self.predict(X) score = np.mean(y_pred == y) - + return score