diff --git a/numpy_questions.py b/numpy_questions.py index 21fcec4b..1fcdc363 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..deebde69 100644 --- a/sklearn_questions.py +++ b/sklearn_questions.py @@ -28,47 +28,100 @@ 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. + """Fit the OneNearestNeighbor classifier according to the training set. - And describe parameters + 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. - And describe parameters + Parameters + ---------- + X : ndarray of shape (n_samples, n_features) + The data to predict the labels. + + 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_: + raise ValueError( + 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) + y_pred = self.y_train_[nearest] + return y_pred def score(self, X, y): - """Write docstring. + """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 - And describe parameters + Returns + ------- + 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) - # XXX fix - return y_pred.sum() + return score