稀疏矩阵:Matlab到Python代码转换

时间:2018-03-04 18:04:57

标签: python python-2.7 matlab numpy sparse-matrix

我应该如何将它从Matlab转换为Python:

A = sparse(row_idx, col_idx, values, len, s1 * s2);
scales = zeros(size(A, 1), 1);
scales(sub2ind([s1 s2], floor(frames(2, :)), floor(frames(1, :)))) = ...
    frames(3, :);
eq = A \ scales;

我的尝试是:

from scipy.sparse import csr_matrix # to replace sparse matrix
import numpy as np # to replace \ with np.linalg.lstsq
A = csr_matrix((values, (row_idx , col_idx )), shape=(length, width * height))
scales = np.zeros((A.shape[0]));
for kp in kps:
   x,y = int(kp.pt[0]), int(kp.pt[1])
   scales[y][x] = int(kp.size) # error
   scales[y*x] = int(kp.size) # again, error:(
...
eq = np.linalg.lstsq(A, scales)

我更改了变量名称(len -> length(s1,s2) -> (width, height)),并在matlab中访问了关键点类中的size成员而不是frames[3],但这些都是微小的变化。< / p>

我不确定的是,我应该如何处理scales创建和索引访问。我似乎错过了一些东西但却无法找到。

我得到TypeError: 'numpy.float64' object does not support item assignment并不会让我感到惊讶,因为scales是1-dim数组,我不应该使用[][]访问它。

但是,将其更改为scales[y*x] = int(kp.size)会引发以下情况:LinAlgError: 0-dimensional array given. Array must be two-dimensional

根据我的理解,Matlab代码采用稀疏矩阵,创建一个列向量(scales),然后填充,以便来自(x,y)的任何索引frame(即索引)每个帧(在我的Python代码中= keypoint))并在所述索引处插入一个新值(size的值为frame(3))。似乎很容易,但我不知道我哪里出错了。

非常感谢任何帮助,谢谢:)

1 个答案:

答案 0 :(得分:2)

问题是np.linalg.lstsqr是一个numpy函数,并不了解稀疏矩阵。 Numpy函数如果将作业委托给方法,则会起作用,但如果它们首先尝试将稀疏矩阵转换为数组则不行。

举个简单的例子:

In [345]: R = np.arange(1,6)
In [346]: M = sparse.csr_matrix(([1,1,1],([0,2,4],[0,1,2])),shape=(5,3))
In [347]: M.A
Out[347]: 
array([[1, 0, 0],
       [0, 0, 0],
       [0, 1, 0],
       [0, 0, 0],
       [0, 0, 1]], dtype=int64)

In [348]: np.linalg.lstsq(M,R, rcond=None)
   ...
-> 1977     _assertRank2(a, b)
   1978     _assertNoEmpty2d(a, b)  # TODO: relax this constraint
   1979     m  = a.shape[0]

/usr/local/lib/python3.6/dist-packages/numpy/linalg/linalg.py in _assertRank2(*arrays)
    193         if a.ndim != 2:
  ....
LinAlgError: 0-dimensional array given. Array must be two-dimensional

它认为M的维度是0-d,而不是2-d。那是因为,当用np.array(或`asarray)包装时,稀疏矩阵会产生一个0d对象数组:

In [351]: np.array(M)
Out[351]: 
array(<5x3 sparse matrix of type '<class 'numpy.int64'>'
    with 3 stored elements in Compressed Sparse Row format>, dtype=object)
In [352]: _.shape
Out[352]: ()

正确的方法是使用自己的方法将稀疏矩阵变为密集:

In [354]: np.linalg.lstsq(M.A,R, rcond=None)
....
Out[354]: (array([1., 3., 5.]), array([20.]), 3, array([1., 1., 1.]))

在MATLAB中,稀疏矩阵被集成到主代码中。在numpy中,它们位于单独的scipy.sparse包中。稀疏矩阵不是np.ndarray的子类。

有一个稀疏的线性代数子包:

In [355]: from scipy.sparse import linalg as spla
In [356]: spla.lsqr(M, R)
Out[356]: 
(array([1., 3., 5.]),
 2,
 1,
 4.47213595499958,
 4.47213595499958,
 1.0,
 1.0,
 4.082652109348718e-16,
 5.916079783099617,
 array([0., 0., 0.]))