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

news2024/11/26 13:55:06

本文主要讲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.coloradmin.cn/o/1875743.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

优化数据库字段使用位运算-php语言示例

背景&#xff1a;一个会员有三个状态&#xff0c;A、B、C&#xff0c;其中一个人可以为 A、B、C、AB&#xff1b;之前数据表结构加了三个字段is_a、is_b、is_c; 本人实在不想这样粗糙的实现需求&#xff0c;遂决定用位运算优化。 上代码&#xff1a; 位运算可以用来处理状态值…

业务代码插件式开发实践

在学习编程初期&#xff0c;会接触到设计模式的概念&#xff1a;23种设计模式&#xff0c;单例模式&#xff0c;策略模式&#xff0c;… 。接触业务研发后&#xff0c;对设计模式的使用和实践有了更深的见解。 使用设计模式是目的为了更高效的支撑业务诉求&#xff0c;如何在保…

【面试干货】Object 类中的公共方法详解

【面试干货】Object 类中的公共方法详解 1、clone() 方法2、equals(Object obj) 方法3、hashCode() 方法4、getClass() 方法5、wait() 方法6、notify() 和 notifyAll() 方法 &#x1f496;The Begin&#x1f496;点点关注&#xff0c;收藏不迷路&#x1f496; 在 Java 中&#…

高频面试题基本总结回顾1(含笔试高频算法整理)

干货分享&#xff0c;感谢您的阅读&#xff01; &#xff08;暂存篇---后续会删除&#xff0c;完整版和持续更新见高频面试题基本总结回顾&#xff08;含笔试高频算法整理&#xff09;&#xff09; 备注&#xff1a;引用请标注出处&#xff0c;同时存在的问题请在相关博客留言…

如何使用飞书快捷指令无感记账,ios版

总结 很多人无法长期坚持记账&#xff0c;主要是每次消费需要打开手机软件&#xff0c;一系列繁琐的操作&#xff0c;导致过程中可能就忘了。 今天给大家带来飞书自动记账。 演示视频 点击查看&#xff1a;https://www.douyin.com/video/7312857946382241063 安装 下载快捷…

【机器学习300问】135、决策树算法ID3的局限性在哪儿?C4.5算法做出了怎样的改进?

ID3算法是一种用于创建决策树的机器学习算法&#xff0c;该算法基于信息论中的信息增益概念来选择最优属性进行划分。信息增益是原始数据集熵与划分后数据集熵的差值&#xff0c;熵越小表示数据集的纯度越高。有关ID3算法的详细步骤和算法公式在我之前的文章中谈到&#xff0c;…

临时文件上传系统Plik

什么是 Plik &#xff1f; Plik 是一个基于 Go 语言的可扩展且用户友好的临时文件上传系统&#xff08;类似于 Wetransfer&#xff09;。 软件主要特点&#xff1a; 强大的命令行客户端易于使用的 Web 用户界面多个数据后端&#xff1a;文件、OpenStack Swift、S3、Google Clo…

单调队列优化DP——AcWing 135. 最大子序和

单调队列优化DP 定义 单调队列优化DP是一种在动态规划&#xff08;Dynamic Programming, DP&#xff09;中应用的数据结构优化方法。它利用单调队列&#xff08;Monotonic Queue&#xff09;这一数据结构来高效维护一个区间内的最值&#xff08;通常是最大值或最小值&#xf…

特斯拉下一代自动驾驶芯片的深度预测

引言 特斯拉一直以来都在自动驾驶技术上不断突破&#xff0c;随着AI大模型技术的爆发&#xff0c;其下一代自动驾驶芯片&#xff08;HW5.0&#xff09;也备受瞩目。本文将深入分析和预测特斯拉下一代自动驾驶芯片AI5的技术特点及其对行业的影响。 深入技术分析 现有自动驾驶…

【电机控制】EG2134无刷电机驱动板——最小核心板STM32F103C8T6,开环、无感SMO验证

【电机控制】EG2134无刷电机驱动板——最小核心板STM32F103C8T6&#xff0c;开环、无感SMO验证 文章目录 前言一、硬件二、软件三、开环SVPWM四、SMO无感观测器五、参考文献总结 前言 【电机控制】直流有刷电机、无刷电机汇总——持续更新 使用工具&#xff1a; 1.控制器&…

