侯体宗的博客
  • 首页
  • Hyperf版
  • beego仿版
  • 人生(杂谈)
  • 技术
  • 关于我
  • 更多分类
    • 文件下载
    • 文字修仙
    • 中国象棋ai
    • 群聊
    • 九宫格抽奖
    • 拼图
    • 消消乐
    • 相册

PyTorch中Tensor的维度变换实现

Python  /  管理员 发布于 5年前   445

对于 PyTorch 的基本数据对象 Tensor (张量),在处理问题时,需要经常改变数据的维度,以便于后期的计算和进一步处理,本文旨在列举一些维度变换的方法并举例,方便大家查看。

维度查看:torch.Tensor.size()

查看当前 tensor 的维度

举个例子:

>>> import torch>>> a = torch.Tensor([[[1, 2], [3, 4], [5, 6]]])>>> a.size()torch.Size([1, 3, 2])

张量变形:torch.Tensor.view(*args) → Tensor

返回一个有相同数据但大小不同的 tensor。 返回的 tensor 必须有与原 tensor 相同的数据和相同数目的元素,但可以有不同的大小。一个 tensor 必须是连续的 contiguous() 才能被查看。

举个例子:

>>> x = torch.randn(2, 9)>>> x.size()torch.Size([2, 9])>>> xtensor([[-1.6833, -0.4100, -1.5534, -0.6229, -1.0310, -0.8038, 0.5166, 0.9774,     0.3455],    [-0.2306, 0.4217, 1.2874, -0.3618, 1.7872, -0.9012, 0.8073, -1.1238,     -0.3405]])>>> y = x.view(3, 6)>>> y.size()torch.Size([3, 6])>>> ytensor([[-1.6833, -0.4100, -1.5534, -0.6229, -1.0310, -0.8038],    [ 0.5166, 0.9774, 0.3455, -0.2306, 0.4217, 1.2874],    [-0.3618, 1.7872, -0.9012, 0.8073, -1.1238, -0.3405]])>>> z = x.view(2, 3, 3)>>> z.size()torch.Size([2, 3, 3])>>> ztensor([[[-1.6833, -0.4100, -1.5534],     [-0.6229, -1.0310, -0.8038],     [ 0.5166, 0.9774, 0.3455]],    [[-0.2306, 0.4217, 1.2874],     [-0.3618, 1.7872, -0.9012],     [ 0.8073, -1.1238, -0.3405]]])

可以看到 x 和 y 、z 中数据的数量和每个数据的大小都是相等的,只是尺寸或维度数量发生了改变。

压缩 / 解压张量:torch.squeeze()、torch.unsqueeze()

  • torch.squeeze(input, dim=None, out=None)

将输入张量形状中的 1 去除并返回。如果输入是形如(A×1×B×1×C×1×D),那么输出形状就为: (A×B×C×D)

当给定 dim 时,那么挤压操作只在给定维度上。例如,输入形状为: (A×1×B),squeeze(input, 0) 将会保持张量不变,只有用 squeeze(input, 1),形状会变成 (A×B)。

返回张量与输入张量共享内存,所以改变其中一个的内容会改变另一个。

举个例子:

>>> x = torch.randn(3, 1, 2)>>> xtensor([[[-0.1986, 0.4352]],    [[ 0.0971, 0.2296]],    [[ 0.8339, -0.5433]]])>>> x.squeeze().size() # 不加参数,去掉所有为元素个数为1的维度torch.Size([3, 2])>>> x.squeeze()tensor([[-0.1986, 0.4352],    [ 0.0971, 0.2296],    [ 0.8339, -0.5433]])>>> torch.squeeze(x, 0).size() # 加上参数,去掉第一维的元素,不起作用,因为第一维有2个元素torch.Size([3, 1, 2])>>> torch.squeeze(x, 1).size() # 加上参数,去掉第二维的元素,正好为 1,起作用torch.Size([3, 2])

可以看到如果加参数,只有维度中尺寸为 1 的位置才会消失

  • torch.unsqueeze(input, dim, out=None)

返回一个新的张量,对输入的制定位置插入维度 1

返回张量与输入张量共享内存,所以改变其中一个的内容会改变另一个。

如果 dim 为负,则将会被转化 dim+input.dim()+1

接着用上面的数据举个例子:

>>> x.unsqueeze(0).size()torch.Size([1, 3, 1, 2])>>> x.unsqueeze(0)tensor([[[[-0.1986, 0.4352]],     [[ 0.0971, 0.2296]],     [[ 0.8339, -0.5433]]]])>>> x.unsqueeze(-1).size()torch.Size([3, 1, 2, 1])>>> x.unsqueeze(-1)tensor([[[[-0.1986],     [ 0.4352]]],    [[[ 0.0971],     [ 0.2296]]],    [[[ 0.8339],     [-0.5433]]]])

