2.5.2.2 稀疏矩阵类

2.5.2.2.1 对角线格式 (DIA))

  • 非常简单的格式
  • 形状 (n_diag, length) 的密集Numpy数组的对角线
    • 固定长度 -> 当离主对角线比较远时会浪费空间
    • _data_matrix的子类 (带数据属性的稀疏矩阵类)
  • 每个对角线的偏移
    • 0 是主对角线
    • 负偏移 = 下面
    • 正偏移 = 上面
  • 快速矩阵 * 向量 (sparsetools)
  • 快速方便的关于项目的操作
    • 直接操作数据数组 (快速的NumPy机件)
  • 构建器接受 :
    • 密集矩阵 (数组)
    • 稀疏矩阵
    • 形状元组 (创建空矩阵)
    • (数据, 偏移) 元组
  • 没有切片、没有单个项目访问
  • 用法 :
    • 非常专业
    • 通过有限微分解偏微分方程
    • 有一个迭代求解器 ##### 2.5.2.2.1.1 示例
  • 创建一些DIA矩阵 :

In [3]:

  1. data = np.array([[1, 2, 3, 4]]).repeat(3, axis=0)
  2. data

Out[3]:

  1. array([[1, 2, 3, 4],
  2. [1, 2, 3, 4],
  3. [1, 2, 3, 4]])

In [6]:

  1. offsets = np.array([0, -1, 2])
  2. mtx = sparse.dia_matrix((data, offsets), shape=(4, 4))
  3. mtx

Out[6]:

  1. <4x4 sparse matrix of type '<type 'numpy.int64'>'
  2. with 9 stored elements (3 diagonals) in DIAgonal format>

In [7]:

  1. mtx.todense()

Out[7]:

  1. matrix([[1, 0, 3, 0],
  2. [1, 2, 0, 4],
  3. [0, 2, 3, 0],
  4. [0, 0, 3, 4]])

In [9]:

  1. data = np.arange(12).reshape((3, 4)) + 1
  2. data

Out[9]:

  1. array([[ 1, 2, 3, 4],
  2. [ 5, 6, 7, 8],
  3. [ 9, 10, 11, 12]])

In [10]:

  1. mtx = sparse.dia_matrix((data, offsets), shape=(4, 4))
  2. mtx.data

Out[10]:

  1. array([[ 1, 2, 3, 4],
  2. [ 5, 6, 7, 8],
  3. [ 9, 10, 11, 12]])

In [11]:

  1. mtx.offsets

Out[11]:

  1. array([ 0, -1, 2], dtype=int32)

In [12]:

  1. print mtx
  1. (0, 0) 1
  2. (1, 1) 2
  3. (2, 2) 3
  4. (3, 3) 4
  5. (1, 0) 5
  6. (2, 1) 6
  7. (3, 2) 7
  8. (0, 2) 11
  9. (1, 3) 12

In [13]:

  1. mtx.todense()

Out[13]:

  1. matrix([[ 1, 0, 11, 0],
  2. [ 5, 2, 0, 12],
  3. [ 0, 6, 3, 0],
  4. [ 0, 0, 7, 4]])
  • 机制的解释 :

偏移: 行

  1. 2: 9
  2. 1: --10------
  3. 0: 1 . 11 .
  4. -1: 5 2 . 12
  5. -2: . 6 3 .
  6. -3: . . 7 4
  7. ---------8
  • 矩阵-向量相乘

In [15]:

  1. vec = np.ones((4, ))
  2. vec

Out[15]:

  1. array([ 1., 1., 1., 1.])

In [16]:

  1. mtx * vec

Out[16]:

  1. array([ 12., 19., 9., 11.])

In [17]:

  1. mtx.toarray() * vec

Out[17]:

  1. array([[ 1., 0., 11., 0.],
  2. [ 5., 2., 0., 12.],
  3. [ 0., 6., 3., 0.],
  4. [ 0., 0., 7., 4.]])

2.5.2.2.2 列表的列表格式 (LIL))

  • 基于行的联接列表
    • 每一行是一个Python列表(排序的)非零元素的列索引
    • 行存储在Numpy数组中 (dtype=np.object)
    • 非零值也近似存储
  • 高效增量构建稀疏矩阵
  • 构建器接受 :
    • 密集矩阵 (数组)
    • 稀疏矩阵
    • 形状元组 (创建一个空矩阵)
  • 灵活切片、高效改变稀疏结构
  • 由于是基于行的,算术和行切片慢
  • 用途 :
    • 当稀疏模式并不是已知的逻辑或改变
    • 例子:从一个文本文件读取稀疏矩阵 ##### 2.5.2.2.2.1 示例
  • 创建一个空的LIL矩阵 :

