Python int8 scipy稀疏矩阵创建错误创建int64结构?

Python int8 scipy稀疏矩阵创建错误创建int64结构?,python,python-3.x,numpy,matrix,scipy,Python,Python 3.x,Numpy,Matrix,Scipy,我一直在尝试使用scipy.sparse创建一个非常大的方形矩阵,其中左下半部分为零,右上半部分为一。我使用了dtypeint8来表示每个元素(看起来使用布尔值会导致8位存储,所以使用它没有意义) 对于相当大的矩阵(比如16300x16300),下面描述的两种方法都很有效 为此,我尝试了各种方法来创建一个,然后使用triu创建一个三角形 问题是,当我尝试生成一个数组(比如522659x522659)时,这些数组被正确创建,但是triu失败,出现以下错误 注意我有750gb的内存,其中4gb在执行

我一直在尝试使用scipy.sparse创建一个非常大的方形矩阵,其中左下半部分为零,右上半部分为一。我使用了dtype
int8
来表示每个元素(看起来使用布尔值会导致8位存储,所以使用它没有意义)

对于相当大的矩阵(比如16300x16300),下面描述的两种方法都很有效

为此,我尝试了各种方法来创建一个,然后使用
triu
创建一个三角形

问题是,当我尝试生成一个数组(比如522659x522659)时,这些数组被正确创建,但是
triu
失败,出现以下错误

注意我有750gb的内存,其中4gb在执行前使用。所以内存错误是真的,因为我无法创建2或4tb的数组!但问题是,我不需要像这样大小的分配来将我想要的数字存储为单个字节

