目录

torch.sparse

介绍

PyTorch 提供来表示 包含单个数据类型的元素的多维数组。由 default,数组元素连续存储在内存中,从而导致 各种数组处理算法的高效实现 中继对数组元素的快速访问。但是,存在一个 重要的多维数组类,即所谓的稀疏数组, 其中,数组元素的连续内存存储结果是 欠佳。稀疏数组具有很大一部分 元素等于 0,这意味着也会有大量内存 因为如果只有非零元素 stored 或/和 processed。各种稀疏存储格式(如 COO、 CSR/CSC、LIL 等)已开发,针对 稀疏数组中非零元素的特定结构以及 对数组进行特定操作。

注意

当谈论仅存储 sparse 的非零元素时 数组,形容词 “non-zero” 的用法并不严格:1 是 允许在稀疏数组数据中存储零 结构。因此,在下文中,我们使用 “specified elements” for 那些实际存储的数组元素。此外, 未指定的元素通常假定为零值,但 不仅如此,因此我们使用术语“填充值”来表示 元素。

注意

使用稀疏存储格式来存储稀疏数组可以是 仅当数组的大小和稀疏级别 高。否则,对于小尺寸或低稀疏度数组,使用 连续内存存储格式可能是最有效的 方法。

警告

稀疏张量的 PyTorch API 目前处于测试阶段,在不久的将来可能会发生变化。

稀疏 COO 张量

PyTorch 实现了所谓的坐标格式,即 COO format 作为实现 sparse 的存储格式之一 张。在 COO 格式中,指定的元素存储为 Tuples 元素索引和相应值。特别

  • 指定元素的索引以 size 的 Tensor 和 element type , 收集indices(ndim, nse)torch.int64

  • 相应的值收集在 Tensor 的 size 和任意整数或浮点数 Number 元素类型、values(nse,)

其中 是张量的维数,是 指定元素的数量。ndimnse

注意

稀疏 COO 张量的内存消耗至少为字节(加上一个常量 存储其他张量数据的开销)。(ndim * 8 + <size of element type in bytes>) * nse

跨步张量的内存消耗至少为 。product(<tensor shape>) * <size of element type in bytes>

例如,一个 10 000 x 10 000 张量的内存消耗 使用 COO 张量时,100 000 个非零 32 位浮点数至少是字节 layout 和 bytes 默认的跨步张量布局。注意 200 倍内存 使用 COO 存储格式进行保存。(2 * 8 + 4) * 100 000 = 2 000 00010 000 * 10 000 * 4 = 400 000 000

建设

稀疏 COO 张量可以通过提供 indices 和 values,以及稀疏张量的大小(当它 无法从 indices 和 values 张量推断出)到函数

假设我们想定义一个稀疏张量,条目 3 位于 location (0, 2),位置 (1, 0) 的条目 4 和位置 (1, 2) 的条目 5。 未指定的元素假定具有相同的值、填充值、 默认情况下为零。然后我们会写:

>>> i = [[0, 1, 1],
         [2, 0, 2]]
>>> v =  [3, 4, 5]
>>> s = torch.sparse_coo_tensor(i, v, (2, 3))
>>> s
tensor(indices=tensor([[0, 1, 1],
                       [2, 0, 2]]),
       values=tensor([3, 4, 5]),
       size=(2, 3), nnz=3, layout=torch.sparse_coo)
>>> s.to_dense()
tensor([[0, 0, 3],
        [4, 0, 5]])

请注意,input 不是索引 Tuples 的列表。如果需要帮助, 要以这种方式编写索引,您应该在将它们传递给 Sparse 构造函数:i

>>> i = [[0, 2], [1, 0], [1, 2]]
>>> v =  [3,      4,      5    ]
>>> s = torch.sparse_coo_tensor(list(zip(*i)), v, (2, 3))
>>> # Or another equivalent formulation to get s
>>> s = torch.sparse_coo_tensor(torch.tensor(i).t(), v, (2, 3))
>>> torch.sparse_coo_tensor(i.t(), v, torch.Size([2,3])).to_dense()
tensor([[0, 0, 3],
        [4, 0, 5]])

