PyTorch 提供了 torch.Tensor 来表示一个包含单一数据类型元素的多维数组。 默认情况下,数组元素连续存储在内存中,从而可以有效地实现各种数组处理算法,这些算法依赖于对数组元素的快速访问。

然而,存在一类重要的多维数组,即所谓的稀疏数组,其中数组元素的连续内存存储被证明是次优的。 稀疏数组具有大部分元素为零的特性,这意味着如果仅存储或/和处理非零元素,则可以节省大量内存和处理器资源。

1 构造稀疏矩阵

import torch
i = torch.LongTensor([[0, 1, 1],[2, 0, 2]])   #row, col
v = torch.FloatTensor([3, 4, 5])    #data
torch.sparse.FloatTensor(i, v, torch.Size([2,3])).to_dense()   #torch.Size
'''
tensor([[0., 0., 3.],[4., 0., 5.]])
'''

构造方法和 scipy笔记:scipy.sparse_UQI-LIUWJ的博客-CSDN博客 2.2 coo矩阵 的类似

  • 在 PyTorch 中,稀疏张量的填充值不能明确指定,一般假定为零
  • 但是,存在可能以不同方式解释填充值的操作。 例如,torch.sparse.softmax() 计算 softmax 时假设填充值为负无穷大。

1.1 稀疏COO tensor

  • 在 COO 格式(coordinate)中,指定的元素存储为元素索引和相应值的元组。

    • 元素索引的类型是torch.int64,size是(ndim,nse)
    • 数值类型是任何类型,size是(nse,)
