Regression

為什麼不使用“正規方程”來找到簡單的最小二乘係數?

  • April 27, 2018

我在這裡看到了這個列表,不敢相信有這麼多方法可以解決最小二乘問題。維基百科上的“正規方程”似乎是一種相當直接的方式:

那麼為什麼不直接使用它們呢?我認為一定存在計算或精度問題,因為在上面的第一個鏈接中,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) 

對於問題,形成正規方程的條件數的平方通過形成. 粗略地說是如果一切都做得很好,您在計算中丟失的位數。這與形成的倒數沒有任何關係. 不管怎樣解決了,你已經輸了精度位數。即,形成正態方程使準確度損失的位數增加了一倍,馬上就可以了。

如果條件數很小(一個是最好的),則無關緊要。如果條件數 =並且您使用穩定的方法,例如 QR 或 SVD,雙精度可能有大約 8 位的精度。如果您形成正規方程,您已經將條件數平方為,並且您的答案基本上沒有準確性。

有時您可以擺脫正常方程,有時則不會。

引用自:https://stats.stackexchange.com/questions/343069

comments powered by Disqus