Ho visto questo elenco qui e non potevo credere che ci fossero così tanti modi per risolvere i minimi quadrati. I "equazioni normali" su Wikipedia sembrava essere un modo abbastanza
Quindi perché non usarli? Ho ipotizzato che ci debba essere un problema computazionale o di precisione dato che nel primo link sopra Mark L. Stone menziona che SVD o QR sono metodi popolari nei software statistici e che le equazioni normali sono "TERRIBILI dal punto di vista dell'affidabilità e dell'accuratezza numerica". Tuttavia , nel codice seguente, le equazioni normali mi danno l'accuratezza di ~ 12 cifre decimali rispetto a tre funzioni pitone popolari: polyfit di numpy ; sciabolo di linea ; e LinearRegression di scikit-learn .
La cosa più interessante è che il normale metodo di equazione è il più veloce quando n = 100000000. I tempi di calcolo per me sono: 2,5 s per il ritorno di linea; 12,9s per polyfit; 4.2s per LinearRegression; e 1.8s per l'equazione normale.
Codice:
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)