import torchi = [[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.is_sparse
#Trues.layout
#torch.sparse_coo

x坐标为0,y坐标为2的元素是3;x坐标为1,y坐标为1的元素是4.。。。

1.1.0 稀疏矩阵转换成正常Tensor

s.to_dense()
'''
tensor([[0, 0, 3],[4, 0, 5]])
'''

1.1.1 COO tensor和正常tensor(strided tensor)空间复杂度对比

  • COO tensor:ndim*8*nse+<element_size>*nse
  • 正常tensor: <tensor_size>*<element_size>
  • 举例 一个10,000*10,000的 float32 Tensor,其中有100,000个非零元素

    • 正常Tensor的话,需要10 000 * 10 000 * 4 = 400 000 000 比特
    • 使用COO tensor的话,需要(2 * 8 + 4) * 100 000 = 2 000 000比特

1.2.3 创建空的COO tensor

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.4 混合稀疏COO Tensor

  • 我们可以将前面value值为标量的稀疏张量扩展到value值为连续张量的稀疏张量。
  • 这种张量称为混合张量。
    • 元素索引的类型是torch.int64,size是(ndim,nse)
    • 数值类型是任何类型,size是(nse,dense_dims)
  • 对应的稀疏矩阵的维度是n_dim+dense_dims
import torchi = [[0, 1, 1],[2, 0, 2]]v =  [[3,2],[4,1],[5,3]]s = torch.sparse_coo_tensor(i, v, (2, 3,2))
s,s.to_dense()'''
(tensor(indices=tensor([[0, 1, 1],[2, 0, 2]]),values=tensor([[3, 2],[4, 1],[5, 3]]),size=(2, 3, 2), nnz=3, layout=torch.sparse_coo),tensor([[[0, 0],[0, 0],[3, 2]],[[4, 1],[0, 0],[5, 3]]]))
'''

1.2.5 未合并的稀疏COO 张量

  • PyTorch 稀疏 COO 张量格式允许未合并的稀疏张量,其中索引中可能存在重复坐标;
  • 在这种情况下,该索引处的值是所有重复值条目的总和。
  • 例如,可以为同一个索引 1 指定多个值 3 和 4,这会导致未合并张量:
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.coalesce().is_coalesced()
# True
s.to_dense()
#tensor([0, 7, 0])

1.2.6 是否需要合并?

  • 在大多数情况下,不用关心稀疏张量是否被合并,因为在给定合并或未合并稀疏张量的情况下,大多数操作的工作方式相同。
  • 但是,一些操作可以在未合并的张量上更有效地实现,而一些操作可以在合并的张量上更有效地实现。
  • 例如,通过简单地连接索引和值张量来实现稀疏 COO 张量的添加:
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)
'''

1.2.7 查看indice和value

1)不用事先合并

import torchi = [[0, 1, 1],[2, 0, 2]]v =  [3, 4, 5]s = torch.sparse_coo_tensor(i, v, (2, 3))
print(s)
print(s._indices())
print(s._values())'''
tensor(indices=tensor([[0, 1, 1],[2, 0, 2]]),values=tensor([3, 4, 5]),size=(2, 3), nnz=3, layout=torch.sparse_coo)
tensor([[0, 1, 1],[2, 0, 2]])
tensor([3, 4, 5])
'''

2) 需要事先合并

print(s.indices())
print(s.values())'''
RuntimeError                              Traceback (most recent call last)
<ipython-input-27-b4753553cd54> in <module>8 s = torch.sparse_coo_tensor(i, v, (2, 3))9 print(s)
---> 10 print(s.indices())11 print(s.values())RuntimeError: Cannot get indices on an uncoalesced tensor, please call .coalesce() first
'''
print(s.coalesce().indices())
print(s.coalesce().values())
'''
tensor(indices=tensor([[0, 1, 1],[2, 0, 2]]),values=tensor([3, 4, 5]),size=(2, 3), nnz=3, layout=torch.sparse_coo)
tensor([[0, 1, 1],[2, 0, 2]])
tensor([3, 4, 5])
'''

1.2.6 sparse_dim 和dense_dim

一个是index的dim,一个是value的dim

import torchi = [[0, 1, 1],[2, 0, 2]]v =  [3, 4, 5]s = torch.sparse_coo_tensor(i, v, (2, 3))
print(s.sparse_dim(),s.dense_dim())
#(2,0)
i = [[0, 1, 1],[2, 0, 2]]v =  [[3,2],[4,1],[5,3]]s = torch.sparse_coo_tensor(i, v, (2, 3,2))
print(s.sparse_dim(),s.dense_dim())
#(2,1)

1.2.7 切片和索引

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

在sparse维度(index部分)和dense部分(value部分)都可以索引

s[1]
'''
tensor(indices=tensor([[0, 1, 1],[2, 0, 2]]),values=tensor([[3, 2],[4, 1],[5, 3]]),size=(2, 3, 2), nnz=3, layout=torch.sparse_coo)
'''s[1,0,1]
#tensor(1)

切片只能在dense部分切

s[1,0,1:],s[1,0,0:]
#(tensor([1]), tensor([4, 1]))

2 稀疏矩阵的基本运算

基本上都是第一个参数是sparse的,第二个是正常Tensor

先构造两个稀疏矩阵

import torch
i = torch.LongTensor([[0, 1, 1],[2, 0, 2]])   #row, col
v = torch.FloatTensor([3, 4, 5])    #data
x1=torch.sparse.FloatTensor(i, v, torch.Size([2,3]))x1,x1.to_dense()
'''
(tensor(indices=tensor([[0, 1, 1],[2, 0, 2]]),values=tensor([3., 4., 5.]),size=(2, 3), nnz=3, layout=torch.sparse_coo),tensor([[0., 0., 3.],[4., 0., 5.]]))
'''
import torch
i = torch.LongTensor([[0, 1, 1],[1, 0, 1]])   #row, col
v = torch.FloatTensor([3, 4, 5])    #data
x2=torch.sparse.FloatTensor(i, v, torch.Size([3,2]))x2,x2.to_dense()
'''
(tensor(indices=tensor([[0, 1, 1],[1, 0, 1]]),values=tensor([3., 4., 5.]),size=(3, 2), nnz=3, layout=torch.sparse_coo),tensor([[0., 3.],[4., 5.],[0., 0.]]))
'''

2.0 不支持dense * sparse!

pytorch不支持M[strided] @ M[sparse_coo]

如果需要,可以这么整:D @ S == (S.t() @ D.t()).t()

2.1 稀疏矩阵的乘法

2.1.1 torch.mm

只支持第二个参数是dense(即dense*dense,或者sparse*dense),输出是dense

dense*dense
dense*sparse
sparse*sparse
sparse*dense

2.1.2 torch.sparse.mm

同样地,只支持第二个参数是dense(即dense*dense,或者sparse*dense)

dense*dense
dense*sparse
sparse*sparse
sparse*dense

2.1.3 torch.mv

矩阵和向量的乘法,第二个也只能是dense的

import torchi = [[0, 1, 1],[2, 0, 2]]v =  [3, 4, 5]s = torch.sparse_coo_tensor(i, v, (2, 3))
print(s.to_dense())
'''
tensor([[0, 0, 3],[4, 0, 5]])
'''t=torch.LongTensor([1,2,3])
torch.mv(s,t),s@t
'''
(tensor([ 9, 19]), tensor([ 9, 19]))
'''

2.1.4 torch.matmul

和torch.mm 类似,第二个也是只能dense

import torchi = [[0, 1, 1],[2, 0, 2]]v =  [3, 4, 5]s = torch.sparse_coo_tensor(i, v, (2, 3))t=torch.LongTensor([[1],[2],[3]])
torch.matmul(s,t),s@t'''
(tensor([[ 9],[19]]),tensor([[ 9],[19]]))
'''

2.2 转置

t()即可

x2,x2.to_dense()
'''
(tensor(indices=tensor([[0, 1, 1],[1, 0, 1]]),values=tensor([3., 4., 5.]),size=(3, 2), nnz=3, layout=torch.sparse_coo),tensor([[0., 3.],[4., 5.],[0., 0.]]))
'''x2.t(),x2.t().to_dense()'''
(tensor(indices=tensor([[1, 0, 1],[0, 1, 1]]),values=tensor([3., 4., 5.]),size=(2, 3), nnz=3, layout=torch.sparse_coo),tensor([[0., 4., 0.],[3., 5., 0.]]))
'''

2.3 索引

稀疏矩阵支持整行索引,支持Sparse.matrix[row_index];

x2,x2.to_dense()
'''
(tensor(indices=tensor([[0, 1, 1],[1, 0, 1]]),values=tensor([3., 4., 5.]),size=(3, 2), nnz=3, layout=torch.sparse_coo),tensor([[0., 3.],[4., 5.],[0., 0.]]))
'''x2[1],x2[1].to_dense()
'''
(tensor(indices=tensor([[0, 1]]),values=tensor([4., 5.]),size=(2,), nnz=2, layout=torch.sparse_coo),tensor([4., 5.]))
'''

稀疏矩阵不支持具体位置位置索引Sparse.matrix[row_index,col_index]

x2[1][1],x2[1][1].to_dense()

2.4 相加

a = torch.sparse.FloatTensor(torch.tensor([[0,1,2],[2,3,4]]), torch.tensor([1,1,1]), torch.Size([5,5]))
a.to_dense()
'''
tensor([[0, 0, 1, 0, 0],[0, 0, 0, 1, 0],[0, 0, 0, 0, 1],[0, 0, 0, 0, 0],[0, 0, 0, 0, 0]])
'''a1=torch.sparse.FloatTensor(torch.tensor([[0,3,2],[2,3,2]]), torch.tensor([1,1,1]), torch.Size([5,5]))
a1.to_dense()
'''
tensor([[0, 0, 1, 0, 0],[0, 0, 0, 0, 0],[0, 0, 1, 0, 0],[0, 0, 0, 1, 0],[0, 0, 0, 0, 0]])
'''

只支持sparse+sparse

torch.add(a,a1) ,torch.add(a,a1).to_dense()
'''
(tensor(indices=tensor([[0, 1, 2, 3, 2],[2, 3, 4, 3, 2]]),values=tensor([2, 1, 1, 1, 1]),size=(5, 5), nnz=5, layout=torch.sparse_coo),tensor([[0, 0, 2, 0, 0],[0, 0, 0, 1, 0],[0, 0, 1, 0, 1],[0, 0, 0, 1, 0],[0, 0, 0, 0, 0]]))
'''a.add(a1),a.add(a1).to_dense()
#同理

pytorch笔记:torch.sparse类相关推荐

  1. pytorch笔记 torch.clamp(截取上下限)

    1 基本用法 torch.clamp(input, min=None, max=None, *, out=None) 使得tensor中比min小的变成min,比max大的变成max 2 使用举例 i ...

  2. pytorch笔记——torch.randperm用法

    前言 记录randperm用法. 方法介绍 torch.randperm(n) 这个方法将[0, n)中的元素随机排列,函数名randperm是random permutation缩写. permut ...

  3. torch的拼接函数_从零开始深度学习Pytorch笔记(13)—— torch.optim

    前文传送门: 从零开始深度学习Pytorch笔记(1)--安装Pytorch 从零开始深度学习Pytorch笔记(2)--张量的创建(上) 从零开始深度学习Pytorch笔记(3)--张量的创建(下) ...

  4. 【 线性回归 Linear-Regression torch模块实现与源码详解 深度学习 Pytorch笔记 B站刘二大人(4/10)】

    torch模块实现与源码详解 深度学习 Pytorch笔记 B站刘二大人 深度学习 Pytorch笔记 B站刘二大人(4/10) 介绍 至此开始,深度学习模型构建的预备知识已经完全准备完毕. 从本章开 ...

  5. pytorch稀疏张量模块torch.sparse详解

      torch.sparse是一个专门处理稀疏张量的模块.通常,张量会按一定的顺序连续地进行存取.但是,对于一个存在很多空值的稀疏张量来说,顺序存储的效率显得较为低下.因此,pytorch推出了稀疏张 ...

  6. PyTorch 笔记(18)— torch.optim 优化器的使用

    到目前为止,代码中的神经网络权重的参数优化和更新还没有实现自动化,并且目前使用的优化方法都有固定的学习速率,所以优化函数相对简单,如果我们自己实现一些高级的参数优化算法,则优化函数部分的代码会变得较为 ...

  7. PyTorch 笔记(16)— torch.nn.Sequential、torch.nn.Linear、torch.nn.RelU

    PyTorch 中的 torch.nn 包提供了很多与实现神经网络中的具体功能相关的类,这些类涵盖了深度神经网络模型在搭建和参数优化过程中的常用内容,比如神经网络中的卷积层.池化层.全连接层这类层次构 ...

  8. PyTorch 1.0 中文文档:torch.sparse

    译者:hijkzzz 警告 这个API目前还处于试验阶段,可能在不久的将来会发生变化. Torch支持COO(rdinate )格式的稀疏张量,这可以有效地存储和处理大多数元素为零的张量. 稀疏张量表 ...

  9. PYTORCH笔记 actor-critic (A2C)

    理论知识见:强化学习笔记:Actor-critic_UQI-LIUWJ的博客-CSDN博客 由于actor-critic是policy gradient和DQN的结合,所以同时很多部分和policy ...

最新文章

  1. 基于Pytorch的动态卷积复现
  2. Java遗传算法并行多机调度程序
  3. 简单粗暴的入门机器学习
  4. biosrecovery什么意思_BIOS中的每个中文是什么意思
  5. CSS3 Version
  6. sp烘焙流程_烘焙工作流程图
  7. 【函数】fill和fill_n填充之区别
  8. windows server 2008 R2 SP1多国语言包官方下载
  9. 如何清除计算机的u盘使用记录,如何消除电脑上U盘使用记录
  10. 如何将ipad大文件传输到window PC
  11. python的xlwt模块_Python xlwt模块
  12. php仿qq空间网页源码,516 仿QQ空间网页头部代码
  13. ElasticSearch 7.7.0 高级篇-搜索技术
  14. 微软文本转语音实测记录附php/go调用源码
  15. 游戏代理加盟需要什么条件?
  16. 华东师范大学计算机模拟试题,华东师范大学计算机机试真题
  17. 2023超好用的Mac清理优化工具CleanMyMacX
  18. 【行业标准】YBT092-2019-合金铸铁磨球(高中低铬铸造钢球)
  19. 网络基础之Wireshark抓包逐行含义
  20. chrome inspect无法识别到手机解决方案之一

热门文章

  1. iOS手机客户端https请求忽略证书认证
  2. 清华大学参赛计算机集群,清华学生超算团队再获双料冠军
  3. 500左右哪款蓝牙耳机值得推荐?500元蓝牙耳机性价比之王
  4. 关键时刻,为什么人们往往做出错误的选择?
  5. 我相信每个人都有选择自己生活方式的权利 —— 写在美术专栏前面
  6. 中文 哈工大_哈工大讯飞联合实验室发布中文RoBERTawwmext预训练模型
  7. 很好的一款思维导图工具XMind使用教程
  8. 全志T507lcd rbg屏调试
  9. 计算机系统大作业 程序人生-Hello’s P2P From Program to Process
  10. 简单模式匹配算法和KMP算法