Regression
為什麼不使用“正規方程”來找到簡單的最小二乘係數?
我在這裡看到了這個列表,不敢相信有這麼多方法可以解決最小二乘問題。維基百科上的“正規方程”似乎是一種相當直接的方式:
那麼為什麼不直接使用它們呢?我認為一定存在計算或精度問題,因為在上面的第一個鏈接中,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 位的精度。如果您形成正規方程,您已經將條件數平方為,並且您的答案基本上沒有準確性。
有時您可以擺脫正常方程,有時則不會。