torch.sparse是一个专门处理稀疏张量的模块。通常,张量会按一定的顺序连续地进行存取。但是,对于一个存在很多空值的稀疏张量来说,顺序存储的效率显得较为低下。因此,pytorch推出了稀疏张量的处理模块。在这里,有意义的值被称为specified elements,而无意义的值(空值,通常为0,但是也可以是其他值)则被称为fill value。只有足够稀疏的张量使用这种方式进行存储才能获得更高的效率。稀疏张量的表示方式有多种,比如COO、CSR/CSC、LIL等,下面介绍COO和CSR两种格式。
  

1 Sparse COO Tensor

1.1 Coordinate format

  这种格式的稀疏矩阵是通过indicesvalues两个张量共同存储的,其中indices张量存储的是specified elements的坐标值,维度为(ndim, nse),类型为torch.int64values张量存储的是specified elements的值,维度为(nse,)。其中,ndim是张量的维度,nsespecified elements的个数。
  下面举个例子演示如何使用torch.sparse_coo_tensor()函数来构造一个COO稀疏矩阵,以及通过to_dense()方法将其变为一般的张量。其中3位于(0, 2)位置,4位于(1, 0)位置,5位于(1, 2)位置。

>>> 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)    # nnz指specified elements个数
>>> s.to_dense()
tensor([[0, 0, 3],[4, 0, 5]])

  上述例子中,i的第一行表示第一维坐标值,第二行表示第二维坐标值。i也可以使用坐标对来表示,但是在构造稀疏矩阵时,需要将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)

  

1.2 Hybrid sparse COO tensors

  上面的例子中,每个坐标下的值都是一个标量(零维数据)。但其实也可以是一个多维的数据,这一拓展的数据被称为Hybrid sparse COO tensors。在这里,indices张量的维度为(sparse_dims, nse)values张量的维度为(nse, dense_dims)。记sparse_dims的大小为M,dense_dims的大小为K,则这个hybrid张量的维度为N=M+K。
  举个例子,下面构造一个sparse_dims为2、dense_dims为1的三维hybrid张量。其中[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]]])

  记M = 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]
s.values().layout == torch.strided

  

1.3 Uncoalesced sparse COO tensors

  COO稀疏张量又可以分为两种:uncoalesced和coalesced。其中uncoalesced允许同一个索引下存在多个不同的值,而coalesced则不行。它们之间可以相互转换,例子如下:

>>> 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.is_coalesced()
False
>>> s.coalesce()
tensor(indices=tensor([[1]]),values=tensor([7]),size=(3,), nnz=1, layout=torch.sparse_coo)
>>> s.is_coalesced()
True

  上述例子说的是,在索引1处存在3和4两个值,而将其coalesce后,则相同索引的值会被相加合并,它们可以通过is_coalesced()方法进行判断。这两种形式并不存在优劣之分,通常也不必太在意它们是哪种方式。在有些情况下uncoalesced效率高,而在有些情况下coalesced效率高。但是,如果你在重复进行一些会产生重复值的操作(比如torch.Tensor.add())时,需要时常将稀疏张量进行coalesce,不然结果会变得非常大。
  

1.4 Working with sparse COO tensors

  下面是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))

  对张量类型进行判断:

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

  获得其sparse_dimdense_dim()的值:

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

  获得indicesvalues张量,coalesced和uncoalesced的方式不一样:

# coalesced
>>> s.indices()
tensor([[0, 1, 1],[2, 0, 2]])
>>> s.values()
tensor([[3, 4],[5, 6],[7, 8]])# uncoalesced
>>> s._indices()
tensor([[0, 1, 1],[2, 0, 2]])
>>> s._values()
tensor([[3, 4],[5, 6],[7, 8]])

  也就是说uncoalesced需要前面加一个_,否则会报错。
  切片操作。COO稀疏张量仅支持dense维度上的切片操作,也即其实是将稀疏表示的张量转换成一般表示的张量之后再执行的切片操作的结果。举个例子:

>>> 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])

  下面分析一下上述代码的输出结果,只要将s转成dense表示的张量,就明白了:

>>> s.to_dense()
tensor([[[0, 0],[0, 0],[3, 4]],[[5, 6],[0, 0],[7, 8]]])

  其中,s[1]的values输出结果也即to_dense()之后结果的下半部分,当然是不包括空值的。然后indices输出结果0和2则是:(1, 0)对应值[5, 6]的坐标,(1, 2)对应值[7, 8]的坐标。
  

2 Sparse CSR Tensor

  CSR (Compressed Sparse Row)格式只支持二维张量的存取,不支持多维张量。但是,与COO格式相比,它有更高的空间存储效率以及更快的运算速度。它由三个一维张量组成:crow_indicescol_indicesvalues。其中,crow_indices用于存储行索引,它的大小为size[0]+1,其中最后一个数字记录了稀疏矩阵中包含多少个specified elements;col_indices记录了每个specified elements的列索引,其大小为nnz(即specified elements个数);values记录的则是每个specified elements的具体值,大小也为nnz。
  可以通过torch.sparse_csr_tensor()方法来构造一个CSR稀疏张量,需要给出crow_indicescol_indicesvalues三个张量,其中crow_indices最后一个指示specified elements个数的数字可以省略,将被自动计算。一个示例:

>>> 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)

  此外,也可以通过tensor.to_sparse_csr()方法将一个普通张量或者是COO稀疏张量转换为一个CSR稀疏张量,其中的0值将被视为fill elements,如下所示:

>>> 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)

  目前pytorch仅支持CSR稀疏张量的tensor.matmul()运算:

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

  