可以看到在指定的位置,增加了一个维度。

扩大张量:torch.Tensor.expand(*sizes) → Tensor

返回 tensor 的一个新视图,单个维度扩大为更大的尺寸。 tensor 也可以扩大为更高维,新增加的维度将附在前面。 扩大 tensor 不需要分配新内存,只是仅仅新建一个 tensor 的视图,其中通过将 stride 设为 0,一维将会扩展位更高维。任何一个一维的在不分配新内存情况下可扩展为任意的数值。

举个例子:

>>> x = torch.Tensor([[1], [2], [3]])>>> x.size()torch.Size([3, 1])>>> x.expand(3, 4)tensor([[1., 1., 1., 1.],    [2., 2., 2., 2.],    [3., 3., 3., 3.]])>>> x.expand(3, -1)tensor([[1.],    [2.],    [3.]])

原数据是 3 行 1 列,扩大后变为 3 行 4 列,方法中填 -1 的效果与 1 一样,只有尺寸为 1 才可以扩大,如果不为 1 就无法改变,而且尺寸不为 1 的维度必须要和原来一样填写进去。

重复张量:torch.Tensor.repeat(*sizes)

沿着指定的维度重复 tensor。 不同于 expand(),本函数复制的是 tensor 中的数据。

举个例子:

>>> x = torch.Tensor([1, 2, 3])>>> x.size()torch.Size([3])>>> x.repeat(4, 2)    [1., 2., 3., 1., 2., 3.],    [1., 2., 3., 1., 2., 3.],    [1., 2., 3., 1., 2., 3.]])>>> x.repeat(4, 2).size()torch.Size([4, 6])

原数据为 1 行 3 列,按行方向扩大为原来的 4 倍,列方向扩大为原来的 2 倍,变为了 4 行 6 列。

变化时可以看成是把原数据作成一个整体,再按指定的维度和尺寸重复,变成一个 4 行 2 列的矩阵,其中的每一个单位都是相同的,再把原数据放到每个单位中。

矩阵转置:torch.t(input, out=None) → Tensor

输入一个矩阵(2维张量),并转置0, 1维。 可以被视为函数 transpose(input, 0, 1) 的简写函数。

举个例子:

>>> x = torch.randn(3, 5)>>> xtensor([[-1.0752, -0.9706, -0.8770, -0.4224, 0.9776],    [ 0.2489, -0.2986, -0.7816, -0.0823, 1.1811],    [-1.1124, 0.2160, -0.8446, 0.1762, -0.5164]])>>> x.t()tensor([[-1.0752, 0.2489, -1.1124],    [-0.9706, -0.2986, 0.2160],    [-0.8770, -0.7816, -0.8446],    [-0.4224, -0.0823, 0.1762],    [ 0.9776, 1.1811, -0.5164]])>>> torch.t(x) # 另一种用法tensor([[-1.0752, 0.2489, -1.1124],    [-0.9706, -0.2986, 0.2160],    [-0.8770, -0.7816, -0.8446],    [-0.4224, -0.0823, 0.1762],    [ 0.9776, 1.1811, -0.5164]])

必须要是 2 维的张量,也就是矩阵,才可以使用。

维度置换:torch.transpose()、torch.Tensor.permute()

  • torch.transpose(input, dim0, dim1, out=None) → Tensor

返回输入矩阵 input 的转置。交换维度 dim0 和 dim1。 输出张量与输入张量共享内存,所以改变其中一个会导致另外一个也被修改。

举个例子:

>>> x = torch.randn(2, 4, 3)>>> xtensor([[[-1.2502, -0.7363, 0.5534],     [-0.2050, 3.1847, -1.6729],     [-0.2591, -0.0860, 0.4660],     [-1.2189, -1.1206, 0.0637]],    [[ 1.4791, -0.7569, 2.5017],     [ 0.0098, -1.0217, 0.8142],     [-0.2414, -0.1790, 2.3506],     [-0.6860, -0.2363, 1.0481]]])>>> torch.transpose(x, 1, 2).size()torch.Size([2, 3, 4])>>> torch.transpose(x, 1, 2)tensor([[[-1.2502, -0.2050, -0.2591, -1.2189],     [-0.7363, 3.1847, -0.0860, -1.1206],     [ 0.5534, -1.6729, 0.4660, 0.0637]],    [[ 1.4791, 0.0098, -0.2414, -0.6860],     [-0.7569, -1.0217, -0.1790, -0.2363],     [ 2.5017, 0.8142, 2.3506, 1.0481]]])>>> torch.transpose(x, 0, 1).size()torch.Size([4, 2, 3])>>> torch.transpose(x, 0, 1)tensor([[[-1.2502, -0.7363, 0.5534],     [ 1.4791, -0.7569, 2.5017]],    [[-0.2050, 3.1847, -1.6729],     [ 0.0098, -1.0217, 0.8142]],    [[-0.2591, -0.0860, 0.4660],     [-0.2414, -0.1790, 2.3506]],    [[-1.2189, -1.1206, 0.0637],     [-0.6860, -0.2363, 1.0481]]])

