我正在尝试加载之前保存的稀疏数组。保存稀疏数组非常简单。然而,尝试阅读它是一件痛苦的事情。scipy.load在我的稀疏数组周围返回一个0d数组。
import scipy as sp
A = sp.load("my_array"); A
array(<325729x325729 sparse matrix of type '<type 'numpy.int8'>'
with 1497134 stored elements in Compressed Sparse Row format>, dtype=object)为了得到一个稀疏矩阵,我必须展平0d数组,或者使用sp.asarray(A)。这似乎是一种很难做的事情。Scipy是否足够聪明,能够理解它加载了一个稀疏数组?有没有更好的加载稀疏数组的方法?
发布于 2011-06-09 02:53:13
scipy.io中的mmwrite/mmread函数可以保存/加载矩阵市场格式的稀疏矩阵。
scipy.io.mmwrite('/tmp/my_array',x)
scipy.io.mmread('/tmp/my_array').tolil() mmwrite和mmread可能就是您所需要的。它经过了良好的测试,并使用了一种众所周知的格式。
但是,以下操作可能会更快一些:
我们可以将行和列的坐标和数据保存为npz格式的一维数组。
import random
import scipy.sparse as sparse
import scipy.io
import numpy as np
def save_sparse_matrix(filename,x):
x_coo=x.tocoo()
row=x_coo.row
col=x_coo.col
data=x_coo.data
shape=x_coo.shape
np.savez(filename,row=row,col=col,data=data,shape=shape)
def load_sparse_matrix(filename):
y=np.load(filename)
z=sparse.coo_matrix((y['data'],(y['row'],y['col'])),shape=y['shape'])
return z
N=20000
x = sparse.lil_matrix( (N,N) )
for i in xrange(N):
x[random.randint(0,N-1),random.randint(0,N-1)]=random.randint(1,100)
save_sparse_matrix('/tmp/my_array',x)
load_sparse_matrix('/tmp/my_array.npz').tolil()下面的代码表明,在npz文件中保存稀疏矩阵可能比使用mmwrite/mmread更快:
def using_np_savez():
save_sparse_matrix('/tmp/my_array',x)
return load_sparse_matrix('/tmp/my_array.npz').tolil()
def using_mm():
scipy.io.mmwrite('/tmp/my_array',x)
return scipy.io.mmread('/tmp/my_array').tolil()
if __name__=='__main__':
for func in (using_np_savez,using_mm):
y=func()
print(repr(y))
assert(x.shape==y.shape)
assert(x.dtype==y.dtype)
assert(x.__class__==y.__class__)
assert(np.allclose(x.todense(),y.todense()))收益率
% python -mtimeit -s'import test' 'test.using_mm()'
10 loops, best of 3: 380 msec per loop
% python -mtimeit -s'import test' 'test.using_np_savez()'
10 loops, best of 3: 116 msec per loop发布于 2015-03-26 00:48:44
可以使用()作为索引来提取隐藏在0d数组中的对象:
A = sp.load("my_array")[()]这看起来很奇怪,但它似乎无论如何都可以工作,而且它是一个非常短的变通方法。
发布于 2015-03-26 06:22:52
对于mmwrite答案的所有票数,我很惊讶没有人试图回答真正的问题。但是因为它已经被重新激活了,所以我会试一试。
这将重现OP案例:
In [90]: x=sparse.csr_matrix(np.arange(10).reshape(2,5))
In [91]: np.save('save_sparse.npy',x)
In [92]: X=np.load('save_sparse.npy')
In [95]: X
Out[95]:
array(<2x5 sparse matrix of type '<type 'numpy.int32'>'
with 9 stored elements in Compressed Sparse Row format>, dtype=object)
In [96]: X[()].A
Out[96]:
array([[0, 1, 2, 3, 4],
[5, 6, 7, 8, 9]])
In [93]: X[()].A
Out[93]:
array([[0, 1, 2, 3, 4],
[5, 6, 7, 8, 9]])
In [94]: x
Out[94]:
<2x5 sparse matrix of type '<type 'numpy.int32'>'
with 9 stored elements in Compressed Sparse Row formatUser4713166给我们的[()]并不是提取稀疏数组的“硬方法”。
np.save和np.load是为在ndarray上运行而设计的。但是稀疏矩阵不是这样的数组,也不是子类(就像np.matrix那样)。看起来,np.save将非数组对象包装在object dtype array中,并将其与对象的酸洗形式一起保存。
当我尝试保存不同类型的对象时,我在以下位置收到错误消息:
403 # We contain Python objects so we cannot write out the data directly.
404 # Instead, we will pickle it out with version 2 of the pickle protocol.--> 405Array(pickle.dump,fp,protocol=2)
因此,对于Is Scipy smart enough to understand that it has loaded a sparse array?,答案是否定的。np.load不知道稀疏数组。但是,当给定不是数组的对象时,np.save足够聪明,并且np.load可以用它在文件中找到的东西做它能做的事情。
对于存储和加载稀疏数组的替代方法,已经提到了io.savemat,MATLAB兼容方法。这将是我的第一选择。但是这个例子也展示了你可以使用常规的Python pickling。如果您需要保存特定的稀疏格式,这可能会更好。如果您能接受[()]提取步骤,那么np.save也不错。:)
https://github.com/scipy/scipy/blob/master/scipy/io/matlab/mio5.py write_sparse - sparse以csc格式保存。除了头文件,它还可以保存A.indices.astype('i4'))、A.indptr.astype('i4'))、A.data.real和可选的A.data.imag。
在快速测试中,我发现np.save/load可以处理除dok之外的所有稀疏格式,load会报告缺少shape。否则,我在稀疏文件中找不到任何特殊的酸洗代码。
https://stackoverflow.com/questions/6282432
复制相似问题