2

我試圖解決方形的線性系統Xc=y。我知道解決這個的方法是:爲什麼python中解決Xc = y的不同方法在不應該的時候給出不同的解決方案?

  1. 使用逆c=<X^-1,y>
  2. 用高斯消元法
  3. 使用僞逆

似乎只要我可以告訴大家,這些別不符合我認爲的基本事實。

  1. 首先通過擬合30次多項式到頻率爲5的餘弦來生成真值參數。所以我有y_truth = X*c_truth
  2. 然後我檢查,如果上述三種方法相匹配的真相

我嘗試過,但似乎該方法不匹配,我不明白爲什麼這應該是這樣的。

我公司生產的完全可運行的重複性代碼:

import numpy as np 
from sklearn.preprocessing import PolynomialFeatures 

## some parameters 
degree_target = 25 
N_train = degree_target+1 
lb,ub = -2000,2000 
x = np.linspace(lb,ub,N_train) 
## generate target polynomial model 
freq_cos = 5 
y_cos = np.cos(2*np.pi*freq_cos*x) 
c_polyfit = np.polyfit(x,y_cos,degree_target)[::-1] ## needs to me reverse to get highest power last 
## generate kernel matrix 
poly_feat = PolynomialFeatures(degree=degree_target) 
K = poly_feat.fit_transform(x.reshape(N_train,1)) # generates degree 0 first 
## get target samples of the function 
y = np.dot(K,c_polyfit) 
## get pinv approximation of c_polyfit 
c_pinv = np.dot(np.linalg.pinv(K), y) 
## get Gaussian-Elminiation approximation of c_polyfit 
c_GE = np.linalg.solve(K,y) 
## get inverse matrix approximation of c_polyfit 
i = np.linalg.inv(K) 
c_mdl_i = np.dot(i,y) 
## check rank to see if its truly invertible 
print('rank(K) = {}'.format(np.linalg.matrix_rank(K))) 
## comapre parameters 
print('--c_polyfit') 
print('||c_polyfit-c_GE||^2 = {}'.format(np.linalg.norm(c_polyfit-c_GE))) 
print('||c_polyfit-c_pinv||^2 = {}'.format(np.linalg.norm(c_polyfit-c_pinv))) 
print('||c_polyfit-c_mdl_i||^2 = {}'.format(np.linalg.norm(c_polyfit-c_mdl_i))) 
print('||c_polyfit-c_polyfit||^2 = {}'.format(np.linalg.norm(c_polyfit-c_polyfit))) 
## 
print('--c_GE') 
print('||c_GE-c_GE||^2 = {}'.format(np.linalg.norm(c_GE-c_GE))) 
print('||c_GE-c_pinv||^2 = {}'.format(np.linalg.norm(c_GE-c_pinv))) 
print('||c_GE-c_mdl_i||^2 = {}'.format(np.linalg.norm(c_GE-c_mdl_i))) 
print('||c_GE-c_polyfit||^2 = {}'.format(np.linalg.norm(c_GE-c_polyfit))) 
## 
print('--c_pinv') 
print('||c_pinv-c_GE||^2 = {}'.format(np.linalg.norm(c_pinv-c_GE))) 
print('||c_pinv-c_pinv||^2 = {}'.format(np.linalg.norm(c_pinv-c_pinv))) 
print('||c_pinv-c_mdl_i||^2 = {}'.format(np.linalg.norm(c_pinv-c_mdl_i))) 
print('||c_pinv-c_polyfit||^2 = {}'.format(np.linalg.norm(c_pinv-c_polyfit))) 
## 
print('--c_mdl_i') 
print('||c_mdl_i-c_GE||^2 = {}'.format(np.linalg.norm(c_mdl_i-c_GE))) 
print('||c_mdl_i-c_pinv||^2 = {}'.format(np.linalg.norm(c_mdl_i-c_pinv))) 
print('||c_mdl_i-c_mdl_i||^2 = {}'.format(np.linalg.norm(c_mdl_i-c_mdl_i))) 
print('||c_mdl_i-c_polyfit||^2 = {}'.format(np.linalg.norm(c_mdl_i-c_polyfit))) 

和我得到的結果是:

rank(K) = 4 
--c_polyfit 
||c_polyfit-c_GE||^2 = 4.44089220304006e-16 
||c_polyfit-c_pinv||^2 = 1.000000000000001 
||c_polyfit-c_mdl_i||^2 = 1.1316233165135605e-06 
||c_polyfit-c_polyfit||^2 = 0.0 
--c_GE 
||c_GE-c_GE||^2 = 0.0 
||c_GE-c_pinv||^2 = 1.0000000000000007 
||c_GE-c_mdl_i||^2 = 1.1316233160694804e-06 
||c_GE-c_polyfit||^2 = 4.44089220304006e-16 
--c_pinv 
||c_pinv-c_GE||^2 = 1.0000000000000007 
||c_pinv-c_pinv||^2 = 0.0 
||c_pinv-c_mdl_i||^2 = 0.9999988683985006 
||c_pinv-c_polyfit||^2 = 1.000000000000001 
--c_mdl_i 
||c_mdl_i-c_GE||^2 = 1.1316233160694804e-06 
||c_mdl_i-c_pinv||^2 = 0.9999988683985006 
||c_mdl_i-c_mdl_i||^2 = 0.0 
||c_mdl_i-c_polyfit||^2 = 1.1316233165135605e-06 

爲什麼呢?它是一臺機器精確的東西嗎?還是因爲當程度很大(大於1)時,錯誤累積(很多)?老實說,我不知道,但所有這些假設對我來說都很愚蠢。如果有人能夠發現我的錯誤,請隨時指出。否則,我可能不會理解線性代數或其他......這更令人擔憂。

此外,如果我能得到這個工作的建議,它將不勝感激。我是否:

  1. 增加間隔的大小不小於1(大小)?
  2. 我可以使用的最大多項式大小度數是多少?
  3. 不同的語言......?或者提高精度?

任何建議表示讚賞!

+0

作爲一個有趣的側面問題,如果我要用GD或SGD訓練我的多項式模型,如果我將模型限制在'[-1,1]'中,那麼我是否會有相同的數值錯誤,或者這只是特別的(僞)反轉矩陣? – Pinocchio

+0

另一個跟進問題。我已經多次提出建議將間隔改爲'[-5,5]'。但是,現在我的問題是,爲什麼不出現相反的問題,然後取代'1.0 + eps_num = NaN'的'1.0 + eps = 1.0'?如果'big_number = number^30'?就像爲什麼數值問題似乎在提高到30的冪數時小於1的數字更敏感? – Pinocchio

回答

2

問題是浮點精度。您將數字從0增加到30,然後將它們加在一起。如果你使用無限精度算術來做這些,這些方法會恢復輸入。使用浮點運算,精度損失意味着你不能。

+0

有沒有辦法讓這些方法產生相同的答案?也許改變投入的範圍?或者也許有更低的多項式? – Pinocchio

+0

我一直在玩它,它似乎對僞逆是一個我最關心的人特別糟...... – Pinocchio

+0

也,這是一個語言相關的問題?例如它會在Matlab中出現嗎? – Pinocchio

相關問題