3 Appendix

3.1 Supported Linear Algebra operations

  下表总结了稀疏矩阵上支持的线性代数运算。这里,T[layout]表示具有给定布局的张量。类似地,M[layout]表示矩阵(2-D PyTorch张量),V[layout]表示向量(1-D PyTorch张量)。此外,f表示标量(float或0-D PyTorch张量),*表示元素乘法,@表示矩阵乘法。下表中,Sparse grad?一列指示了该运算是否支持稀疏张量的反向传播梯度计算。


  

3.2 Tensor methods and sparse

  下表是与稀疏张量相关的方法:


  下表是COO稀疏张量所特有的方法:


  下表是CSR稀疏张量所特有的方法:


  下述方法支持COO稀疏张量:


  

3.3 Torch functions specific to sparse Tensors

  下表是只支持稀疏张量的方法:


  下面是一些支持稀疏张量的方法:


  
  更详细内容可参考pytorch官网

pytorch稀疏张量模块torch.sparse详解相关推荐

  1. 【PyTorch系例】torch.Tensor详解和常用操作

    学习教材: 动手学深度学习 PYTORCH 版(DEMO) (https://github.com/ShusenTang/Dive-into-DL-PyTorch) PDF 制作by [Marcus ...

  2. 【PyTorch教程】PyTorch分布式并行模块DistributedDataParallel(DDP)详解

    本期目录 DDP简介 1. 单卡训练回顾 2. 与DataParallel比较 1)DataParallel 2)DistributedDataParallel 3. 多卡DDP训练 本章的重点是学习 ...

  3. 史上最详细的Pytorch版yolov3代码中文注释详解(四)

    史上最详细的Pytorch版yolov3代码中文注释详解(一):https://blog.csdn.net/qq_34199326/article/details/84072505 史上最详细的Pyt ...

  4. Pytorch autograd.grad与autograd.backward详解

    Pytorch autograd.grad与autograd.backward详解 引言 平时在写 Pytorch 训练脚本时,都是下面这种无脑按步骤走: outputs = model(inputs ...

  5. Pytorch的nn.Conv2d()详解

    Pytorch的nn.Conv2d()详解 nn.Conv2d()的使用.形参与隐藏的权重参数 in_channels out_channels kernel_size stride = 1 padd ...

  6. Faster-RCNN.pytorch的搭建、使用过程详解(适配PyTorch 1.0以上版本)

    Faster-RCNN.pytorch的搭建.使用过程详解 引言 faster-rcnn pytorch代码下载 faster-rcnn pytorch配置过程 faster-rcnn pytorch ...

  7. torch.unsqueeze和 torch.squeeze() 详解

    1. torch.unsqueeze 详解 torch.unsqueeze(input, dim, out=None) 作用:扩展维度 返回一个新的张量,对输入的既定位置插入维度 1 注意: 返回张量 ...

  8. python数据集的预处理_关于Pytorch的MNIST数据集的预处理详解

    关于Pytorch的MNIST数据集的预处理详解 MNIST的准确率达到99.7% 用于MNIST的卷积神经网络(CNN)的实现,具有各种技术,例如数据增强,丢失,伪随机化等. 操作系统:ubuntu ...

  9. pytorch教程之nn.Module类详解——使用Module类来自定义网络层

    前言:前面介绍了如何自定义一个模型--通过继承nn.Module类来实现,在__init__构造函数中申明各个层的定义,在forward中实现层之间的连接关系,实际上就是前向传播的过程. 事实上,在p ...

最新文章

  1. 【 MATLAB 】Matlab 帮助文档需要登录问题如何解决?
  2. 中小型研发团队架构实践:电商如何做企业总体架构?
  3. MySQL性能突发事件问题排查技巧
  4. 深度案例 | TO B 企业如何从 0 到 1 实现数据驱动?
  5. cmd.exe启动参数说明
  6. php 判断 跳转url参数,怎么通过链接获取跳转后的url参数
  7. HDU 1160 FatMouse#39;s Speed DP题解
  8. 打开计算机打不开运行错误怎么办,注册表打不开,电脑出错注册表编辑器打不开怎么办?...
  9. 免费Ebook 分享《Silverlight for Windows Phone Toolkit in Depth》
  10. 多级队列调度算法可视化界面_多级反馈队列调度算法
  11. Android TextView 跑马灯效果和 EditText 冲突解决办法
  12. 科研绘图软件GraphPad Prism教程(一)
  13. 解决html中图片自适应屏幕大小的问题
  14. 企业数字化/数智化转型(一):数智力创新2.0
  15. 51CTO学院三周年
  16. CleanMyMac最新版V4.11.4版MAC电脑系统加速器
  17. Apifox:详细使用教程,带你轻松拿捏
  18. 苹果的「AI 建筑师」GAUDI:根据文本生成 3D 场景
  19. 【Scrum模式语言15】发布计划(Release Plan)
  20. 高效团队建设与管理 学习心得

热门文章

  1. Game Framework学习笔记(1):初识Game Framework
  2. seacms_locoy.php,海洋cms 火车头采集发布模块接口,包含视频和文章
  3. (5.17)QQ登入视图
  4. 最小二乘法求回归方程的推导
  5. 用html5写一个母亲节贺卡
  6. 华为云建立网站----容易上手操作链接推荐
  7. 2022年长沙护士资格考试综合练习题及答案
  8. 国人被清朝误导300年
  9. Linux之在CentOS上一次艰难的木马查杀过程
  10. 假设检验、显著性水平、P值、Z值的理解