【问题标题】:sparse matrix: Matlab to Python code conversion稀疏矩阵:Matlab 到 Python 代码的转换
【发布时间】:2018-08-12 09:47:22
【问题描述】:

我应该如何将这个从 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)),并在关键点类中访问 size 成员,而不是在 matlab 中访问 frames[3],但这些都是微小的变化。

我不确定的是,我究竟应该如何处理 scales 创建和索引访问。我似乎错过了什么,但找不到什么。

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

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


据我了解,Matlab 代码采用稀疏矩阵,创建一个列向量 (scales),然后填充该列向量,以便 frame 中的任何索引 (x,y)(即每帧的索引 (=@987654336 @ 在我的 Python 代码中))并在所述索引处插入一个新值(该值是 sizeframe(3))。看起来很简单,但我不知道我哪里出错了。

任何帮助将不胜感激,谢谢:)

【问题讨论】:

  • np.zeros((n, 1)) 创建一个列向量/数组。或者稍后使用reshapescales[:, np.newaxis] 添加第二个维度。
  • 我不确定在这种情况下尺寸应该是多少。 matlab代码不是创建列向量,这正是我正在做的吗?
  • np.zeros(n] 是 1d,不是列向量
  • 所以你的意思是我只需要添加`,1`?

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


【解决方案1】:

问题是 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.]))

【讨论】:

    猜你喜欢
    • 2017-07-02
    • 2022-08-18
    • 2023-04-10
    • 2012-06-20
    • 2019-11-14
    • 2021-11-25
    • 1970-01-01
    • 2011-10-11
    • 1970-01-01
    相关资源
    最近更新 更多