In [2]:

  1. mtx = sparse.lil_matrix((4, 5))
  • 准备随机数据:

In [4]:

  1. from numpy.random import rand
  2. data = np.round(rand(2, 3))
  3. data

Out[4]:

  1. array([[ 0., 0., 0.],
  2. [ 1., 0., 0.]])
  • 使用象征所以分配数据:

In [6]:

  1. mtx[:2, [1, 2, 3]] = data
  2. mtx

Out[6]:

  1. <4x5 sparse matrix of type '<type 'numpy.float64'>'
  2. with 3 stored elements in LInked List format>

In [7]:

  1. print mtx
  1. (0, 1) 1.0
  2. (0, 3) 1.0
  3. (1, 2) 1.0

In [8]:

  1. mtx.todense()

Out[8]:

  1. matrix([[ 0., 1., 0., 1., 0.],
  2. [ 0., 0., 1., 0., 0.],
  3. [ 0., 0., 0., 0., 0.],
  4. [ 0., 0., 0., 0., 0.]])

In [9]:

  1. mtx.toarray()

Out[9]:

  1. array([[ 0., 1., 0., 1., 0.],
  2. [ 0., 0., 1., 0., 0.],
  3. [ 0., 0., 0., 0., 0.],
  4. [ 0., 0., 0., 0., 0.]])

更多的切片和索引:

In [10]:

  1. mtx = sparse.lil_matrix([[0, 1, 2, 0], [3, 0, 1, 0], [1, 0, 0, 1]])
  2. mtx.todense()

Out[10]:

  1. matrix([[0, 1, 2, 0],
  2. [3, 0, 1, 0],
  3. [1, 0, 0, 1]])

In [11]:

  1. print mtx
  1. (0, 1) 1
  2. (0, 2) 2
  3. (1, 0) 3
  4. (1, 2) 1
  5. (2, 0) 1
  6. (2, 3) 1

In [12]:

  1. mtx[:2, :]

Out[12]:

  1. <2x4 sparse matrix of type '<type 'numpy.int64'>'
  2. with 4 stored elements in LInked List format>

In [13]:

  1. mtx[:2, :].todense()

Out[13]:

  1. matrix([[0, 1, 2, 0],
  2. [3, 0, 1, 0]])

In [14]:

  1. mtx[1:2, [0,2]].todense()

Out[14]:

  1. matrix([[3, 1]])

In [15]:

  1. mtx.todense()

Out[15]:

  1. matrix([[0, 1, 2, 0],
  2. [3, 0, 1, 0],
  3. [1, 0, 0, 1]])

2.5.2.2.3 值的字典格式 (DOK))

  • Python字典的子类
    • 键是 (行, 列) 索引元组 (不允许重复的条目)
    • 值是对应的非零值
  • 高效增量构建稀疏矩阵
  • 构建器支持:
    • 密集矩阵 (数组)
    • 稀疏矩阵
    • 形状元组 (创建空矩阵)
  • 高效 O(1) 对单个元素的访问
  • 灵活索引,改变稀疏结构是高效
  • 一旦创建完成后可以被高效转换为coo_matrix
  • 算术很慢 (循环用dict.iteritems())
  • 用法:
    • 当稀疏模式是未知的假设或改变时
2.5.2.2.3.1 示例
  • 逐个元素创建一个DOK矩阵:

In [16]:

  1. mtx = sparse.dok_matrix((5, 5), dtype=np.float64)
  2. mtx

Out[16]:

  1. <5x5 sparse matrix of type '<type 'numpy.float64'>'
  2. with 0 stored elements in Dictionary Of Keys format>

In [17]:

  1. for ir in range(5):
  2. for ic in range(5):
  3. mtx[ir, ic] = 1.0 * (ir != ic)
  4. mtx

Out[17]:

  1. <5x5 sparse matrix of type '<type 'numpy.float64'>'
  2. with 20 stored elements in Dictionary Of Keys format>

In [18]:

  1. mtx.todense()

