MATLAB有一个gsvd函数来执行广义SVD。自2013年以来,我认为关于把它放到scipy中的github pages已经有了很多讨论,有些页面有我可以使用的代码,比如here,这对于像我这样的新手来说是非常复杂的(让它运行)。
我还发现LJWilliams github页面有一个implementation。这一点也不好,因为在转移到python 3时有很多bug。尝试更正诸如assert和print之类的简单错误。事情很快变得复杂起来。
有人能帮我做一个python的gsvd代码,或者教我如何使用那些在线的代码吗?
另外,这也是我在LJWilliams实现中得到的结果,一旦print和assert语句被更正。代码看起来很复杂,我不确定花时间在上面是否是最好的选择!还有一些人在同一个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\u thesis/AMfe/AMfe/gsvd.py”,第260行,
在gsvd中
U,V,Z,C,S=csd(Q[0:m,:],Q[m:m+n,:])
文件“/home/eghx/agent18/master\u 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行,单位:qr
覆盖(overwrite)
文件
“/home/eghx/anaconda3/lib/python3.5/site packages/scipy/linalg/decomp_qr.py”,
19号线,安全呼叫
ret=f(*参数,**kwargs)
ValueError:未能创建intent(cache | hide)|可选数组--必须
定义了维度,但得到(0,)
最佳答案
如果您想在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的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号线以后
纽米矩阵在这里切片似乎是错误的。我把第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)
在
diagp()
有两个使用
X*Y
的矩阵乘法应该是np.dot(X,Y)
(注意*
是numpy
中的element-wise multiplication,而不是矩阵乘法。)