我的问题是:

  • 为什么这两种方法都试图构造
    int64
    类型的对象,而我已经将
    int8
    类型的数据提供给它
  • 如果我有足够的内存,如何创建522659x522659矩阵
  • 尝试1:

    内存使用峰值约为260gb—这很有意义,因为这会在只占用上半部分之前创建522659*522659=273172430281个内存。因此,它的效率很低,因为它生成的值是需要的两倍,但是错误发生在调用
    scipy.sparse.triu
    的过程中,而不是在生成值的过程中

    Python 3.5.4 (default, Sep 27 2019, 09:11:05) 
    [GCC 7.4.0] on linux
    
    numpy==1.18.0
    scipy==1.4.1
    
    尝试2:

    这一次创建的内存占用约134gb,但当将这些内存添加到矩阵中时,内存使用量将继续攀升至约387gb,并保持不变,然后以与尝试1类似的方式崩溃。请注意,它尝试创建的
    int64
    的大小是尝试1的一半,这是我的意图-只生成我需要的那些,但实际内存使用到这一点更大

    #!/usr/local/bin/python3.5                                  
    
    import scipy.sparse as sp
    import numpy as np
    
    def generate_sparse_pattern(length):
        print("Length:" + str(length))
        return sp.triu(np.ones((length,length), dtype=np.int8))
    
    m = generate_sparse_pattern(522659)
    

    这个答案正在进行中

    当稀疏矩阵是稀疏矩阵时,它们在空间和时间上都是高效的。粗略的经验表明,10%或更少的稀疏度是好的。50%不是

    该软件包的核心是为线性代数工作开发的(例如有限元ODE解决方案)。特别是
    csr
    格式针对矩阵乘法进行了优化。它使用编译代码(
    cython
    ),它使用标准的
    c
    数据类型-整数、浮点和双精度。在
    numpy
    术语中,表示
    int64
    float32
    float64
    。所选格式接受其他数据类型,如
    int8
    ,但在转换为其他格式和计算时很难保持该数据类型

    行和列索引被显式存储(用于
    coo
    csr
    ),并根据矩阵的形状使用
    int32
    int64

    ===

    您的第一个方法:

    #!/usr/local/bin/python3.5                                       
    
    import scipy.sparse as sp
    import numpy as np
    
    def generate_sparse_pattern(length):
       print("Length:" + str(length))
       print("Create Matrix")
       matrix = sp.lil_matrix((length,length), dtype=np.int8)
       print("Create Ones")
       ones = np.ones((length * (length+1) // 2), dtype=np.int8)
       matrix[np.triu_indices_from(matrix,0)] = ones
       return matrix.tocsr()
    
    m = generate_sparse_pattern(522659)
    
    273172430281是
    长度**2
    ,原始数组中的总数。由于形状的原因,它必须使用较大的
    int64
    dtype。密集数组只需要有空间容纳273172430281
    int8
    值,但是稀疏数组添加了这个
    int64
    索引数组
    triu
    将把所有这些数组一分为二(取决于k),但这仍然比密集数组大

    ===

    在第二种情况下

    File "/usr/local/lib/python3.5/site-packages/scipy/sparse/extract.py", line 162, in triu
        A = coo_matrix(A, copy=False)
      File "/usr/local/lib/python3.5/site-packages/scipy/sparse/coo.py", line 191, in __init__
        self.row, self.col = M.nonzero()
    MemoryError: Unable to allocate 3.98 TiB for an array with shape (273172430281, 2) and data type int64
    
    生成(n,m)布尔掩码

    tri(n, m, k=k-1, dtype=bool)
    
    查找该掩码的非零元素的索引。它需要类似的空间

    nonzero(~tri(n, m, k=k-1, dtype=bool))
    
    是一个2元素的元组,包含15个元素的行和列索引数组

    密集阵列占用的空间要少得多,即使它同时节省了0和1:

    (136586476470, 2) and data type int64
    
    In [43]: np.triu_indices_from(np.ones((5,5)))                                            
    Out[43]: 
    (array([0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 3, 3, 4]),
     array([0, 1, 2, 3, 4, 1, 2, 3, 4, 2, 3, 4, 3, 4, 4]))
    

    这个答案正在进行中

    当稀疏矩阵是稀疏矩阵时,它们在空间和时间上都是高效的。粗略的经验表明,10%或更少的稀疏度是好的。50%不是

    该软件包的核心是为线性代数工作开发的(例如有限元ODE解决方案)。特别是
    csr
    格式针对矩阵乘法进行了优化。它使用编译代码(
    cython
    ),它使用标准的
    c
    数据类型-整数、浮点和双精度。在
    numpy
    术语中,表示
    int64
    float32
    float64
    。所选格式接受其他数据类型,如
    int8
    ,但在转换为其他格式和计算时很难保持该数据类型

    行和列索引被显式存储(用于
    coo
    csr
    ),并根据矩阵的形状使用
    int32
    int64

    ===

    您的第一个方法:

    #!/usr/local/bin/python3.5                                       
    
    import scipy.sparse as sp
    import numpy as np
    
    def generate_sparse_pattern(length):
       print("Length:" + str(length))
       print("Create Matrix")
       matrix = sp.lil_matrix((length,length), dtype=np.int8)
       print("Create Ones")
       ones = np.ones((length * (length+1) // 2), dtype=np.int8)
       matrix[np.triu_indices_from(matrix,0)] = ones
       return matrix.tocsr()
    
    m = generate_sparse_pattern(522659)
    
    273172430281是
    长度**2
    ,原始数组中的总数。由于形状的原因,它必须使用较大的
    int64
    dtype。密集数组只需要有空间容纳273172430281
    int8
    值,但是稀疏数组添加了这个
    int64
    索引数组
    triu
    将把所有这些数组一分为二(取决于k),但这仍然比密集数组大

    ===

    在第二种情况下

    File "/usr/local/lib/python3.5/site-packages/scipy/sparse/extract.py", line 162, in triu
        A = coo_matrix(A, copy=False)
      File "/usr/local/lib/python3.5/site-packages/scipy/sparse/coo.py", line 191, in __init__
        self.row, self.col = M.nonzero()
    MemoryError: Unable to allocate 3.98 TiB for an array with shape (273172430281, 2) and data type int64
    
    生成(n,m)布尔掩码

    tri(n, m, k=k-1, dtype=bool)
    
    查找该掩码的非零元素的索引。它需要类似的空间

    nonzero(~tri(n, m, k=k-1, dtype=bool))
    
    是一个2元素的元组,包含15个元素的行和列索引数组

    密集阵列占用的空间要少得多,即使它同时节省了0和1:

    (136586476470, 2) and data type int64
    
    In [43]: np.triu_indices_from(np.ones((5,5)))                                            
    Out[43]: 
    (array([0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 3, 3, 4]),
     array([0, 1, 2, 3, 4, 1, 2, 3, 4, 2, 3, 4, 3, 4, 4]))
    

    查看
    sp.triu
    的代码。我从来没用过。在第二个例子中,
    np.triu
    正在创建一个包含所有上层索引的非常大的数组。
    np.triu index\u from
    调用
    np.tri
    来创建一个掩码(这是我想要的!)-但是
    m中的
    min\u int
    等于更大的外部(arange(N,dtype=\u min\u int(0,N)