【问题标题】:Python: L1-norm of a sparse non-square matrixPython:稀疏非方阵的 L1 范数
【发布时间】:2014-11-06 13:59:46
【问题描述】:

我在尝试计算稀疏矩阵的 1 范数时遇到了一个问题。我正在使用函数scipy.sparse.linalg.onenormest,但它给了我一个错误,因为运算符只能作用于方阵。

这里是一个代码示例:

from scipy import sparse

row = array([0,2,2,0,1,2])
col = array([0,0,1,2,2,2])
data = array([1,2,3,4,5,6])

A = sparse.csc_matrix( (data,(row,col)), shape=(5,3) )

onenormest(A)

这是错误:

Traceback (most recent call last):
  File "<ipython console>", line 1, in <module>
  File "C:\Python27\lib\site-packages\scipy\sparse\linalg\_onenormest.py", line 76, in onenormest
    raise ValueError('expected the operator to act like a square matrix')
ValueError: expected the operator to act like a square matrix

如果我将 A 定义为方阵,则运算符 onenormest 可以工作,但这不是我想要的。

有人知道如何计算稀疏非方阵的一范数吗?

【问题讨论】:

  • 你真的想要L^1-norm吗?我不知道1-norm 是什么。
  • 没错,所以在这个例子中,L1-norm 必须是 15
  • 不是说应该是21吗?
  • 其实我想复制 Matlab norm(X,p) 函数。其中 X 是我的稀疏矩阵,p = 1。Matlab 给出的结果是 15。基本上是 X 的所有列中最高的 L1 范数。

标签: python matrix scipy sparse-matrix norm


【解决方案1】:

我认为你想要numpy.linalg.norm

from numpy import linalg
from scipy import sparse


row = array([0,2,2,0,1,2])
col = array([0,0,1,2,2,2])
data = array([1,2,3,4,5,6])

A = sparse.csc_matrix( (data,(row,col)), shape=(5,3) )

print linalg.norm(A.todense(), ord=1) #15

调用 A.data 不起作用,因为稀疏矩阵对象的 .data 只是数据 - 它显示为向量。

如果你的稀疏矩阵很小,那么这很好。如果它很大,那么显然这是一个问题。在这种情况下,您可以编写自己的例程。

如果您只对L^1-norm 感兴趣,并且无法进行密集转换,那么您可以通过以下方式进行:

def sparseL1Norm = lambda A: max([numpy.abs(A).getcol(i).sum() for i in range(A.shape[1])])

【讨论】:

  • 感谢您的回答。我试过了,但运算符规范不适用于稀疏矩阵。
  • 仅供参考,我强烈怀疑@unutbu 的np.abs(A).sum(axis=0).max() 会表现更好,尤其是对于大型矩阵。
【解决方案2】:

这会找到每列的 L1 范数:

from scipy import sparse
import numpy as np

row = np.array([0,2,2,0,1,2])
col = np.array([0,0,1,2,2,2])
data = np.array([1,2,3,-4,-5,-6]) # made negative to exercise abs
A = sparse.csc_matrix( (data,(row,col)), shape=(5,3) )
print(abs(A).sum(axis=0))

产量

[[ 3  3 15]]

然后你可以取最大值来找到矩阵的 L1 范数:

print(abs(A).sum(axis=0).max())
# 15

abs(A) 是一个稀疏矩阵:

In [29]: abs(A)
Out[29]: 
<5x3 sparse matrix of type '<type 'numpy.int64'>'
    with 6 stored elements in Compressed Sparse Column format>

summax 是稀疏矩阵的方法,所以abs(A).sum(axis=0).max() 计算L1 范数而不致密矩阵。

注意:大多数 NumPy 函数(例如 np.abs)并非设计用于处理稀疏矩阵。尽管np.abs(A) 返回了正确的结果,但它是通过间接路径到达那里的。更直接的方法是使用abs(A),它调用A.__abs__()Thanks to pv. 指出这一点。

【讨论】:

  • 谢谢!这似乎有效。但是我想要的是 Matlab norm(X,p) 函数的相同行为,结果是 15。15 是 A 的第三列的 L1 范数,这是更高的 L1 范数(第一列norm = 4,第二列 norm = 3,第三列 norm = 15)
  • 这不起作用,因为稀疏矩阵的A.data 只是[1 2 3 4 5 6]
  • 是的。所以结果是 21。但是如果例如我定义 A = sparse.csc_matrix( (data,(row,col)), shape=(5,5) ) 然后我计算 onenormest(A) 结果是 15,所以适用于方形稀疏矩阵,但不适用于非方形矩阵:(
  • np.abs(A).sum(axis=0).max() 比我的解决方案更整洁:/
  • 改为使用abs(A).sum(axis=0).max()np.abs 通过一些间接路由调用A.__abs__(),您可以使用pdb.runcall(np.abs, A) 进行验证,而abs(A) 直接调用它。一般来说,目前 Numpy 例程和稀疏矩阵不能一起工作。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-10
  • 1970-01-01
  • 2020-12-01
  • 2013-12-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多