PyTorch Tensor进阶操作指南(二):深度学习中的关键技巧

本文主要讲tensor的裁剪、索引、降维和增维

Tensor与numpy互转、Tensor运算等,请看这篇文章

目录

9.1、首先看torch.squeeze()函数:

示例9.1:(基本的使用)

小技巧1:如何看维数

示例9.2:(指定降多少维)

小技巧2:如何理解如size([2,1,2,1,2])等等张量的形状

示例9.3:(不可降维的张量)

9.2、torch.unsqueeze()函数

9.3、torch.view()函数和torch.resize_()函数

十、Tensor的索引

10.1、Tensor的一般索引(共享内存)

10.2、Tensor的高级索引(不共享内存)

理解辅助:

小技巧:什么是共享内存?

python列表的共享内存:

张量的一般索引或高级索引得出的张量是否共享内存:

十一、Tensor梯度裁剪

torch.clamp(tensor,min,max,out=None)函数:


本文主要讲tensor的裁剪、索引、降维和增维。同时详细讲了入门者的痛点就是看不懂tensor的size表示或者看不懂其内部结构,并且补充了一个大多数人都不知道的增、降维的方法,索引位置如何理解等

九、Tensor的降维和增维

我们常见的用于tensor的维数操作有很多如

torch.squeeze()
可降维、
torch.unsqueeze()
可增维

,下面我们通过一些例子简介两个函数

9.1、首先看

torch.squeeze()

函数:

示例9.1:(基本的使用)
import torch as t
a=t.ones(2,1,2,1,2)
print("a==",a)
print("a.size()==",a.size())
b=t.squeeze(a)
print("b==",b)
print("b.size()==",b.size())

运行结果:

a== tensor([[[[[1., 1.]],

[[1., 1.]]]],

[[[[1., 1.]],

[[1., 1.]]]]])

a.size()== torch.Size([2, 1, 2, 1, 2])

b== tensor([[[1., 1.],

[1., 1.]],

[[1., 1.],

[1., 1.]]])

b.size()== torch.Size([2, 2, 2])

小技巧1:如何看维数