大创项目推荐 题目:基于机器视觉opencv的手势检测 手势识别 算法 - 深度学习 卷积神经网络 opencv python

文章目录 1 简介2 传统机器视觉的手势检测2.1 轮廓检测法2.2 算法结果2.3 整体代码实现2.3.1 算法流程 3 深度学习方法做手势识别3.1 经典的卷积神经网络3.2 YOLO系列3.3 SSD3.4 实现步骤3.4.1 数据集3.4.2 图像预处理3.4.3 构建卷积神经网络结构3.4.4 实验训练过程及结果 3.5 …

linux 文件管理

一、linux文件命名规则 1.可使用字符&#xff1a;所有字符都可使用&#xff0c;不建议使用"<、>、&#xff1f;、*"等特殊字符 正常文件命名规则&#xff1a; 1.尽量使用小写 2.在需要对文件名分割时&#xff0c;建议使用“_”&#xff0c;chen_2004_06_28…

【高中数学之基本不等式】已知:a,b皆为正实数且1/a+1/(b+2)=1/2 求:a+b的最小值?

解&#xff1a;先从1/a1/(b2)1/2 入手&#xff0c;看能否化二为一&#xff08;将两变量化成一个变量&#xff09; 由1/a1/(b2)1/2 两边通分得(b2a)/a/(b2)1/2 交叉相乘得2a2b4ab2a 最后得到a24/b 所以ab24/bb 此时已经可以用基本不等式了 ab24/bb>22*根号下(4/b*b)22…

CSS 核心知识点 - grid

思维导图 参考网址: https://developer.mozilla.org/zh-CN/docs/Web/CSS/CSS_grid_layout 一、什么是 grid&#xff1f; CSS Grid布局是在CSS3规范中引入的一种新的布局方式&#xff0c;旨在解决传统布局方法&#xff08;如浮动、定位、表格布局&#xff09;存在的许多问题。C…

运行CDN

背景 CDN代码&#xff0c;调试运行 日常 git clone代码配置虚拟环境 puthon3.8,pip install r requirements.txt改项目数据集路径&#xff0c;在hico.py文件里面 # PATHS {# train: (root / images / train2015, root / annotations / trainval_hico.json),# val: …

【Python】已解决:ModuleNotFoundError: No module named ‘nltk‘

文章目录 一、分析问题背景二、可能出错的原因三、错误代码示例四、正确代码示例五、注意事项 已解决&#xff1a;ModuleNotFoundError: No module named ‘nltk‘ 一、分析问题背景 在Python编程中&#xff0c;我们常常需要使用第三方库来扩展语言的功能和应用场景。NLTK&am…

DataWhale-吃瓜教程学习笔记(四)

学习视频&#xff1a;第3章-二分类线性判别分析_哔哩哔哩_bilibili 西瓜书对应章节&#xff1a; 3.4 文章目录 - 算法原理- 损失函数推导-- 异类样本中心尽可能远-- 同类样本方差尽可能小-- 综合 知识点补充 - 二范数二范数&#xff08;2-norm&#xff09;详解定义几何意义性质…

Bridging nonnull in Objective-C to Swift: Is It Safe?

Bridging nonnull in Objective-C to Swift: Is It Safe? In the world of iOS development, bridging between Objective-C and Swift is a common practice, especially for legacy codebases (遗留代码库) or when integrating (集成) third-party libraries. One importa…

链表-求链表中环的入口结点(easy)

目录 一、问题描述 二、解题思路 三、代码实现 四、刷题链接 一、问题描述 二、解题思路 本题基本思路&#xff1a; 1.设置一个hashSet来存储已经访问过的链表结点地址&#xff0c;注意不要直接存储链表内元素&#xff0c;因为链表内元素可能存在重复的&#xff0c;地址是不…

APP项目测试 之 开发模型和发布

项目客户端一般分为&#xff1a;浏览器端和APP端 APP端分为&#xff1a;手机端&#xff08;安装在手机上的软件&#xff09;和PC端&#xff08;安装在电脑上的软件&#xff09; 1.开发模型 项目迭代速度不同&#xff1a;开发模型不一样 传统行业&#xff1a;瀑布模型 互联网行业…