Я побачив цей список тут і не міг повірити, що існує стільки способів вирішити найменші квадрати. «Нормальні рівняння» на Вікіпедії , здавалося, досить прямим
То чому б просто не використовувати їх? Я припускав, що має виникнути обчислювальна чи точна проблема, враховуючи, що в першому посиланні вище Марка Л. Стоун згадується, що SVD або QR є популярними методами в статистичному програмному забезпеченні і що нормальні рівняння є "ГОЛОВНІ з точки зору надійності та чисельної точності". Однак у наступному коді звичайні рівняння дають мені точність до 12 знаків після коми, порівняно з трьома популярними функціями пітона: polyfit numpy ; SciPy в linregress ; та лінійна регресія scikit- learn .
Що цікавіше, що звичайний метод рівняння є найшвидшим, коли n = 100000000. Для мене обчислювальні періоди: 2,5s для прямого прогресу; 12,9 за поліфіт; 4.2s для LinearRegression; і 1,8s для нормального рівняння.
Код:
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)