为什么python中求解Xc=y的不同方法给出了不同的解决方案,而它们本不应该给出不同的解决方案?
我试图解一个平方的线性系统。我知道解决这个问题的方法有:为什么python中求解Xc=y的不同方法给出了不同的解决方案,而它们本不应该给出不同的解决方案?,python,numpy,linear-algebra,linear-regression,polynomial-math,Python,Numpy,Linear Algebra,Linear Regression,Polynomial Math,我试图解一个平方的线性系统。我知道解决这个问题的方法有: 使用反向c= 利用高斯消去法 使用伪逆 据我所知,这些似乎与我认为的基本事实不符 首先,通过将30次多项式拟合为频率为5的余弦来生成真值参数。所以我有了y_真理=X*c_真理 然后我检查上述三种方法是否符合事实 我试过了,但方法似乎不匹配,我不明白为什么会这样 我生成了完全可运行的可复制代码: import numpy as np from sklearn.preprocessing import PolynomialFeatures
c=
y_真理=X*c_真理
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)时误差累积(很多)?老实说,我不知道,但我觉得所有这些假设都很愚蠢。如果有人能发现我的错误,请随意指出。否则,我可能不懂线性代数或其他东西……这更令人担忧
此外,如果我能得到建议,这将是非常感谢。我是否:
任何建议都将不胜感激 问题在于浮点精度。你把0和1之间的数字提高到30次方,然后把它们相加。如果您使用无限精度算法执行此操作,这些方法将恢复输入。对于浮点运算,精度损失意味着不能。有没有办法让这些方法得到相同的答案?也许改变输入的范围?或者可能有较低阶的多项式?我一直在玩弄它,它似乎对伪逆特别不利,这是我最关心的一个…而且,这是一个语言相关的问题吗?例如,它还会出现在Matlab中吗?我不知道有什么方法可以轻松地修改高阶多项式回归,使其在数值上稳定,无论是在Matlab、python还是其他语言中。你能做的是使用性能更好的基函数,例如截断的傅里叶级数。如果我用GD或SGD训练多项式模型,如果我将模型限制在
[-1,1]
中,我会有同样的数值错误吗?或者这只是(伪)反转矩阵的特殊情况吗?作为一个有趣的附带问题,如果我用GD或SGD训练多项式模型,如果我将我的模型限制在[-1,1]
中,我会有同样的数值错误吗?或者这只是(伪)反转矩阵的特殊情况?另一个后续问题。有人多次建议我将间隔改为,[-5,5]
。然而,现在我的问题是,为什么没有出现相反的问题,然后我们得到的不是1.0+eps=1.0
,而是1.0+big_number=NaN
?如果big\u number=number^30
?比如,当一个数量级小于1的数字被提升到30次方时,为什么数字问题看起来更敏感?