Out[18]:

  1. matrix([[ 0., 1., 1., 1., 1.],
  2. [ 1., 0., 1., 1., 1.],
  3. [ 1., 1., 0., 1., 1.],
  4. [ 1., 1., 1., 0., 1.],
  5. [ 1., 1., 1., 1., 0.]])
  • 切片与索引:

In [19]:

  1. mtx[1, 1]

Out[19]:

  1. 0.0

In [20]:

  1. mtx[1, 1:3]

Out[20]:

  1. <1x2 sparse matrix of type '<type 'numpy.float64'>'
  2. with 1 stored elements in Dictionary Of Keys format>

In [21]:

  1. mtx[1, 1:3].todense()

Out[21]:

  1. matrix([[ 0., 1.]])

In [22]:

  1. mtx[[2,1], 1:3].todense()

Out[22]:

  1. matrix([[ 1., 0.],
  2. [ 0., 1.]])

2.5.2.2.4 座标格式 (COO))

  • 也被称为 ‘ijv’ 或 ‘triplet’ 格式
    • 三个NumPy数组: row, col, data
    • data[i]是在 (row[i], col[i]) 位置的值
    • 允许重复值
  • _data_matrix的子类 (带有data属性的稀疏矩阵类)
  • 构建稀疏矩阵的高速模式
  • 构建器接受:
    • 密集矩阵 (数组)
    • 稀疏矩阵
    • 形状元组 (创建空数组)
    • (data, ij)元组
  • 与CSR/CSC格式非常快的互相转换
  • 快速的矩阵 * 向量 (sparsetools)
  • 快速而简便的逐项操作
    • 直接操作数据数组 (快速NumPy机制)
  • 没有切片,没有算术 (直接)
  • 使用:
    • 在各种稀疏格式间的灵活转换
    • 当转化到其他形式 (通常是 CSR 或 CSC), 重复的条目被加总到一起
      • 有限元素矩阵的快速高效创建
2.5.2.2.4.1 示例
  • 创建空的COO矩阵:

In [23]:

  1. mtx = sparse.coo_matrix((3, 4), dtype=np.int8)
  2. mtx.todense()

Out[23]:

  1. matrix([[0, 0, 0, 0],
  2. [0, 0, 0, 0],
  3. [0, 0, 0, 0]], dtype=int8)
  • 用 (data, ij) 元组创建:

In [24]:

  1. row = np.array([0, 3, 1, 0])
  2. col = np.array([0, 3, 1, 2])
  3. data = np.array([4, 5, 7, 9])
  4. mtx = sparse.coo_matrix((data, (row, col)), shape=(4, 4))
  5. mtx

Out[24]:

  1. <4x4 sparse matrix of type '<type 'numpy.int64'>'
  2. with 4 stored elements in COOrdinate format>

In [25]:

  1. mtx.todense()

Out[25]:

  1. matrix([[4, 0, 9, 0],
  2. [0, 7, 0, 0],
  3. [0, 0, 0, 0],
  4. [0, 0, 0, 5]])

2.5.2.2.5 压缩稀疏行格式 (CSR))

  • 面向行
    • 三个Numpy数组: indices, indptr, data
      • indices是列索引的数组
      • data是对应的非零值数组
      • indptr指向行开始的所以和数据
      • 长度是n_row + 1, 最后一个项目 = 值数量 = indicesdata的长度
      • i-th行的非零值是列索引为indices[indptr[i]:indptr[i+1]]data[indptr[i]:indptr[i+1]]
      • 项目 (i, j) 可以通过data[indptr[i]+k], k是j在indices[indptr[i]:indptr[i+1]]的位置来访问
    • _cs_matrix (常规 CSR/CSC 功能) 的子类
    • _data_matrix (带有data属性的稀疏矩阵类) 的子类
  • 快速矩阵向量相乘和其他算术 (sparsetools)
  • 构建器接受:
    • 密集矩阵 (数组)
    • 稀疏矩阵
    • 形状元组 (创建空矩阵)
    • (data, ij) 元组
    • (data, indices, indptr) 元组
  • 高效行切片,面向行的操作
  • 较慢的列切片,改变稀疏结构代价昂贵
  • 用途:
    • 实际计算 (大多数线性求解器都支持这个格式)
2.5.2.2.5.1 示例
  • 创建空的CSR矩阵:

In [26]:

  1. mtx = sparse.csr_matrix((3, 4), dtype=np.int8)
  2. mtx.todense()

Out[26]:

  1. matrix([[0, 0, 0, 0],
  2. [0, 0, 0, 0],
  3. [0, 0, 0, 0]], dtype=int8)
  • (data, ij)元组创建:

