为什么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=
  • 利用高斯消去法
  • 使用伪逆
  • 据我所知,这些似乎与我认为的基本事实不符

  • 首先,通过将30次多项式拟合为频率为5的余弦来生成真值参数。所以我有了
    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)时误差累积(很多)?老实说,我不知道,但我觉得所有这些假设都很愚蠢。如果有人能发现我的错误,请随意指出。否则,我可能不懂线性代数或其他东西……这更令人担忧

    此外,如果我能得到建议,这将是非常感谢。我是否:

  • 将间隔的大小增加到不小于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次方时,为什么数字问题看起来更敏感?