Vi esta lista aquí y no podía creer que hubiera tantas formas de resolver mínimos cuadrados. Las "ecuaciones normales" en la Wikipedia parecían ser una forma bastante
Entonces, ¿por qué no solo usarlos? Supuse que debe haber un problema de cálculo o precisión dado que en el primer enlace anterior, Mark L. Stone menciona que SVD o QR son métodos populares en software estadístico y que las ecuaciones normales son "TERRIBLES desde el punto de vista de la fiabilidad y la precisión numérica". Sin embargo , en el siguiente código, las ecuaciones normales me dan una precisión de ~ 12 lugares decimales en comparación con tres funciones populares de python: polyfit de numpy ; linregress de scipy ; y scikit-learn de LinearRegression .
Lo que es más interesante es que el método de ecuación normal es el más rápido cuando n = 100000000. Los tiempos de cálculo para mí son: 2.5s para linregress; 12.9s para polyfit; 4.2s para la regresión lineal; y 1.8s para la ecuación normal.
Código:
import numpy as np
from sklearn.linear_model import LinearRegression
from scipy.stats import linregress
import timeit
b0 = 0
b1 = 1
n = 100000000
x = np.linspace(-5, 5, n)
np.random.seed(42)
e = np.random.randn(n)
y = b0 + b1*x + e
# scipy
start = timeit.default_timer()
print(str.format('{0:.30f}', linregress(x, y)[0]))
stop = timeit.default_timer()
print(stop - start)
# numpy
start = timeit.default_timer()
print(str.format('{0:.30f}', np.polyfit(x, y, 1)[0]))
stop = timeit.default_timer()
print(stop - start)
# sklearn
clf = LinearRegression()
start = timeit.default_timer()
clf.fit(x.reshape(-1, 1), y.reshape(-1, 1))
stop = timeit.default_timer()
print(str.format('{0:.30f}', clf.coef_[0, 0]))
print(stop - start)
# normal equation
start = timeit.default_timer()
slope = np.sum((x-x.mean())*(y-y.mean()))/np.sum((x-x.mean())**2)
stop = timeit.default_timer()
print(str.format('{0:.30f}', slope))
print(stop - start)