用于python广义奇异值分解的GSVD

时间:2016-06-14 13:52:02

标签: python python-3.x numpy scipy

MATLAB有一个gsvd函数来执行广义SVD。自2013年以来,我认为关于github pages关于将其置于scipy中的问题进行了大量讨论,有些页面有我可以使用的代码,例如here,对于像我这样的新手来说这是非常复杂的(对于让它运行)。

我还找到了implementation的LJWilliams github页面。这很不好,因为转移到python 3时有很多错误。尝试纠正断言和打印等简单的错误。它很快变得复杂。

有人可以帮我使用python的gsvd代码或告诉我如何使用在线的吗?

此外,一旦打印和断言语句得到纠正,这就是我在LJWilliams实现中得到的结果。代码看起来很复杂,我不确定花时间做它是最好的事情!还有一些人报告了同一个github页面上的问题,我不确定它是固定还是已连接。

n = 10
m = 6
p = 6

A = np.random.rand(m,n)
B = np.random.rand(p,n)
gsvd(A,B)
  

文件“/home/eghx/agent18/master_thesis/AMfe/amfe/gsvd.py”,第260行,   在gsvd       U,V,Z,C,S = csd(Q [0:m,:],Q [m:m + n,:])

     

文件“/home/eghx/agent18/master_thesis/AMfe/amfe/gsvd.py”,第107行,   在csd       Q,R = scipy.linalg.qr(S [q:n,m:p])

     

文件   “/home/eghx/anaconda3/lib/python3.5/site-packages/scipy/linalg/decomp_qr.py”   第141行,第2行       overwrite_a = overwrite_a)

     

文件   “/home/eghx/anaconda3/lib/python3.5/site-packages/scipy/linalg/decomp_qr.py”   第19行,在safecall       ret = f(* args,** kwargs)

     

ValueError:无法创建意图(缓存|隐藏)|可选数组 - 必须   定义了尺寸但得到了(0,)

1 个答案:

答案 0 :(得分:4)

如果你想在github上使用LJWillams实现,那就有一些bug。但是,要完全理解这项技术,我可能会建议您自己去实施它。我查看了Octave(相当于MATLAB的免费软件)和他们的"code is a wrapper to the corresponding Lapack dggsvd and zggsvd routines.",这是scipy应该做的事情。

我会发布我发现的错误,但我不打算将代码发布到完整的工作状态,因为我不确定版权方面的代码是什么,因为受版权保护的MATLAB实现,用于翻译它。

警告 :我不是广义SVD的专家,只是从调试的角度来看这个问题,而不是基础算法是否正确。我已经在你的原始随机数组和Python文件中已经存在的测试用例上工作了。

错误

设置k

在第63行附近,设置k的条件和对numpy.argparse的误解(特别是与MATLAB' s find相比)似乎设置了k错误在某些情况下。将该代码更改为

if q == 1:
    k = 0
elif m < p:
    k = n;
else:
    k = max([0,sum((np.diag(C) <= 1/np.sqrt(2)))])

第79行

S [1,1]应该是S [0,0],我认为(Python 0索引数组)

第83行

这里的numpy矩阵切片似乎错了。我通过将第83-95行改为:

来获得代码
    UT, ST, VT = scipy.linalg.svd(slice_matrix(S,i,j))
    ST = add_zeros(ST,np.zeros([n-k,r-k]))

    if k > 0: 
        print('Zeroing elements of S in row indices > r, to be replaced by ST')
        S[0:k,k:r] = 0
    S[k:n,k:r] = ST
    C[:,j] = np.dot(C[:,j],VT)
    V[:,i] = np.dot(V[:,i],UT)
    Z[:,j] = np.dot(Z[:,j],VT)
    i = np.arange(k,q)
    Q,R = scipy.linalg.qr(C[k:q,k:r])

    C[i,j] = np.diag(diagf(R))
    U[:,k:q] = np.dot(U[:,k:q],Q)
<{1}} 中的

使用diagp()的两个矩阵乘法应该是X*Y而是np.dot(X,Y)中的* element-wise multiplication,而不是矩阵乘法。)