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.mfbz.cn/a/758327.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

ISO15765-2 道路车辆——通过控制器局域网(CAN)进行诊断通信 (翻译版)(万字长文)

ISO15765-2 道路车辆——通过控制器局域网&#xff08;CAN&#xff09;进行诊断通信 (翻译版)(万字长文) 文章目录 ISO15765-2 道路车辆——通过控制器局域网&#xff08;CAN&#xff09;进行诊断通信 (翻译版)(万字长文)第二部分&#xff1a;传输协议和网络层服务前言Foreword…

在navicat对mysql声明无符号字段

1.无符号设置 在 MySQL 中&#xff0c;我们可以使用 UNSIGNED 属性来设置列的无符号属性&#xff0c;这意味着该列只能存储非负整数值。对于一些需要存储正整数的列&#xff0c;比如年龄、数量等&#xff0c;使用 UNSIGNED 属性可以提高数据存储和查询的效率&#xff0c;并且能…

浅谈一下VScode如何配置C环境

1.这几天突然发现在VScode写C程序比在DevC效果更好&#xff0c;因为在VScode中写代码有代码补全功能。所以我突然对在VScode中配置C环境变量产生了兴趣。 2.不过在VScode中配置C环境要是按照官方的来配置有点麻烦。 3.我这里有一个直接配置VScode中C环境变量的应用。 前提是…

原来“山水博客“的分类也是可以拖动排序的

这二天一直用“山水博客”写文章&#xff0c;发现一个问题&#xff0c;好象它的分类不能调整位置&#xff0c;这可是个大bug。首先&#xff0c;界面上没发现拖动相关按钮&#xff1b;如果按住分类拖动&#xff0c;会成这样&#xff1a; 后来仔细看了它的文档&#xff0c;发现它…

智能社区服务小程序的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;用户管理&#xff0c;房屋信息管理&#xff0c;住户信息管理&#xff0c;家政服务管理&#xff0c;家政预约管理&#xff0c;报修信息管理 微信端账号功能包括&#xff1a;系统首页&#xff0c;房屋信…

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

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

在vs上远程连接Linux写服务器项目并启动后,可以看到服务启动了,但是通过浏览器访问该服务提示找不到页面

应该是被防火墙挡住了&#xff0c;查看这个如何检查linux服务器被防火墙挡住 • Worktile社区 和这个关于Linux下Nginx服务启动&#xff0c;通过浏览器无法访问的问题_linux无法访问nginx-CSDN博客 的提示之后&#xff0c;知道防火墙开了&#xff0c;想着可能是我写的服务器的…

大数据面试题之Spark(1)

目录 Spark的任务执行流程 Spark的运行流程 Spark的作业运行流程是怎么样的? Spark的特点 Spark源码中的任务调度 Spark作业调度 Spark的架构 Spark的使用场景 Spark on standalone模型、YARN架构模型(画架构图) Spark的yarn-cluster涉及的参数有哪些? Spark提交jo…

c++类成员指针用法

1&#xff09;C入门级小知识&#xff0c;分享给将要学习或者正在学习C开发的同学。 2&#xff09;内容属于原创&#xff0c;若转载&#xff0c;请说明出处。 3&#xff09;提供相关问题有偿答疑和支持。 c中新增类成员指针操作&#xff0c;为了访问方便&#xff0c;他是指…

Spring Boot项目如何配置跨域

1、通过SpringSecurity进行配置 2、前端跨域配置&#xff1a;proxy配置项用于设置代理规则&#xff0c;用于前端开发中与后端API交互时使用。

《HelloGitHub》第 99 期

兴趣是最好的老师&#xff0c;HelloGitHub 让你对编程感兴趣&#xff01; 简介 HelloGitHub 分享 GitHub 上有趣、入门级的开源项目。 github.com/521xueweihan/HelloGitHub 这里有实战项目、入门教程、黑科技、开源书籍、大厂开源项目等&#xff0c;涵盖多种编程语言 Python、…

JS乌龟吃鸡游戏

代码&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>乌龟游戏</title><script type"text/javascript">function move(obj){//乌龟图片高度var wuGui_height 67;…

pikachu靶场 利用Rce上传一句话木马案例(工具:中国蚁剑)

目录 一、准备靶场&#xff0c;进入RCE 二、测试写入文件 三、使用中国蚁剑 一、准备靶场&#xff0c;进入RCE 我这里用的是pikachu 打开pikachu靶场&#xff0c;选择 RCE > exec "ping" 测试是否存在 Rce 漏洞 因为我们猜测在这个 ping 功能是直接调用系统…

这四款软件很好用,可以提升工作、学习效率

TableConvert TableConvert是一个基于Web的在线表格转换工具&#xff0c;能够将多种格式的表格数据进行快速转换。它支持将Excel、URL、HTML、JSON、CSV等格式转换为Markdown表、CSV/TSV、XML、YAML、插入SQL、HTML、Excel和LaTeX等格式。用户只需将表格数据粘贴到编辑器&#…

[C++][设计模式][适配器模式]详细讲解

目录 1.动机2.模式定义3.要点总结4.代码感受 1.动机 在软件系统中&#xff0c;由于应用环境的变化&#xff0c;常常需要将”一些现存的对象“放在新的环境中应用&#xff0c;但是新环境要求的接口是这些现存对象所不满足如何应对这些”迁移的变化“&#xff1f;如何既能利用现…

C语言图书管理系统控制台程序

程序示例精选 C语言图书管理系统控制台程序 如需安装运行环境或远程调试&#xff0c;见文章底部个人QQ名片&#xff0c;由专业技术人员远程协助&#xff01; 前言 这篇博客针对《C语言图书管理系统控制台程序》编写代码&#xff0c;代码整洁&#xff0c;规则&#xff0c;易读…

LabVIEW程序员应该怎么提高自己的工作能力?

作为一名LabVIEW程序员&#xff0c;提升工作能力可以从以下几个方面入手&#xff1a; 1. 深入理解LabVIEW基础 掌握LabVIEW编程语言&#xff1a;熟悉LabVIEW的图形化编程方式&#xff0c;理解其数据流编程模型。熟悉常用的VI&#xff08;虚拟仪器&#xff09;和函数&#xff1…

Flink 从入门到放弃

0 写在前面 程序员闯荡江湖的一生都在与数据打交道&#xff0c;初入江湖时基于 MySQL 的 CRUD&#xff0c;渐入佳境后利用 Redis 实现查询加速及分布式控制&#xff0c;本质上都是数据处理&#xff1b;无论主动/被动&#xff0c;都在利用数据来达成业务/技术目的。自然而然的&a…

The this Pointer (this 指针) and An Array of Objects (对象数组)

The this Pointer [this 指针] and An Array of Objects [对象数组] 1. The this Pointer (this 指针)2. An Array of Objects (对象数组)References 1. The this Pointer (this 指针) class Stock { private:double total_val_;... public:double Total() const { return tot…

详细解释Redis的SET NX命令

详细解释Redis的SET NX命令 SET NX 命令是 Redis 中用于实现分布式锁的一个重要命令。它的语法和用法如下&#xff1a; SET key value NX [EX seconds | PX milliseconds]参数解释 key&#xff1a;要设置的键名。value&#xff1a;要设置的键值&#xff0c;通常用一个唯一标…