In [27]:

  1. row = np.array([0, 0, 1, 2, 2, 2])
  2. col = np.array([0, 2, 2, 0, 1, 2])
  3. data = np.array([1, 2, 3, 4, 5, 6])
  4. mtx = sparse.csr_matrix((data, (row, col)), shape=(3, 3))
  5. mtx

Out[27]:

  1. <3x3 sparse matrix of type '<type 'numpy.int64'>'
  2. with 6 stored elements in Compressed Sparse Row format>

In [28]:

  1. mtx.todense()

Out[28]:

  1. matrix([[1, 0, 2],
  2. [0, 0, 3],
  3. [4, 5, 6]])

In [29]:

  1. mtx.data

Out[29]:

  1. array([1, 2, 3, 4, 5, 6])

In [30]:

  1. mtx.indices

Out[30]:

  1. array([0, 2, 2, 0, 1, 2], dtype=int32)

In [31]:

  1. mtx.indptr

Out[31]:

  1. array([0, 2, 3, 6], dtype=int32)

(data, indices, indptr)元组创建:

In [32]:

  1. data = np.array([1, 2, 3, 4, 5, 6])
  2. indices = np.array([0, 2, 2, 0, 1, 2])
  3. indptr = np.array([0, 2, 3, 6])
  4. mtx = sparse.csr_matrix((data, indices, indptr), shape=(3, 3))
  5. mtx.todense()

Out[32]:

  1. matrix([[1, 0, 2],
  2. [0, 0, 3],
  3. [4, 5, 6]])

2.5.2.2.6 压缩稀疏列格式 (CSC))

  • 面向列
    • 三个Numpy数组: indicesindptrdata
    • indices是行索引的数组
    • data是对应的非零值
    • indptr指向indicesdata开始的列
    • 长度是n_col + 1, 最后一个条目 = 值数量 = indicesdata的长度
    • 第i列的非零值是行索引为indices[indptr[i]:indptr[i+1]]data[indptr[i]:indptr[i+1]]
    • 项目 (i, j) 可以作为data[indptr[j]+k]访问, k是i在indices[indptr[j]:indptr[j+1]]的位置
    • _cs_matrix的子类 (通用的 CSR/CSC 功能性)
      • _data_matrix的子类 (带有data属性的稀疏矩阵类)
  • 快速的矩阵和向量相乘及其他数学 (sparsetools)
  • 构建器接受:
    • 密集矩阵 (数组)
    • 稀疏矩阵
    • 形状元组 (创建空矩阵)
    • (data, ij)元组
    • (data, indices, indptr)元组
  • 高效列切片、面向列的操作
  • 较慢的行切片、改变稀疏结构代价昂贵
  • 用途:
    • 实际计算 (巨大多数线性求解器支持这个格式)
2.5.2.2.6.1 示例
  • 创建空CSC矩阵:

In [33]:

  1. mtx = sparse.csc_matrix((3, 4), dtype=np.int8)
  2. mtx.todense()

Out[33]:

  1. matrix([[0, 0, 0, 0],
  2. [0, 0, 0, 0],
  3. [0, 0, 0, 0]], dtype=int8)
  • (data, ij)元组创建:

In [34]:

  1. row = np.array([0, 0, 1, 2, 2, 2])
  2. col = np.array([0, 2, 2, 0, 1, 2])
  3. data = np.array([1, 2, 3, 4, 5, 6])
  4. mtx = sparse.csc_matrix((data, (row, col)), shape=(3, 3))
  5. mtx

Out[34]:

  1. <3x3 sparse matrix of type '<type 'numpy.int64'>'
  2. with 6 stored elements in Compressed Sparse Column format>

In [35]:

  1. mtx.todense()

Out[35]:

  1. matrix([[1, 0, 2],
  2. [0, 0, 3],
  3. [4, 5, 6]])

In [36]:

  1. mtx.data

Out[36]:

  1. array([1, 4, 5, 2, 3, 6])

In [37]:

  1. mtx.indices

Out[37]:

  1. array([0, 2, 2, 0, 1, 2], dtype=int32)

In [38]:

  1. mtx.indptr

Out[38]:

  1. array([0, 2, 3, 6], dtype=int32)
  • (data, indices, indptr)元组创建:

In [39]:

  1. data = np.array([1, 4, 5, 2, 3, 6])
  2. indices = np.array([0, 2, 2, 0, 1, 2])
  3. indptr = np.array([0, 2, 3, 6])
  4. mtx = sparse.csc_matrix((data, indices, indptr), shape=(3, 3))
  5. mtx.todense()

Out[39]:

  1. matrix([[1, 0, 2],
  2. [0, 0, 3],
  3. [4, 5, 6]])

2.5.2.2.7 块压缩行格式 (BSR))

  • 本质上,CSR带有密集的固定形状的子矩阵而不是纯量的项目
    • 块大小(R, C)必须可以整除矩阵的形状(M, N)
    • 三个Numpy数组: indicesindptrdata
      • indices是每个块列索引的数组
      • data是形状为(nnz, R, C)对应的非零值
    • _cs_matrix的子类 (通用的CSR/CSC功能性)
    • _data_matrix的子类 (带有data属性的稀疏矩阵类)
  • 快速矩阵向量相乘和其他的算术 (sparsetools)
  • 构建器接受:
    • 密集矩阵 (数组)
    • 稀疏矩阵
    • 形状元组 (创建空的矩阵)
    • (data, ij)元组
    • (data, indices, indptr)元组
  • 许多对于带有密集子矩阵的稀疏矩阵算术操作比CSR更高效很多
  • 用途:

    • 类似CSR
    • 有限元素向量值离散化 ##### 2.5.2.2.7.1 示例
  • 创建空的(1, 1)块大小的(类似CSR…)的BSR矩阵:

In [40]:

  1. mtx = sparse.bsr_matrix((3, 4), dtype=np.int8)
  2. mtx

Out[40]:

  1. <3x4 sparse matrix of type '<type 'numpy.int8'>'
  2. with 0 stored elements (blocksize = 1x1) in Block Sparse Row format>

In [41]:

  1. mtx.todense()

Out[41]:

  1. matrix([[0, 0, 0, 0],
  2. [0, 0, 0, 0],
  3. [0, 0, 0, 0]], dtype=int8)
  • 创建块大小(3, 2)的空BSR矩阵:

In [42]:

  1. mtx = sparse.bsr_matrix((3, 4), blocksize=(3, 2), dtype=np.int8)
  2. mtx

Out[42]:

  1. <3x4 sparse matrix of type '<type 'numpy.int8'>'
  2. with 0 stored elements (blocksize = 3x2) in Block Sparse Row format>
  1. - 一个bug?
  • (1, 1)块大小 (类似 CSR…)(data, ij)的元组创建:

In [43]:

row = np.array([0, 0, 1, 2, 2, 2])
col = np.array([0, 2, 2, 0, 1, 2])
data = np.array([1, 2, 3, 4, 5, 6])
mtx = sparse.bsr_matrix((data, (row, col)), shape=(3, 3))
mtx

Out[43]:

<3x3 sparse matrix of type '<type 'numpy.int64'>'
    with 6 stored elements (blocksize = 1x1) in Block Sparse Row format>

In [44]:

mtx.todense()

Out[44]:

matrix([[1, 0, 2],
        [0, 0, 3],
        [4, 5, 6]])

In [45]:

mtx.indices

Out[45]:

array([0, 2, 2, 0, 1, 2], dtype=int32)

In [46]:

mtx.indptr

Out[46]:

array([0, 2, 3, 6], dtype=int32)
  • (2, 1)块大小(data, indices, indptr)的元组创建:

In [47]:

indptr = np.array([0, 2, 3, 6])
indices = np.array([0, 2, 2, 0, 1, 2])
data = np.array([1, 2, 3, 4, 5, 6]).repeat(4).reshape(6, 2, 2)
mtx = sparse.bsr_matrix((data, indices, indptr), shape=(6, 6))
mtx.todense()

Out[47]:

matrix([[1, 1, 0, 0, 2, 2],
        [1, 1, 0, 0, 2, 2],
        [0, 0, 0, 0, 3, 3],
        [0, 0, 0, 0, 3, 3],
        [4, 4, 5, 5, 6, 6],
        [4, 4, 5, 5, 6, 6]])

In [48]:

data

Out[48]:

array([[[1, 1],
        [1, 1]],

       [[2, 2],
        [2, 2]],

       [[3, 3],
        [3, 3]],

       [[4, 4],
        [4, 4]],

       [[5, 5],
        [5, 5]],

       [[6, 6],
        [6, 6]]])