一般我们可以直接认为
( 后面有多少个 [ 就是多少维
,如上面的示例9.1的a我们数一下发现其 ( 后面有5个 [ 那么我们可以说它是一个五维的张量或者说是一个五阶的矩阵,再如示例9.1的b,他是一个三维的张量,我们发现在用了一次
torch.squeeze()
函数就降了两维,那如果我只需要降一维要怎么操作呢?下面示例9.2操作一下:

示例9.2:(指定降多少维)
import torch as t
a=t.ones(2,1,2,1,2)
print("a==",a)
print("a.size()==",a.size())
b=t.squeeze(a,1)
print("b==",b)
print("b.size()==",b.size())
c=t.squeeze(a,0)
print("c==",c)
print("c.size()==",c.size())

运行结果:

a== tensor([[[[[1., 1.]],

[[1., 1.]]]],

[[[[1., 1.]],

[[1., 1.]]]]])

a.size()== torch.Size([2, 1, 2, 1, 2])

b== tensor([[[[1., 1.]],

[[1., 1.]]],

[[[1., 1.]],

[[1., 1.]]]])

b.size()== torch.Size([2, 2, 1, 2])

c== tensor([[[[[1., 1.]],

[[1., 1.]]]],

[[[[1., 1.]],

[[1., 1.]]]]])

c.size()== torch.Size([2, 1, 2, 1, 2])

小结:

由示例9.2我们可以看出
torch.squeeze(input,dim=None)
函数的参数dim当指定值
为0时则不进行降维操作

若为1,则降一维
;那么在这里我们要降多少维就用多少次就可以啦

小技巧2:如何理解如size([2,1,2,1,2])等等张量的形状

在上面两个例子中如果你看torch.Size([2, 1, 2, 1, 2])这些一脸懵逼,看不出来是几维异或看不出来这个张量的结构是怎么样的,请看看我的理解,入门你可以认为
这里 [] 里面多少个数字就是多少维
那么怎么看这个张量的形状或者说行和列是怎么个构成呢?比如一个张量torch.Size([a, b, c, d, e])

那么这就是

一个有a个元素的五维张量,这a个元素均是四维张量,一个四维张量又由b个三维张量组成,一个三维张量由c个二维张量组成,这个二维张量的形状为d*e即d行e列

如示例9.2的c

那么你发现规律了吗?

从这个图例也可以很好理解

再如torch.Size([1, 2, 3, 4, 5])就是一个有1个元素的五维张量,这1个元素均是四维张量,一个四维张量又由2个三维张量组成,一个三维张量由3个二维张量组成,这个二维张量的形状为4*5即4行5列

看看输出:

tensor([[[[[1., 1., 1., 1., 1.],

[1., 1., 1., 1., 1.],

[1., 1., 1., 1., 1.],

[1., 1., 1., 1., 1.]],

[[1., 1., 1., 1., 1.],

[1., 1., 1., 1., 1.],

[1., 1., 1., 1., 1.],

[1., 1., 1., 1., 1.]],

[[1., 1., 1., 1., 1.],

[1., 1., 1., 1., 1.],

[1., 1., 1., 1., 1.],

[1., 1., 1., 1., 1.]]],

[[[1., 1., 1., 1., 1.],

[1., 1., 1., 1., 1.],

[1., 1., 1., 1., 1.],

[1., 1., 1., 1., 1.]],

[[1., 1., 1., 1., 1.],

[1., 1., 1., 1., 1.],

[1., 1., 1., 1., 1.],

[1., 1., 1., 1., 1.]],

[[1., 1., 1., 1., 1.],

[1., 1., 1., 1., 1.],

[1., 1., 1., 1., 1.],

[1., 1., 1., 1., 1.]]]]])

那么是不是所有的张量都可以用进行降维呢?显然不是,在上面的例子中我们就可以看出被降的维数都是只有一个元素的,下面一个例子说明:

示例9.3:(不可降维的张量)
import torch as t
a=t.ones(2,2,2).squeeze(1)
b=t.ones(1,2,2).squeeze(1)
c=t.ones(2,1,2).squeeze(1)
print(b)
print("a.shape=={}\nb.shape=={}\nc.shape=={}\n".format(a.shape,b.shape,c.shape))

运行结果:

tensor([[[1., 1.],

[1., 1.]]])

a.shape==torch.Size([2, 2, 2])

b.shape==torch.Size([1, 2, 2])

c.shape==torch.Size([2, 2])


9.2、torch.unsqueeze()函数


torch.squeeze(input,dim=None)
函数使用方法类似

import torch as t
a=t.ones(2,2,2).unsqueeze(1)
b=t.ones(1,2,2).unsqueeze(2)
c=t.ones(2,1,2)
d=t.unsqueeze(c,0)#与d=t.ones(2,1,2).unsqueeze(0)同
print("a.shape=={}\nb.shape=={}\nd.shape=={}\n".format(a.shape,b.shape,d.shape))

运行结果:

a.shape==torch.Size([2, 1, 2, 2])

b.shape==torch.Size([1, 2, 1, 2])

d.shape==torch.Size([1, 2, 1, 2])

9.3、torch.view()函数和

torch.resize_()函数

不知道大家发现没有在
上一篇
中torch.view()函数和torch.resize_()函数也可以实现增、降维的能力

但不推荐在实际中增、降维用torch.resize_()函数,因为它会会为Tensor自动分配新的内存空间,所以下面将示例torch.view()函数,而torch.resize_()函数使用方法基本一致可自行测试

示例:

import torch as t
a=t.linspace(-1,1,10)
b=a.view(10,1)
c=a.view(1,2,5)
d=c.view(5,2)
print("a.shape=={}\nb.shape=={}\nc.shape=={}\nd.shape=={}\n".format(a.shape,b.shape,c.shape,d.shape))
print("a=={}\nb=={}\nc=={}\nd=={}\n".format(a,b,c,d))

运行结果:

a.shape==torch.Size([10])

b.shape==torch.Size([10, 1])

c.shape==torch.Size([1, 2, 5])

d.shape==torch.Size([5, 2])

a==tensor([-1.0000, -0.7778, -0.5556, -0.3333, -0.1111,  0.1111,  0.3333,  0.5556,

0.7778,  1.0000])

b==tensor([[-1.0000],

[-0.7778],

[-0.5556],

[-0.3333],

[-0.1111],

[ 0.1111],

[ 0.3333],

[ 0.5556],

[ 0.7778],

[ 1.0000]])

c==tensor([[[-1.0000, -0.7778, -0.5556, -0.3333, -0.1111],

[ 0.1111,  0.3333,  0.5556,  0.7778,  1.0000]]])

d==tensor([[-1.0000, -0.7778],

[-0.5556, -0.3333],

[-0.1111,  0.1111],

[ 0.3333,  0.5556],

[ 0.7778,  1.0000]])

十、Tensor的索引

10.1、Tensor的一般索引(共享内存)

Tensor的索引与列表索引相似

import torch as t
a=t.arange(0,6).view(2,3)
print("a={}\na[0]={}\na[:,0]={}\na[:2]={}\na[:1,:1]={}\n".format(a,a[0],a[:,0],a[:2],a[:1,:1]))

运行结果:

a=tensor([[0, 1, 2],

[3, 4, 5]])

a[0]=tensor([0, 1, 2])

a[:,0]=tensor([0, 3])

a[:2]=tensor([[0, 1, 2],

[3, 4, 5]])

a[:1,:1]=tensor([[0]])

小结:可以看见上述示例中张量的索引方式为:a[Rows,Columns] ,这种方式对于三维等也是可以的,对于精准到一个单一元素可以加一参数,如:

import torch as t
a=t.arange(0,18).view(2,3,3)
print("a={}\na[0]={}\na[1,1,2]={}\na[1,2,0]={}\na[:1,:1]={}\n".format(a,a[0],a[1,1,2],a[1,2,0],a[:1,:1]))

运行结果:

a=tensor([[[ 0,  1,  2],

[ 3,  4,  5],

[ 6,  7,  8]],

[[ 9, 10, 11],

[12, 13, 14],

[15, 16, 17]]])

a[0]=tensor([[0, 1, 2],

[3, 4, 5],

[6, 7, 8]])

a[1,1,2]=14

a[1,2,0]=15

a[:1,:1]=tensor([[[0, 1, 2]]])

小结:由上面的例子可以看见,对于三维张量索引时,a[Rows,Columns,index],不一样的就是此时只a[Rows,Columns]得到的是一个一维张量而不是一个元素,所以再加一个元素的索引就可以达到单一元素,四维张量也是类似

10.2、Tensor的高级索引(不共享内存)

import torch as t
a=t.arange(0,18).view(2,3,3)
print("a={}\na[[0,1],...]={}\na[[1,0],[1,2],[2,2]]={}\na[[0,1,1],[2],[1]]={}\n".format(a,a[[0,1],...],a[[1,0],[1,2],[2,2]],a[[0,1,1],[2],[1]]))

运行结果:

a=tensor([[[ 0,  1,  2],

[ 3,  4,  5],

[ 6,  7,  8]],

[[ 9, 10, 11],

[12, 13, 14],

[15, 16, 17]]])

a[[0,1],…]=tensor([[[ 0,  1,  2],    //##相当于a[0] and a[1] 即输出第一、二行

[ 3,  4,  5],

[ 6,  7,  8]],

[[ 9, 10, 11],

[12, 13, 14],

[15, 16, 17]]])

a[[1,0],[1,2],[2,2]]=tensor([14,  8])  //##相当于a[1,1,2] and a[0,2,2]

a[[0,1,1],[2],[1]]=tensor([ 7, 16, 16])  //##相当于a[0,2,1] and a[1,2,1] and a[1,2,1]

理解辅助:

由上图可见,一个三维张量
行 是一个二维张量,列是一个一维张量,那么index就是这个一维张量里面的元素啦!

小结:一维索引一个参数,二维索引两个参数,三维索引三个参数

小技巧:什么是共享内存?

python列表的共享内存:

有python编程基础的朋友应该都看过下面这个例子:

a=[1,2,3,4,5,6]

b=a

b[1]=10

a

[1, 10, 3, 4, 5, 6]

由上面的例子中我们不难看出来,python列表中将一个已经存在的列表(a)赋给另一个列表(b)得出列表(b)是和原列表()共用一块内存的,共用即说明这
两个列表无论是修改哪一个的元素值,另一个也会随着变化
,就比如上面的列表a,b,改变b的值a也会变,同样改变a,b也变,大家可以之行测试一下

张量的一般索引或高级索引得出的张量是否共享内存:

直接上例子:

import torch as t
a=t.arange(0,9).view(3,3)
b=a[1]
c=a[[1],...]
print("未改变前a:\n{}".format(a))
b[0]=100
print("改变一般索引得出张量b的值,此时a:\n{}".format(a))
c[0]=1000
print("改变一般索引得出张量c的值,此时a:\n{}".format(a))

运行结果:

未改变前a:

tensor([[0, 1, 2],

[3, 4, 5],

[6, 7, 8]])

改变一般索引得出张量b的值,此时a:

tensor([[  0,   1,   2],

[100,   4,   5],

[  6,   7,   8]])

改变一般索引得出张量c的值,此时a:

tensor([[  0,   1,   2],

[100,   4,   5],

[  6,   7,   8]])

可见改变张量b时张量a随着改变,而改变c时a保持原来的值,即

张量的一般索引与原张量共享内存,而张量的高级索引与原张量一般不共享内存

划重点:共享内存的两个列表一般内存地址相同,而共享内存的两个张量内存地址一般不相同

十一、Tensor梯度裁剪

torch.clamp(tensor,min,max,out=None)函数:

逐个比对tensor里面的元素,当tensor的一个元素<min,返回min

当 min<= tensor的一个元素 <=max,返回tensor的对应元素

当tensor的一个元素>max,返回max

示例如下:

import torch as t
a=t.arange(0,6).view(2,3)
b=t.clamp(a,3)
c=t.clamp(a,2,5)
print("a={}\nb={}\nc={}\n".format(a,b,c))

运行结果:

a=tensor([[0, 1, 2],

[3, 4, 5]])

b=tensor([[3, 3, 3],

[3, 4, 5]])

c=tensor([[2, 2, 2],

[3, 4, 5]])

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/364567.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

全球海洋平均质量变化的时间序海洋、冰和水文等效水高数据集

Tellus Level-4 Antarctica Mass Anomaly Time Series from JPL GRACE/GRACE-FO Mascon CRI Filtered Release 06.1 version 03 从 JPL GRACE/GRACE-FO Mascon CRI 过滤发布的 Tellus Level-4 南极洲质量异常时间序列 06.1 版本 03 简介 该数据集是全球海洋平均质量变化的时…

水果品牌网站开展如何拓宽渠道

对大多数人来说&#xff0c;零售买水果只在乎是买什么水果、哪个产地、价格等因此&#xff0c;对品牌的依赖度相对较低。但对于水果品牌公司来说&#xff0c;货好仅是基本&#xff0c;还需要将品牌发展出去、能获取准属性客户和转化路径。 与零售不同&#xff0c;批发生意或是…

本末倒置!做660+880一定要避免出现这3种情况!

每年都有不少人做过660题&#xff0c;但是做过之后&#xff0c;并没有真正理解其中的题目&#xff0c;所以做过之后效果也不好&#xff01;再去做880题&#xff0c;做的也会比较吃力。 那该怎么办呢&#xff0c;不建议你继续做880题&#xff0c;先把660给吃透再说。 接下来给…

【01-02】Mybatis的配置文件与基于XML的使用

1、引入日志 在这里我们引入SLF4J的日志门面&#xff0c;使用logback的具体日志实现&#xff1b;引入相关依赖&#xff1a; <!--日志的依赖--><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId><version&g…

计算神经网络中梯度的核心机制 - 反向传播(backpropagation)算法(1)

计算神经网络中梯度的核心机制 - 反向传播&#xff08;backpropagation&#xff09;算法&#xff08;1&#xff09; flyfish 链式法则在深度学习中的主要应用是在反向传播&#xff08;backpropagation&#xff09;算法中。 从简单的开始 &#xff0c;文本说的就是链式法则 R …

安卓应用开发学习:获取经纬度及地理位置描述信息

前段时间&#xff0c;我在学习鸿蒙应用开发的过程中&#xff0c;在鸿蒙系统的手机上实现了获取经纬度及地理位置描述信息&#xff08;鸿蒙应用开发学习&#xff1a;手机位置信息进阶&#xff0c;从经纬度数据获取地理位置描述信息&#xff09;。反而学习时间更长的安卓应用开发…

计算机视觉全系列实战教程 (十四):图像金字塔(高斯金字塔、拉普拉斯金字塔)

1.图像金字塔 (1)下采样 从G0 -> G1、G2、G3 step01&#xff1a;对图像Gi进行高斯核卷积操作&#xff08;高斯滤波&#xff09;step02&#xff1a;删除所有的偶数行和列 void cv::pyrDown(cv::Mat &imSrc, //输入图像cv::Mat &imDst, //下采样后的输出图像cv::Si…

第一节:如何开发第一个spring boot3.x项目(自学Spring boot 3.x的第一天)

大家好&#xff0c;我是网创有方&#xff0c;从今天开始&#xff0c;我会记录每篇我自学spring boot3.x的经验。只要我不偷懒&#xff0c;学完应该很快&#xff0c;哈哈&#xff0c;更新速度尽可能快&#xff0c;想和大佬们一块讨论&#xff0c;如果需要讨论的欢迎一起评论区留…

零基础开始学习鸿蒙开发-页面导航栏布局设计

1.设定初始页(Idex.ets) import {find} from ../pages/find import {home} from ../pages/home import {setting} from ../pages/setting Entry Component struct Index {private controller: TabsController new TabsController()State gridMargin: number 10State gridGut…

[图解]建模相关的基础知识-19

1 00:00:00,640 --> 00:00:04,900 前面讲了关系的这些范式 2 00:00:06,370 --> 00:00:11,570 对于我们建模思路来说&#xff0c;有什么样的作用 3 00:00:12,660 --> 00:00:15,230 我们建模的话&#xff0c;可以有两个思路 4 00:00:16,790 --> 00:00:20,600 一个…

项目实训-接口测试(十八)

项目实训-后端接口测试&#xff08;十八&#xff09; 文章目录 项目实训-后端接口测试&#xff08;十八&#xff09;1.概述2.测试对象3.测试一4.测试二 1.概述 本篇博客将记录我在后端接口测试中的工作。 2.测试对象 3.测试一 这段代码是一个单元测试方法&#xff0c;用于验证…

二叉树从根节点出发的所有路径

二叉树从根节点出发的所有路径 看上图中 二叉树结构 从根节点出发的所有路径 如下 6->4->2->1 6->4->2->3 6->4->5 6->8->7 6->8->9 逻辑思路&#xff1a; 按照先序遍历 加 回溯法 实现 代码如下 // 调用此方法&#xff0c;将根节点传递…

【Lua】第二篇:打印函数和注释

文章目录 一. 打印函数二. 注释方式1. 单行注释2. 多行注释 一. 打印函数 Lua 程序是以 .lua 结尾的文件&#xff0c;创建一个的 Test.lua 的文件&#xff0c;使用 print 函数输出字符串"Hello World"&#xff1a; print(Hello World) 保存之后使用命令lua 文件名编…

安卓开发自定义时间日期显示组件

安卓开发自定义时间日期显示组件 问题背景 实现时间和日期显示&#xff0c;左对齐和对齐两种效果&#xff0c;如下图所示&#xff1a; 问题分析 自定义view实现一般思路&#xff1a; &#xff08;1&#xff09;自定义一个View &#xff08;2&#xff09;编写values/attrs.…

如何用Go语言,实现基于宏系统的解释器?

目录 一、Go语言介绍二、什么是宏系统三、什么是解释器四、如何用Go语言实现一个基于宏系统的解释器&#xff1f; 一、Go语言介绍 Go语言&#xff0c;又称为Golang&#xff0c;是一种由谷歌公司开发并开源的编程语言。Go语言的设计目标是提高程序员的生产力&#xff0c;同时具…

Oracle、MySQL、PostGreSQL、SQL Server-空值

Oracle、MySQL、PostGreSQL、SQL Server-null value 最近几年数据库市场百花齐放&#xff0c;在做跨数据库迁移的数据库选型时&#xff0c;除了性能、稳定、安全、运维、功能、可扩展外&#xff0c;像开发中对于值的处理往往容易被人忽视&#xff0c; 之前写过一篇关于PG区别O…

2024年6月26日 (周三) 叶子游戏新闻

老板键工具来唤去: 它可以为常用程序自定义快捷键&#xff0c;实现一键唤起、一键隐藏的 Windows 工具&#xff0c;并且支持窗口动态绑定快捷键&#xff08;无需设置自动实现&#xff09;。 土豆录屏: 免费、无录制时长限制、无水印的录屏软件 《Granblue Fantasy Versus: Risi…

Cisco Identity Services Engine (ISE) 3.3 Patch 2 - 基于身份的网络访问控制和策略实施系统

Cisco Identity Services Engine (ISE) 3.3 Patch 2 - 基于身份的网络访问控制和策略实施系统 思科身份服务引擎 (ISE) - 下一代 NAC 解决方案 请访问原文链接&#xff1a;Cisco Identity Services Engine (ISE) 3.3 Patch 2 - 基于身份的网络访问控制和策略实施系统&#xf…

笔灵AI写作:释放创意,提升写作效率的秘诀

内容为王&#xff0c;在内容创作的世界中尤为重要。然而&#xff0c;面对写作时常常感到无从下手&#xff1a;有时缺乏灵感&#xff0c;有时难以表达清楚自己的想法。AI写作助手的出现&#xff0c;为这些问题提供了创新的解决方案&#xff0c;极大地改变了内容创作的过程。 今…

STM32——使用TIM输出比较产生PWM波形控制舵机转角

一、输出比较简介&#xff1a; 只有高级定时器和通用寄存器才有输入捕获/输出比较电路&#xff0c;他们有四个CCR&#xff08;捕获/比较寄存器&#xff09;&#xff0c;共用一个CNT&#xff08;计数器&#xff09;&#xff0c;而输出比较功能是用来输出PWM波形的。 红圈部分…