Eu vi essa lista aqui e não podia acreditar que havia tantas maneiras de resolver mínimos quadrados. As "equações normais" na Wikipedia pareciam ser um caminho bastante direto:
Então, por que não usá-los? Eu assumi que deve haver um problema computacional ou de precisão, dado que no primeiro link acima, Mark L. Stone menciona que SVD ou QR são métodos populares em software estatístico e que as equações normais são "TERRÍVEIS do ponto de vista da confiabilidade e da precisão numérica". No entanto , no código a seguir, as equações normais estão fornecendo precisão de ~ 12 casas decimais quando comparadas a três funções populares do python: polyfit do numpy ; vestido de linha de scipy ; e a LinearRegression do scikit -learn .
O mais interessante é que o método da equação normal é o mais rápido quando n = 100000000. Os tempos computacionais para mim são: 2,5s para regressão linear; 12.9s para polyfit; 4.2s para regressão linear; e 1,8s para a equação 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)