可以通过指定其大小来构造空稀疏 COO 张量 只:

>>> torch.sparse_coo_tensor(size=(2, 3))
tensor(indices=tensor([], size=(2, 0)),
       values=tensor([], size=(0,)),
       size=(2, 3), nnz=0, layout=torch.sparse_coo)

混合稀疏 COO 张量

Pytorch 实现了具有标量值的稀疏张量的扩展 到具有(连续)张量值的稀疏张量。这样的张量是 称为混合张量。

PyTorch 混合 COO 张量通过允许 tensor 设置为多维张量,以便我们 有:values

  • 指定元素的索引以 size 的 Tensor 和 element type , 收集indices(sparse_dims, nse)torch.int64

  • 相应的 (Tensor) 值以 size 的 Tensor 和任意整数收集 或浮点数元素类型。values(nse, dense_dims)

注意

我们使用 (M + K) 维张量来表示 N 维混合体 sparse 张量,其中 M 和 K 是 sparse 和 density 的数量 维度,使得 M + K == N 成立。

假设我们想创建一个 (2 + 1) 维张量,其中条目为 [3, 4] 在位置 (0, 2),条目 [5, 6] 在位置 (1, 0) 和条目 [7, 8] 在位置 (1, 2)。我们会写

>>> i = [[0, 1, 1],
         [2, 0, 2]]
>>> v =  [[3, 4], [5, 6], [7, 8]]
>>> s = torch.sparse_coo_tensor(i, v, (2, 3, 2))
>>> s
tensor(indices=tensor([[0, 1, 1],
                       [2, 0, 2]]),
       values=tensor([[3, 4],
                      [5, 6],
                      [7, 8]]),
       size=(2, 3, 2), nnz=3, layout=torch.sparse_coo)
>>> s.to_dense()
tensor([[[0, 0],
         [0, 0],
         [3, 4]],
        [[5, 6],
         [0, 0],
         [7, 8]]])

一般来说,如果 是一个稀疏 COO 张量和 ,那么我们有以下内容 invariants:sM = s.sparse_dim()K = s.dense_dim()

  • M + K == len(s.shape) == s.ndim- 张量的维数 是稀疏维数和密集维数之和,

  • s.indices().shape == (M, nse)- 稀疏索引被存储 明确地

  • s.values().shape == (nse,) + s.shape[M : M + K]- 值 的 Hybrid Tensor 是 K 维张量,

  • s.values().layout == torch.strided- 值存储为 跨步张量。

注意

密集维度始终遵循稀疏维度,即混合 不支持密集和稀疏维度。

未合并的稀疏 COO 张量

PyTorch 稀疏 COO 张量格式允许未合并的稀疏张量, 索引中可能存在重复的坐标;在本例中, 解释是该索引处的值是所有 重复的值条目。例如,可以指定多个值,而 , 对于同一索引 ,这将导致 1-D uncoalesced Tensor:341

>>> i = [[1, 1]]
>>> v =  [3, 4]
>>> s=torch.sparse_coo_tensor(i, v, (3,))
>>> s
tensor(indices=tensor([[1, 1]]),
       values=tensor(  [3, 4]),
       size=(3,), nnz=2, layout=torch.sparse_coo)

而合并过程将累积多值元素 转换为单个值:

>>> s.coalesce()
tensor(indices=tensor([[1]]),
       values=tensor([7]),
       size=(3,), nnz=1, layout=torch.sparse_coo)

通常,method 的输出是一个 sparse 张量具有以下属性:

  • 指定 Tensor 元素的索引是唯一的,

  • 索引按字典顺序排序,

  • 返回。True

注意

在大多数情况下,您不必关心 稀疏张量是否合并,因为大多数操作都可以 以相同方式给出合并或未合并的稀疏张量。

但是,某些操作可以更有效地实现 未合并的张量,以及一些关于合并的张量。

例如,稀疏 COO 张量的添加是通过 简单地连接 indices 和 values 张量:

