dafriedman97 / mlbook

Repository for the free online book Machine Learning from Scratch (link below!)
https://dafriedman97.github.io/mlbook/content/introduction.html
MIT License
1.16k stars 211 forks source link

No-constructors classes #15

Closed epogrebnyak closed 3 years ago

epogrebnyak commented 3 years ago

Congratulations on a releasing the well structured book! Neat use of Jupyter book!

I thought of use of no-constructor classes in your code - good for combining methods together, but not really a great pattern for starting programming - not to replicate when a learner just starts writing Python code.

class LinearRegression:

    def fit(self, X, y, intercept = False):

        # record data and dimensions
        if intercept == False: # add intercept (if not already included)
            ones = np.ones(len(X)).reshape(len(X), 1) # column of ones 
            X = np.concatenate((ones, X), axis = 1)
        self.X = np.array(X)
        self.y = np.array(y)
        self.N, self.D = self.X.shape

        # estimate parameters
        XtX = np.dot(self.X.T, self.X)
        XtX_inverse = np.linalg.inv(XtX)
        Xty = np.dot(self.X.T, self.y)
        self.beta_hats = np.dot(XtX_inverse, Xty)

        # make in-sample predictions
        self.y_hat = np.dot(self.X, self.beta_hats)

        # calculate loss
        self.L = .5*np.sum((self.y - self.y_hat)**2)

I understand this is an idiom throughout the book, but if you consider restructuring the code at some point, there can be a more functional representation:


        # estimate parameters
        XtX = np.dot(self.X.T, self.X)
        XtX_inverse = np.linalg.inv(XtX)
        Xty = np.dot(self.X.T, self.y)
        self.beta_hats = np.dot(XtX_inverse, Xty)

def estimate_betas(X,Y):
        XtX = np.dot(X.T, X)
        XtX_inverse = np.linalg.inv(XtX)
        Xty = np.dot(X.T, Y)
        return np.dot(XtX_inverse, Xty)
epogrebnyak commented 3 years ago

The estimate_betas() function you can probably mount back to LinearRegression() for similar interface across fucntions.

Another idea is probably write a small comment on why classes with .fit() and .predict() would are needed (similar to scikit-learn API, uniform across many models, etc)