我在这里看到了这个列表,不敢相信有这么多方法可以解决最小二乘问题。维基百科上的“正规方程”似乎是一种相当直接的方式:
那么为什么不直接使用它们呢?我认为一定存在计算或精度问题,因为在上面的第一个链接中,Mark L. Stone 提到 SVD 或 QR 是统计软件中的流行方法,并且正规方程“从可靠性和数值精度的角度来看是可怕的”。然而,在下面的代码中,与三个流行的 python 函数相比,正规方程的精度可以精确到小数点后 12 位:numpy 的polyfit;scipy 的线性回归;和 scikit-learn 的LinearRegression。
更有趣的是,当 n = 100000000 时,正规方程方法是最快的。我的计算时间是:2.5s for linregress;polyfit 12.9s;线性回归 4.2s;正常方程为 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)