numpy - 为什么我不能将数据分配给第一个 "try:"中的稀疏矩阵的一部分?

标签 numpy scipy sparse-matrix

我想为 crs 稀疏矩阵的一部分赋值(我知道它很昂贵,但在我的项目中无关紧要)。
我试图为稀疏矩阵的一部分分配一个浮点变量,但第一次不起作用。但是,如果我在“除外”中做完全相同的事情,它将完美无缺地工作。

然后我尝试检查稀疏矩阵的 dtype 和它的一部分,由于某种原因它们是不同的。整个矩阵的数据类型是我指定的 float16,但矩阵的一部分具有 float32 dtype。

这是两个问题的一个小例子:

from scipy.sparse import csr_matrix
import numpy as np

frame = csr_matrix((10, 10),dtype=np.float16)

print "================\n================ Part 1\n================"
print "Let's assign a value to part of the sparse matrix:"
try:
    frame[0:3,0:3] = np.float16(0.6)
    print "The first attempt worked!"
except:
    print "The first attempt didn't work"

print "let's try again :"

try:
    frame[0:3,0:3] = np.float16(0.6)
    print "The second attempt worked!"
except:
    print "The second attempt didn't work"

print "================\n================ Part 2\n================"
print "Let's check the datatype:"
print "Frame dtype is:",; print frame.dtype
print "Part-of-frame dtype is",; print frame[0:3,0:3].dtype

结果如下:
================
================ Part 1
================
Let's assign a value to part of the sparse matrix:
The first attempt didn't work
let's try again :
The second attempt worked!
================
================ Part 2
================
Let's check the datatype:
Frame dtype is: float16
Part-of-frame dtype is float32

我仍然尝试将 np.float32 分配给稀疏矩阵的一部分,并且我得到了相同的行为。有人可以解释发生了什么吗?

最佳答案

简短回答 - 问题出在 np.float16 ;坚持使用通常 32 或 64 个浮点数。

================================

首先是一个工作案例(在 0.17 中)

In [334]: M=sparse.csr_matrix((5,5),dtype=np.float)
In [335]: M[:3,:3]=0.6
/usr/lib/python3/dist-packages/scipy/sparse/compressed.py:730: SparseEfficiencyWarning: Changing the sparsity structure of a csr_matrix is expensive. lil_matrix is more efficient.
  SparseEfficiencyWarning)
In [336]: M.A
Out[336]: 
array([[ 0.6,  0.6,  0.6,  0. ,  0. ],
       [ 0.6,  0.6,  0.6,  0. ,  0. ],
       [ 0.6,  0.6,  0.6,  0. ,  0. ],
       [ 0. ,  0. ,  0. ,  0. ,  0. ],
       [ 0. ,  0. ,  0. ,  0. ,  0. ]])
In [338]: M.data
Out[338]: array([ 0.6,  0.6,  0.6,  0.6,  0.6,  0.6,  0.6,  0.6,  0.6])

如果我再次分配,则不会收到稀疏警告。

现在,如果我使用您的 dtype,我会收到稀疏警告,但也会收到 ValueError(您的通用 except 隐藏了该警告):
In [339]: M=sparse.csr_matrix((5,5),dtype=np.float16)
In [340]: M[:3,:3]=np.float16(0.6)
/usr/lib/python3/dist-packages/scipy/sparse/compressed.py:730: SparseEfficiencyWarning: Changing the sparsity structure of a csr_matrix is expensive. lil_matrix is more efficient.
  SparseEfficiencyWarning)
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-340-aaecba748069> in <module>()
----> 1 M[:3,:3]=np.float16(0.6)

/usr/lib/python3/dist-packages/scipy/sparse/compressed.py in __setitem__(self, index, x)
    654             return
    655         i, j = self._swap((i.ravel(), j.ravel()))
--> 656         self._set_many(i, j, x.ravel())
    657 
    658     def _setdiag(self, values, k):

/usr/lib/python3/dist-packages/scipy/sparse/compressed.py in _set_many(self, i, j, x)
    738             j = j[mask]
    739             j[j < 0] += N
--> 740             self._insert_many(i, j, x[mask])
    741 
    742     def _insert_many(self, i, j, x):