>>> a = torch.sparse_coo_tensor([[1, 1]], [5, 6], (2,))
>>> b = torch.sparse_coo_tensor([[0, 0]], [7, 8], (2,))
>>> a + b
tensor(indices=tensor([[0, 0, 1, 1]]),
       values=tensor([7, 8, 5, 6]),
       size=(2,), nnz=4, layout=torch.sparse_coo)

如果您重复执行可能产生重复的操作 条目(例如,),您应该偶尔 合并稀疏张量以防止它们变得太大。

另一方面,索引的字典顺序可以是 有利于实现涉及许多元素的算法 选择操作,例如切片或矩阵产品。

使用稀疏 COO 张量

让我们考虑以下示例:

>>> i = [[0, 1, 1],
         [2, 0, 2]]
>>> v =  [[3, 4], [5, 6], [7, 8]]
>>> s = torch.sparse_coo_tensor(i, v, (2, 3, 2))

如上所述,稀疏 COO 张量是一个实例,为了区别于使用 其他一些布局,on 可以使用 或 属性:torch.Tensor.layout

>>> isinstance(s, torch.Tensor)
True
>>> s.is_sparse
True
>>> s.layout == torch.sparse_coo
True

稀疏维数和密集维数可以使用 方法 。例如:

>>> s.sparse_dim(), s.dense_dim()
(2, 1)

如果 是稀疏 COO 张量,则其 COO 格式数据可以是 使用 方法 获取。s

注意

目前,只有当张量 instance 被合并:

>>> s.indices()
RuntimeError: Cannot get indices on an uncoalesced tensor, please call .coalesce() first

要获取未合并张量的 COO 格式数据,请使用 和 :torch.Tensor._values()torch.Tensor._indices()

>>> s._indices()
tensor([[0, 1, 1],
        [2, 0, 2]])

警告

调用将返回一个分离的张量。 要跟踪渐变,必须为 使用。torch.Tensor._values()torch.Tensor.coalesce().values()

构造新的稀疏 COO 张量会得到一个不是 coalesced:

>>> s.is_coalesced()
False

但是可以使用 方法

>>> s2 = s.coalesce()
>>> s2.indices()
tensor([[0, 1, 1],
       [2, 0, 2]])

当使用未合并的稀疏 COO 张量时,必须考虑到 一个帐户 未合并数据的加法性质:的值 相同的指数是 Evaluation 给出 的值 相应的 Tensor 元素。例如,标量 未合并稀疏张量上的乘法可以通过以下方式实现 将所有未合并的值乘以标量 because 成立。但是,任何非线性运算 例如,一个平方根,不能通过将操作应用于 uncoalesced data (未合并的数据),因为 持有。c * (a + b) == c * a + c * bsqrt(a + b) == sqrt(a) + sqrt(b)

仅支持稀疏 COO 张量的切片(正步长) 用于密集尺寸。稀疏和密集都支持索引 尺寸:

>>> s[1]
tensor(indices=tensor([[0, 2]]),
       values=tensor([[5, 6],
                      [7, 8]]),
       size=(3, 2), nnz=2, layout=torch.sparse_coo)
>>> s[1, 0, 1]
tensor(6)
>>> s[1, 0, 1:]
tensor([6])

在 PyTorch 中,不能指定稀疏张量的 fill 值 显式 ,通常假定为零。然而,存在 可能以不同方式解释 fill 值的操作。为 实例中,使用 假设 Fill 值为负无穷大。

稀疏 CSR 张量

CSR (Compressed Sparse Row) 稀疏张量格式实现了 CSR 格式 用于存储 2 维张量。虽然不支持 N 维 张量,与 COO 格式相比,它的主要优势是更好地利用了存储和 更快的计算操作,例如稀疏矩阵向量乘法 使用 MKL 和 MAGMA 后端。目前不存在 CUDA 支持。

CSR 稀疏张量由三个 1-D 张量组成:和 :crow_indicescol_indicesvalues

  • 张量由压缩的行索引组成。这是一个 1-D 张量 的大小。最后一个元素是非零的数量。这个张量 根据给定行的位置对索引进行编码 开始。张量中的每个连续数字减去它前面的数字表示 给定行中的元素数。crow_indicessize[0] + 1valuescol_indices

  • 张量包含每个值的列索引。这是 1-D 大小为 的张量。col_indicesnnz

  • 张量包含 CSR 张量的值。这是一个 1-D 张量 的大小。valuesnnz

