Widziałem tę listę tutaj i nie mogłem uwierzyć, że istnieje tak wiele sposobów rozwiązania najmniejszych kwadratów. „Normalne równania” na Wikipedii wydawał się być dość prosty sposób do
Dlaczego więc ich nie użyć? Zakładam, że musi istnieć problem obliczeniowy lub precyzyjny, biorąc pod uwagę, że w pierwszym linku powyżej Mark L. Stone wspomina, że SVD lub QR są popularnymi metodami w oprogramowaniu statystycznym i że równania normalne są „OKAZISTE z punktu widzenia niezawodności i dokładności numerycznej”. Jednak w poniższym kodzie równania normalne dają mi dokładność do ~ 12 miejsc po przecinku w porównaniu z trzema popularnymi funkcjami pytona: polyfit numpy ; regres linowy Scipy'ego ; i scikit-learn'S regresja liniowa .
Co ciekawsze, metoda równania normalnego jest najszybsza, gdy n = 100000000. Czasy obliczeniowe dla mnie wynoszą: 2,5 s dla regresji liniowej; 12,9s dla polyfit; 4.2s dla regresji liniowej; i 1,8 s dla równania normalnego.
Kod:
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)