可以对多维度的张量进行转置

  • torch.Tensor.permute(dims)

将 tensor 的维度换位

接着用上面的数据举个例子:

>>> x.size()torch.Size([2, 4, 3])>>> x.permute(2, 0, 1).size()torch.Size([3, 2, 4])>>> x.permute(2, 0, 1)tensor([[[-1.2502, -0.2050, -0.2591, -1.2189],     [ 1.4791, 0.0098, -0.2414, -0.6860]],    [[-0.7363, 3.1847, -0.0860, -1.1206],     [-0.7569, -1.0217, -0.1790, -0.2363]],    [[ 0.5534, -1.6729, 0.4660, 0.0637],     [ 2.5017, 0.8142, 2.3506, 1.0481]]])

直接在方法中填入各个维度的索引,张量就会交换指定维度的尺寸,不限于两两交换。

 以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。


  • 上一条:
    浅谈Pytorch中的torch.gather函数的含义
    下一条:
    PyTorch中Tensor的拼接与拆分的实现
  • 昵称:

    邮箱:

    0条评论 (评论内容有缓存机制,请悉知!)
    最新最热
    • 分类目录
    • 人生(杂谈)
    • 技术
    • linux
    • Java
    • php
    • 框架(架构)
    • 前端
    • ThinkPHP
    • 数据库
    • 微信(小程序)
    • Laravel
    • Redis
    • Docker
    • Go
    • swoole
    • Windows
    • Python
    • 苹果(mac/ios)
    • 相关文章
    • 在python语言中Flask框架的学习及简单功能示例(0个评论)
    • 在Python语言中实现GUI全屏倒计时代码示例(0个评论)
    • Python + zipfile库实现zip文件解压自动化脚本示例(0个评论)
    • python爬虫BeautifulSoup快速抓取网站图片(1个评论)
    • vscode 配置 python3开发环境的方法(0个评论)
    • 近期文章
    • 在go中实现一个常用的先进先出的缓存淘汰算法示例代码(0个评论)
    • 在go+gin中使用"github.com/skip2/go-qrcode"实现url转二维码功能(0个评论)
    • 在go语言中使用api.geonames.org接口实现根据国际邮政编码获取地址信息功能(1个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf分页文件功能(0个评论)
    • gmail发邮件报错:534 5.7.9 Application-specific password required...解决方案(0个评论)
    • 欧盟关于强迫劳动的规定的官方举报渠道及官方举报网站(0个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf文件功能(0个评论)
    • Laravel从Accel获得5700万美元A轮融资(0个评论)
    • 在go + gin中gorm实现指定搜索/区间搜索分页列表功能接口实例(0个评论)
    • 在go语言中实现IP/CIDR的ip和netmask互转及IP段形式互转及ip是否存在IP/CIDR(0个评论)
    • 近期评论
    • 122 在

      学历:一种延缓就业设计,生活需求下的权衡之选中评论 工作几年后,报名考研了,到现在还没认真学习备考,迷茫中。作为一名北漂互联网打工人..
    • 123 在

      Clash for Windows作者删库跑路了,github已404中评论 按理说只要你在国内,所有的流量进出都在监控范围内,不管你怎么隐藏也没用,想搞你分..
    • 原梓番博客 在

      在Laravel框架中使用模型Model分表最简单的方法中评论 好久好久都没看友情链接申请了,今天刚看,已经添加。..
    • 博主 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 @1111老铁这个不行了,可以看看近期评论的其他文章..
    • 1111 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 网站不能打开,博主百忙中能否发个APP下载链接,佛跳墙或极光..
    • 2016-10
    • 2016-11
    • 2018-04
    • 2020-03
    • 2020-04
    • 2020-05
    • 2020-06
    • 2022-01
    • 2023-07
    • 2023-10
    Top

    Copyright·© 2019 侯体宗版权所有· 粤ICP备20027696号 PHP交流群

    侯体宗的博客