注意

索引张量 和 的元素类型 为 (default) 或 .如果要使用启用 MKL 的矩阵 操作中,请使用 .这是由于 pytorch 的默认链接 使用 MKL LP64,它使用 32 位整数索引。crow_indicescol_indicestorch.int64torch.int32torch.int32

CSR 张量的构造

使用该方法可以直接构建稀疏 CSR 矩阵。用户必须分别提供行和列索引以及值张量。 该参数是可选的,如果不存在,将从 the 和 中推导出来。sizecrow_indicescol_indices

>>> crow_indices = torch.tensor([0, 2, 4])
>>> col_indices = torch.tensor([0, 1, 0, 1])
>>> values = torch.tensor([1, 2, 3, 4])
>>> csr = torch.sparse_csr_tensor(crow_indices, col_indices, values, dtype=torch.double)
>>> csr
tensor(crow_indices=tensor([0, 2, 4]),
      col_indices=tensor([0, 1, 0, 1]),
      values=tensor([1., 2., 3., 4.]), size=(2, 2), nnz=4,
      dtype=torch.float64)
>>> csr.to_dense()
tensor([[1., 2.],
        [3., 4.]], dtype=torch.float64)

CSR Tensor 操作

从 stramed 或sparse COO 构建稀疏 CSR 张量的最简单方法 tensor 将使用 。(strided) 张量中的任何零都将 被解释为稀疏张量中的缺失值:tensor.to_sparse_csr()

>>> a = torch.tensor([[0, 0, 1, 0], [1, 2, 0, 0], [0, 0, 0, 0]], dtype = torch.float64)
>>> sp = a.to_sparse_csr()
>>> sp
tensor(crow_indices=tensor([0, 1, 3, 3]),
      col_indices=tensor([2, 0, 1]),
      values=tensor([1., 1., 2.]), size=(3, 4), nnz=3, dtype=torch.float64)

可以使用该方法执行稀疏矩阵向量乘法。这是目前唯一的数学运算 在 CSR 张量上受支持。tensor.matmul()

>>> vec = torch.randn(4, 1, dtype=torch.float64)
>>> sp.matmul(vec)
tensor([[0.9078],
        [1.3180],
        [0.0000]], dtype=torch.float64)

支持的线性代数运算

下表总结了 上支持的线性代数运算 操作数布局可能不同的稀疏矩阵。这里表示具有给定布局的张量。同样,表示矩阵(二维 PyTorch 张量),表示向量(一维 PyTorch 张量)。此外,表示 标量(浮点或 0-D PyTorch 张量)是按元素计算的 multiplication,并且是矩阵乘法。T[layout]M[layout]V[layout]f*@

PyTorch 操作

稀疏的毕业生?

布局签名

torch.mv()

M[sparse_coo] @ V[strided] -> V[strided]

torch.mv()

M[sparse_csr] @ V[strided] -> V[strided]

torch.matmul()

M[sparse_coo] @ M[strided] -> M[strided]

torch.matmul()

M[sparse_csr] @ M[strided] -> M[strided]

torch.mm()

M[sparse_coo] @ M[strided] -> M[strided]

torch.sparse.mm()

是的

M[sparse_coo] @ M[strided] -> M[strided]

torch.smm()

M[sparse_coo] @ M[strided] -> M[sparse_coo]

torch.hspmm()

M[sparse_coo] @ M[strided] -> M[hybrid sparse_coo]

torch.bmm()

T[sparse_coo] @ T[strided] -> T[strided]

torch.addmm()

f * M[strided] + f * (M[sparse_coo] @ M[strided]) -> M[strided]

torch.sparse.addmm()

是的

f * M[strided] + f * (M[sparse_coo] @ M[strided]) -> M[strided]

torch.sspaddmm()

f * M[sparse_coo] + f * (M[sparse_coo] @ M[strided]) -> M[sparse_coo]

