Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何减少scipy.sparse.dok_矩阵的存储大小_Python_Python 3.x_Numpy_Scipy_Sparse Matrix - Fatal编程技术网

Python 如何减少scipy.sparse.dok_矩阵的存储大小

Python 如何减少scipy.sparse.dok_矩阵的存储大小,python,python-3.x,numpy,scipy,sparse-matrix,Python,Python 3.x,Numpy,Scipy,Sparse Matrix,我希望使用中间存储格式构建一个稀疏实矩阵,然后将该矩阵转换为存储格式,并使用生成的矩阵执行计算。然而,中间矩阵的大小大大超过了我的估计和可用内存 我的环境 使用numpy 当我构建一个由16位整数组成的20000×20000 numpy数组时,我估计其大小为20000**2*16/8/2**20≈ 763米。根据htopunix工具的报告,该过程的常驻集大小(RSS)为815M,这与我的估计相符 将numpy导入为np n=20000 M=np.one((n,n),dtype=np.uint16

我希望使用中间存储格式构建一个稀疏实矩阵,然后将该矩阵转换为存储格式,并使用生成的矩阵执行计算。然而,中间矩阵的大小大大超过了我的估计和可用内存

我的环境 使用
numpy
当我构建一个由16位整数组成的20000×20000 numpy数组时,我估计其大小为20000**2*16/8/2**20≈ 763米。根据
htop
unix工具的报告,该过程的常驻集大小(RSS)为815M,这与我的估计相符

将numpy导入为np
n=20000
M=np.one((n,n),dtype=np.uint16)
使用
dict
当我使用16位整数作为键和值构建一个20000×20000
scipy.sparse.dok_矩阵时,我估计大小为20000**2*(16*3)/8/2**30≈ 2.24G加上哈希表的一些小开销。然而,这个过程的RSS为66.4G,这表明我在估计中犯了一个严重错误

将numpy导入为np
n=20000
M=dict()
对于范围(n)中的i:
i=np.uint16(i)
对于范围(n)内的j:
j=np.uint16(j)
M[(i,j)]=np.uint16(1)
使用
scipy.sparse.dok_矩阵
当我构建一个20000×20000
scipy.sparse.dok_矩阵时,使用16位整数作为键和值,如下所示,我估计大小将再次为20000**2*(16*3)/8/2**30≈ 2.24G加上哈希表的一些小开销。然而,这个过程的RSS为81.3G,这比我估计的dict例子还要远

从scipy.sparse导入dok_矩阵
将numpy作为np导入
n=20000
M=dok_矩阵((n,n),dtype=np.uint16)
对于范围(n)中的i:
i=np.uint16(i)
对于范围(n)内的j:
j=np.uint16(j)
M[i,j]=1

虽然您可以控制
dok
数据
值的
数据类型
,但无法控制密钥存储

查看
dok_矩阵
类别代码:

def __setitem__(self, index, x):
   ...
   v = np.asarray(x, dtype=self.dtype)
   ...
   dict.__setitem__(self, (int(i), int(j)), v[()])
因此,元素存储为所选
dtype
的numpy“标量”对象:

In [129]: M = sparse.dok_matrix((10,10), dtype=np.uint16)
In [130]: M[0,0] = 1
In [131]: list(M.items())
Out[131]: [((0, 0), 1)]
In [132]: type(_[0][1])
Out[132]: numpy.uint16
我对Python dict存储了解不够,无法估计哈希表所需的内存。我不认为实际的索引元组存储在任何地方,只是它们的散列

最近的另一个问题试图使用
sys.getsizeof
比较数组和列表的内存使用情况。在这个dok上使用它:

In [133]: sys.getsizeof(M)     # 1 item
Out[133]: 256
In [134]: for i in range(10):
     ...:     for j in range(10):
     ...:         M[i,j]=1
     ...:         
In [135]: sys.getsizeof(M)     # full
Out[135]: 4720
对于列表,
getsizeof
仅捕获对象开销和指针缓冲区。我不知道它用字典捕捉到了什么。也许只是散列表。数据值存储在内存中的其他位置:

In [136]: sys.getsizeof(Out[131][0][1])
Out[136]: 26
In [137]: M.nnz
Out[137]: 100
In [138]: 26*M.nnz
Out[138]: 2600
其他稀疏格式的存储更容易估计
coo
csr
使用3个numpy数组。索引数组根据矩阵的维数存储为
int32
int64


为了粗略估计内存使用情况,我将各种格式写入文件:

In [164]: np.save('Mdense',M.A)
In [165]: sparse.save_npz('Mcsr',M.tocsr())
In [166]: sparse.save_npz('Mcoo',M.tocoo())

In [179]: f = open('Mdok',mode='wb')
In [180]: pickle.Pickler(f).dump(M)
In [181]: f.close()

In [182]: ll M*
-rw-rw-r-- 1 paul  900 Apr 16 11:53 Mcoo.npz
-rw-rw-r-- 1 paul  911 Apr 16 11:53 Mcsr.npz
-rw-rw-r-- 1 paul  328 Apr 16 11:53 Mdense.npy
-rw-rw-r-- 1 paul 3023 Apr 16 11:57 Mdok
由于
M
已满,因此稀疏
coo
格式将占用密集数组的3倍空间
coo
对于
数据
中的每一个都有一个100元素的数组
csr
试图压缩
数组,但差异并不总是那么显著


对于
dok
,我不得不使用
pickle
sparse.save_npz
不处理
dok

当您可以控制
dok
数据
值的
类型时,您无法控制密钥存储

查看
dok_矩阵
类别代码:

def __setitem__(self, index, x):
   ...
   v = np.asarray(x, dtype=self.dtype)
   ...
   dict.__setitem__(self, (int(i), int(j)), v[()])
因此,元素存储为所选
dtype
的numpy“标量”对象:

In [129]: M = sparse.dok_matrix((10,10), dtype=np.uint16)
In [130]: M[0,0] = 1
In [131]: list(M.items())
Out[131]: [((0, 0), 1)]
In [132]: type(_[0][1])
Out[132]: numpy.uint16
我对Python dict存储了解不够,无法估计哈希表所需的内存。我不认为实际的索引元组存储在任何地方,只是它们的散列

最近的另一个问题试图使用
sys.getsizeof
比较数组和列表的内存使用情况。在这个dok上使用它:

In [133]: sys.getsizeof(M)     # 1 item
Out[133]: 256
In [134]: for i in range(10):
     ...:     for j in range(10):
     ...:         M[i,j]=1
     ...:         
In [135]: sys.getsizeof(M)     # full
Out[135]: 4720
对于列表,
getsizeof
仅捕获对象开销和指针缓冲区。我不知道它用字典捕捉到了什么。也许只是散列表。数据值存储在内存中的其他位置:

In [136]: sys.getsizeof(Out[131][0][1])
Out[136]: 26
In [137]: M.nnz
Out[137]: 100
In [138]: 26*M.nnz
Out[138]: 2600
其他稀疏格式的存储更容易估计
coo
csr
使用3个numpy数组。索引数组根据矩阵的维数存储为
int32
int64


为了粗略估计内存使用情况,我将各种格式写入文件:

In [164]: np.save('Mdense',M.A)
In [165]: sparse.save_npz('Mcsr',M.tocsr())
In [166]: sparse.save_npz('Mcoo',M.tocoo())

In [179]: f = open('Mdok',mode='wb')
In [180]: pickle.Pickler(f).dump(M)
In [181]: f.close()

In [182]: ll M*
-rw-rw-r-- 1 paul  900 Apr 16 11:53 Mcoo.npz
-rw-rw-r-- 1 paul  911 Apr 16 11:53 Mcsr.npz
-rw-rw-r-- 1 paul  328 Apr 16 11:53 Mdense.npy
-rw-rw-r-- 1 paul 3023 Apr 16 11:57 Mdok
由于
M
已满,因此稀疏
coo
格式将占用密集数组的3倍空间
coo
对于
数据
中的每一个都有一个100元素的数组
csr
试图压缩
数组,但差异并不总是那么显著


对于
dok
,我不得不使用
pickle
<代码>稀疏。save_npz
不处理
dok

解释您的估计值不清楚的地方?请明确说明您的问题。我会说它可能是“我如何使一个
dok_矩阵
小于一个常规的非稀疏矩阵,甚至一个dict?”它不可能真的小于一个非稀疏矩阵。但是,我更希望包含相同数据的稀疏矩阵不是100倍大。请解释您的估计值。什么不清楚?请明确说明您的问题。我会说它可能是“我如何使一个
dok_矩阵
小于一个常规的非稀疏矩阵,甚至一个dict?”它不可能真的小于一个非稀疏矩阵。但是,我更希望包含相同数据的稀疏矩阵不是100倍大