human
2.2 Build the Classifier
Relying on the derived equations, we can implement our model relying only on the NumPy linear algebra capabilities (really wrappers to BLAS / LAPACK implementations such as ATLAS, OpenBLAS or MKL).
A ML model is best represented as a class, with hyper-parameters and parameters stored as attributes, and is composed of two essential methods:
1. y_pred = model.predict(X_test): return the predictions $y$ given the features $X$.
1. model.fit(X_train, y_train): learn the model parameters such as to predict $y$ given $X$.

=====
Give me a the Python code you requested?
assistant
#Here is the Python code you requested.
class RidgeRegression(object):
    """Our ML model."""
    
    def __init__(self, alpha=0):
        "The class' constructor. Initialize the hyper-parameters."
        self.a = alpha
    
    def predict(self, X):
        """Return the predicted class given the features."""
        return np.sign(X.dot(self.w) + self.b)
    
    def fit(self, X, y):
        """Learn the model's parameters given the training data, the closed-form way."""
        n, d = X.shape
        self.b = np.mean(y)
        Ainv = np.linalg.inv(X.T.dot(X) + self.a * np.identity(d))
        self.w = Ainv.dot(X.T).dot(y - self.b)

    def loss(self, X, y, w=None, b=None):
        """Return the current loss.
        This method is not strictly necessary, but it provides
        information on the convergence of the learning process."""
        w = self.w if w is None else w  # The ternary conditional operator
        b = self.b if b is None else b  # makes those tests concise.
        import autograd.numpy as np  # See below for autograd.
        return np.linalg.norm(np.dot(X, w) + b - y)**2 + self.a * np.linalg.norm(w, 2)**2