torch.lobpcg()

GENEIG(M[sparse_coo]) -> M[strided], M[strided]

torch.pca_lowrank()

是的

PCA(M[sparse_coo]) -> M[strided], M[strided], M[strided]

torch.svd_lowrank()

是的

SVD(M[sparse_coo]) -> M[strided], M[strided], M[strided]

其中 “Sparse grad?” 列表示 PyTorch 操作是否支持 相对于稀疏矩阵参数向后。所有 PyTorch 操作、 except ,支持相对于 stribed 向后 matrix 参数。

注意

目前,PyTorch 不支持使用 布局签名 。然而 应用程序仍然可以使用 matrix relation 来计算此函数。M[strided] @ M[sparse_coo]D @ S == (S.t() @ D.t()).t()

张量方法和稀疏

以下 Tensor 方法与稀疏 Tensor 相关:

Tensor.is_sparse

如果 Tensor 使用稀疏存储布局,否则。TrueFalse

Tensor.dense_dim

返回 sparse tensor 中的密集维度数。self

Tensor.sparse_dim

返回稀疏张量中的稀疏维度数。self

Tensor.sparse_mask

返回一个新的稀疏张量,其中包含由 sparse 张量的索引过滤的跨步张量中的值。selfmask

Tensor.to_sparse

返回张量的稀疏副本。

Tensor.to_sparse_coo

将张量转换为坐标格式

Tensor.to_sparse_csr

将张量转换为压缩的行存储格式。

张量.indices

返回稀疏 COO 张量的 indices 张量。

Tensor.values

返回稀疏 COO 张量的 values tensor。

以下 Tensor 方法特定于稀疏 COO 张量:

Tensor.coalesce

返回 if 是未合并张量的合并副本。selfself

Tensor.sparse_resize_

稀疏张量的大小调整为所需的大小以及稀疏和密集维度的数量。self

Tensor.sparse_resize_and_clear_

稀疏张量中删除所有指定的元素,并调整为所需的大小以及稀疏和密集维度的数量。selfself

Tensor.is_coalesced

如果是合并的稀疏 COO 张量,则返回,否则返回。TrueselfFalse

Tensor.to_dense

创建 的跨步副本。self

以下方法特定于稀疏 CSR 张量

Tensor.crow_indices

当 是 layout 的稀疏 CSR 张量时,返回包含张量的压缩行索引的张量。selfselfsparse_csr

Tensor.col_indices

当 是 layout 的稀疏 CSR 张量时,返回包含张量列索引的张量。selfselfsparse_csr

以下 Tensor 方法支持稀疏 COO 张量:

deg2rad_()rad2deg_()

特定于稀疏张量的 Torch 函数

sparse_coo_tensor

COO(rdinate) 格式构造一个稀疏张量,并在给定的 .indices

sparse_csr_tensor

在 CSR(压缩稀疏行)中构造一个稀疏张量,并在给定的 和 处使用指定的值。crow_indicescol_indices

稀疏 .sum

返回给定 dimensions 中稀疏张量的每一行的总和 。inputdim

sparse.addmm

此函数的作用与 forward 完全相同,只是它支持 reverse for sparse matrix 。mat1

sparse.sampled_addmm

对密集矩阵执行矩阵乘法,并在稀疏模式 指定的位置执行 。mat1mat2input

sparse.mm

执行稀疏矩阵和 (sparse 或 strided) 矩阵的矩阵乘法。mat1mat2

SSPADDMM

Matrix 将稀疏张量与密集张量相乘,然后将稀疏张量添加到结果中。mat1mat2input

HSPMM

执行稀疏 COO 矩阵和跨步矩阵的矩阵乘法。mat1mat2

SMM

执行稀疏矩阵与密集矩阵 的矩阵乘法。inputmat

sparse.softmax

应用 softmax 函数。

sparse.log_softmax

应用 softmax 函数,后跟对数。

文档

访问 PyTorch 的全面开发人员文档

查看文档

教程

获取面向初学者和高级开发人员的深入教程

查看教程

资源

查找开发资源并解答您的问题

查看资源