将使用-v7.3(HDF5)格式保存的Matlab稀疏矩阵加载到Python并进行操作

5 投票
3 回答
3757 浏览
提问于 2025-04-17 07:49

我刚开始学Python,之前用的是Matlab。我有一个很大的稀疏矩阵,保存成了Matlab v7.3(HDF5)格式。到目前为止,我找到两种方法可以加载这个文件,一种是用 h5py,另一种是用 tables。不过在加载完之后,对这个矩阵的操作似乎非常慢。例如,在Matlab中:

>> whos     
  Name           Size                   Bytes  Class     Attributes

  M      11337x133338            77124408  double    sparse    

>> tic, sum(M(:)); toc
Elapsed time is 0.086233 seconds.

使用tables:

t = time.time()
sum(f.root.M.data)
elapsed = time.time() - t
print elapsed
35.929461956

使用h5py:

t = time.time()
sum(f["M"]["data"])
elapsed = time.time() - t
print elapsed

(我等得不耐烦了...)

[编辑]

根据@bpgergo的评论,我应该补充一下,我尝试过把用 h5py 加载的结果(f)转换成 numpy 数组或者 scipy 稀疏数组,方法有这两种:

from scipy import sparse
A = sparse.csc_matrix((f["M"]["data"], f["M"]["ir"], f["tfidf"]["jc"]))

或者

data = numpy.asarray(f["M"]["data"])
ir = numpy.asarray(f["M"]["ir"])
jc = numpy.asarray(f["M"]["jc"])    
    A = sparse.coo_matrix(data, (ir, jc))

但这两种操作也都非常慢。

我是不是漏掉了什么?

3 个回答

0

你缺少NumPy这个库;这里有一个专门为Matlab用户准备的指南。

2

最后的答案留给后人:

import tables, warnings
from scipy import sparse

def load_sparse_matrix(fname) :
    warnings.simplefilter("ignore", UserWarning) 
    f = tables.openFile(fname)
    M = sparse.csc_matrix( (f.root.M.data[...], f.root.M.ir[...], f.root.M.jc[...]) )
    f.close()
    return M
3

你遇到的问题主要是因为你在使用 Python 的 sum 函数处理一个实际上是存储在硬盘上的数组(也就是说,它并不在内存里)。

首先,你是在比较从硬盘读取数据的时间和从内存读取数据的时间。如果你想和在 Matlab 中的操作进行比较,最好先把这个数组加载到内存中。

其次,Python 自带的 sum 函数对于 numpy 数组来说效率很低。(具体来说,逐个遍历 numpy 数组中的每个元素是非常慢的,而 Python 的 sum 就是这么做的。)对于 numpy 数组,建议使用 numpy.sum(yourarray) 或者 yourarray.sum()

举个例子:

(我使用 h5py,因为我对它更熟悉。)

import h5py
import numpy as np

f = h5py.File('yourfile.hdf', 'r')
dataset = f['/M/data']

# Load the entire array into memory, like you're doing for matlab...
data = np.empty(dataset.shape, dataset.dtype)
dataset.read_direct(data)

print data.sum() #Or alternately, "np.sum(data)"

撰写回答