/usr/lib/python3/dist-packages/scipy/sparse/compressed.py in _insert_many(self, i, j, x)
    805             # TODO: only sort where necessary
    806             self.has_sorted_indices = False
--> 807             self.sort_indices()
    808 
    809         self.check_format(full_check=False)

/usr/lib/python3/dist-packages/scipy/sparse/compressed.py in sort_indices(self)
   1039         if not self.has_sorted_indices:
   1040             fn = _sparsetools.csr_sort_indices
-> 1041             fn(len(self.indptr) - 1, self.indptr, self.indices, self.data)
   1042             self.has_sorted_indices = True
   1043 

ValueError: Output dtype not compatible with inputs.

如果我只是尝试转换 csr,我会得到同样的错误致密:
In [346]: M=sparse.csr_matrix((5,5),dtype=np.float16)
In [347]: M.A
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-347-bdd665fbe1b0> in <module>()
----> 1 M.A

/usr/lib/python3/dist-packages/scipy/sparse/base.py in __getattr__(self, attr)
    511     def __getattr__(self, attr):
    512         if attr == 'A':
--> 513             return self.toarray()
    514         elif attr == 'T':
    515             return self.transpose()

/usr/lib/python3/dist-packages/scipy/sparse/compressed.py in toarray(self, order, out)
    938     def toarray(self, order=None, out=None):
    939         """See the docstring for `spmatrix.toarray`."""
--> 940         return self.tocoo(copy=False).toarray(order=order, out=out)
    941 
    942     ...
ValueError: Output dtype not compatible with inputs.

所以问题不在于赋值,而在于处理 dtype .它看起来像一个错误,但您可以通过不使用此 dtype 来避免它。

lil matrix 也有这个 dtype 的问题:
In [348]: M=sparse.lil_matrix((5,5),dtype=np.float16)
In [349]: M[:3,:3]=np.float16(0.6)
...
KeyError: (dtype('int32'), dtype('float16'))

在转换的某个时刻,指定的 dtype 没有被保留。

但是为什么要使用 float16首先? float32 和 float64 是正常的 numpy 浮点数。

即使我成功创建了一个 np.float16矩阵,在大多数稀疏操作期间不保留该数据类型:
In [374]: M=sparse.csr_matrix(np.arange(9).reshape(3,3), dtype=np.float16)
In [375]: M.data
Out[375]: array([ 1.,  2.,  3.,  4.,  5.,  6.,  7.,  8.], dtype=float16)
In [376]: 
In [376]: M
Out[376]: 
<3x3 sparse matrix of type '<class 'numpy.float16'>'
    with 8 stored elements in Compressed Sparse Row format>

In [377]: M.A   # same error converting to dense
...
ValueError: Output dtype not compatible with inputs.

In [378]: M.T     # dtype kept during transpose
Out[378]: 
<3x3 sparse matrix of type '<class 'numpy.float16'>'
    with 8 stored elements in Compressed Sparse Column format>

dtype 不保留乘法或索引。很可能编译的矩阵乘法代码是为 32 和 64(常规 C 浮点数和 double 数)而不是 16 编写的。
In [379]: M*M
Out[379]: 
<3x3 sparse matrix of type '<class 'numpy.float32'>'
    with 9 stored elements in Compressed Sparse Row format>
In [380]: M[0,:]
Out[380]: 
<1x3 sparse matrix of type '<class 'numpy.float32'>'
    with 2 stored elements in Compressed Sparse Row format>

我不知道文档是否警告 float16 ,但我认为它几乎没用。

关于numpy - 为什么我不能将数据分配给第一个 "try:"中的稀疏矩阵的一部分?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40046118/

相关文章:

python - numba 类型与 nd 过滤器匹配

python - pandas 在两行索引之间填充值(行仅通过值查找)

python - 向量化结果添加到 numpy 数组

python - 如何根据设置值创建均匀分布的 Numpy 数组

python - scikit-learn MinMax 缩放器无法缩放

python - 获取scipy的gmres迭代方法的迭代次数

python - 将整数列表拆分为 bin,保留索引

Python/Scipy : Find "bounded" min/max of a matrix

python - 稀疏矩阵上 hstack 的类型错误

r - 如何在大型稀疏矩阵中组合具有相同名称的列