J'ai vu cette liste ici et je ne pouvais pas croire qu'il y avait tant de façons de résoudre les moindres carrés. Les «équations normales» sur Wikipédia semblaient être une méthode assez simple:
Alors pourquoi ne pas simplement les utiliser? J'ai supposé qu'il devait y avoir un problème de calcul ou de précision étant donné que dans le premier lien ci-dessus, Mark L. Stone mentionne que SVD ou QR sont des méthodes populaires dans les logiciels statistiques et que les équations normales sont "TERRIBLES du point de vue de la fiabilité et de la précision numérique". Cependant , dans le code suivant, les équations normales me donnent une précision à environ 12 décimales par rapport à trois fonctions python populaires: polyfit de numpy ; linregress de scipy ; et scikit-learn de régression linéaire .
Ce qui est plus intéressant, c'est que la méthode d'équation normale est la plus rapide lorsque n = 100000000. Les temps de calcul pour moi sont: 2,5 s pour linregress; 12,9 pour polyfit; 4.2s pour LinearRegression; et 1,8 s pour l'équation normale.
Code:
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)