I was playing around with LinearRegression in Scikit Learn and I found a peculiarity that I'm trying to make sense out of.
If you compare values from the coef_
attribute, they only match the values given from the equation:
if you standardize the X
feature matrix.
As an example, let's look at the results from the boston housing data set:
import pandas as pd
import numpy as np
from sklearn.datasets import load_boston
from sklearn.linear_model import LinearRegression
boston = load_boston()
X = pd.DataFrame(boston.data)
X.columns = boston.feature_names
y = boston.target
With non-standardized data the results between the two methods differ:
# Comparison of Coefficients Without Standardized Data
np_coeffs = (np.linalg.inv(X.T.dot(X))).dot(X.T.dot(y))
lreg = LinearRegression()
sk_coeffs = lreg.fit(X, y).coef_
# Put results into a dataframe for easy comparison
coeff_comparison1 = pd.DataFrame({
'Variable' : X.columns,
'np_coeffs': np_coeffs,
'sk_coeffs': sk_coeffs
})
Which yields the following results:
If we standardize the data though, the results match exactly:
# comparison for coefficients with standardized data
X_std = (X - X.mean()) / X.std()
np_std_coeffs = (np.linalg.inv(X_std.T.dot(X_std))).dot(X_std.T.dot(y))
sk_std_coeffs = lreg.fit(X_std, y).coef_
coeff_comparison2 = pd.DataFrame({
'Variable' : X.columns,
'np_std_coeffs': np_std_coeffs,
'sk_std_coeffs': sk_std_coeffs
})
Which gives the following dataframe:
And as you can see the results match exactly.
I'm curious what Scikit Learn does that causes one set of results to match those of the matrix equation, and the others to diverge.
Thank you.
np_coeffs = (np.linalg.inv(X.T.dot(X))).dot(X.T.dot(y))
, it's always better to do this:np_coeffs = np.linalg.solve(X.T.dot(X), X.T.dot(y))
. The equation is written mathematically with an inverse, but it's best to avoid explicitly computing an inverse wherever possible. As an aside, there's now a better way to write that out in python:np_coeffs = np.linalg.solve(X.T @ X, X.T @ y)
. The@
for matrix multiplication makes the whole thing more readable. $\endgroup$