新手小白的pytorch学习第三弹-------tensor的基本操作

  1. reshape, view, stacking, squeeze(), unsqueeze(),permute()
  2. torch.tensor 和 numpy 的 array
  3. 切片,张量里面获取元素值
  4. 随机种子

1 导入torch

import torch

2 reshape()

tensor_A = torch.arange(1, 11)
tensor_A

tensor_A.reshape(2, 5)

tensor_A.reshape(2, 5)

tensor([[ 1, 2, 3, 4, 5],
[ 6, 7, 8, 9, 10]])

tensor_A.reshape(1, 10)

tensor([[ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]])

tensor_A.reshape(10, 1)

tensor([[ 1],
[ 2],
[ 3],
[ 4],
[ 5],
[ 6],
[ 7],
[ 8],
[ 9],
[10]])

tensor_A.reshape(1, 9)

在这里插入图片描述##### 发现了吗? tensor_A 的每一个成功的reshape,括号中元素乘积都等于 tensor_A 中元素的个数(10)

而失败的 reshape 的乘积为 9 ,所以失败了
告诉我们元素要兼容,就是我可以将你这个 tensor 换个形状, 但你不能多元素也不能少元素, 就是说不能无中生有,也不能顺手牵羊

3 view

tensor_C = torch.arange(1, 10)
tensor_C

tensor([1, 2, 3, 4, 5, 6, 7, 8, 9])

x = tensor_C.view(3, 3)
x

tensor([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])

print(tensor_C, tensor_C.shape)
tensor_reshaped = tensor_C.reshape(3, 3)
tensor_viewed = tensor_C.view(3,3)
print(tensor_C, tensor_C.shape)
print(tensor_reshaped, tensor_reshaped.shape)
print(tensor_viewed, tensor_viewed.shape)

tensor([1, 2, 3, 4, 5, 6, 7, 8, 9]) torch.Size([9])
tensor([1, 2, 3, 4, 5, 6, 7, 8, 9]) torch.Size([9])
tensor([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]]) torch.Size([3, 3])
tensor([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]]) torch.Size([3, 3])

我刚开始还是没看出来 view和 reshape的区别,因为你看,是不是都将原来的张量的形状改变了
x = tensor_C.view(1, 9)
x

tensor([[1, 2, 3, 4, 5, 6, 7, 8, 9]])

好,接下来我们改变 x 中的值,注意这里的 x 是 view 之后的值
x[:,8] = 500
x, tensor_C

(tensor([[ 1, 2, 3, 4, 5, 6, 7, 8, 500]]),
tensor([ 1, 2, 3, 4, 5, 6, 7, 8, 500]))

发现了不, 我改变 view 之后的张量的值,原来的 tensor_C 张量的值也发生了改变,提问:这说明了什么?哎,这说明了什么?
答:这说明了我们俩改的就是同一个东西,即改的内容是内存中同一个地址单元的值
没错,这就是 view 和 reshape 在改变张量形状之间的区别,好,我们用 reshape 做个实验瞅瞅
tensor_D = torch.arange(1, 10)
tensor_D

tensor([1, 2, 3, 4, 5, 6, 7, 8, 9])

y = tensor_D.reshape(3, 3)
y

tensor([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])

ok, 咱么来改变一下 y 的值,看看原来的 tensor_D 有没有变化, 有变化说明什么?哎,对,说明和view一样
没有变化呢,对,没错,没有变化就说明他俩的区别,一个表示同一个内存里的值, 一个啥也不是,简单的改变一下形状
y[2:3] = 500
y, tensor_D
不是,怎么 reshape 和 view 一样啊
反正在这里看是一样的,等之后遇到问题再说吧,这里的数据都是连续的昂,注意注意

(tensor([[ 1, 2, 3],
[ 4, 5, 6],
[500, 500, 500]]),
tensor([ 1, 2, 3, 4, 5, 6, 500, 500, 500]))

4 stacking

让我们来学习一下张量的堆叠

先创建一个我们需要堆叠的张量
z = torch.arange(2, 50, step=10)
z

tensor([ 2, 12, 22, 32, 42])

这里要注意, torch.stack(), 第一个参数是一个 tuple, 要堆叠多少个张量就填几个该张量
tensor_stacked = torch.stack((z,z,z,z,z), dim=0)
tensor_stacked

tensor([[ 2, 12, 22, 32, 42],
[ 2, 12, 22, 32, 42],
[ 2, 12, 22, 32, 42],
[ 2, 12, 22, 32, 42],
[ 2, 12, 22, 32, 42]])

可以看出来, dim=0,表示是堆叠行
tensor_stacked = torch.stack((z, z, z, z), dim=1)
tensor_stacked

tensor([[ 2, 2, 2, 2],
[12, 12, 12, 12],
[22, 22, 22, 22],
[32, 32, 32, 32],
[42, 42, 42, 42]])

dim=1, 表示堆叠列
tensor_stacked = torch.stack((z, z, z, z), dim=2)
tensor_stacked

在这里插入图片描述

好,这里试验了一下,报错了,说是[-2,1]之间, 咱们试试看看
tensor_stacked = torch.stack((z, z, z, z), dim=-2)
tensor_stacked

tensor([[ 2, 12, 22, 32, 42],
[ 2, 12, 22, 32, 42],
[ 2, 12, 22, 32, 42],
[ 2, 12, 22, 32, 42]])

tensor_stacked = torch.stack((z, z, z, z), dim=-1)
tensor_stacked

tensor([[ 2, 2, 2, 2],
[12, 12, 12, 12],
[22, 22, 22, 22],
[32, 32, 32, 32],
[42, 42, 42, 42]])

从上面的代码和实验结果,咱们不难发现,dim = -2 和 dim = 0是一样的, dim = -1 和 dim = 1是一样的,好记好记得,两个1是列就可以啦

5 squeeze()

去掉单维,使得张量中只有高于一维的
a = torch.ones(1, 3, 3)
a, a.shape

(tensor([[[1., 1., 1.],
[1., 1., 1.],
[1., 1., 1.]]]),
torch.Size([1, 3, 3]))

tensor_squeezed = a.squeeze()
tensor_squeezed, tensor_squeezed.shape

(tensor([[1., 1., 1.],
[1., 1., 1.],
[1., 1., 1.]]),
torch.Size([3, 3]))

看见没,两个张量的 shape 中,是不是 squeeze 之后,单维的没了,就是为 1 的没了
咱们再试一个看看
b = torch.rand(1, 1, 1, 3, 4)
b, b.shape

(tensor([[[[[0.1872, 0.7857, 0.0147, 0.0184],
[0.7243, 0.0842, 0.8350, 0.3980],
[0.6132, 0.1699, 0.5776, 0.1239]]]]]),
torch.Size([1, 1, 1, 3, 4]))

tensor_squeezed = b.squeeze()
tensor_squeezed, tensor_squeezed.shape

(tensor([[0.1872, 0.7857, 0.0147, 0.0184],
[0.7243, 0.0842, 0.8350, 0.3980],
[0.6132, 0.1699, 0.5776, 0.1239]]),
torch.Size([3, 4]))

6 unsqueeze()

张量的扩张,咱们来看看咋扩张的呢
tensor_unsqueezed = tensor_squeezed.unsqueeze(dim=0)
tensor_unsqueezed, tensor_unsqueezed.shape

(tensor([[[0.1872, 0.7857, 0.0147, 0.0184]],

     [[0.7243, 0.0842, 0.8350, 0.3980]],

     [[0.6132, 0.1699, 0.5776, 0.1239]]]),

torch.Size([3, 1, 4]))

tensor_unsqueezed = tensor_squeezed.unsqueeze(dim=1)
tensor_unsqueezed, tensor_unsqueezed.shape

(tensor([[[0.1872, 0.7857, 0.0147, 0.0184]],
[[0.7243, 0.0842, 0.8350, 0.3980]],
[[0.6132, 0.1699, 0.5776, 0.1239]]]),
torch.Size([3, 1, 4]))

tensor_unsqueezed = tensor_squeezed.unsqueeze(dim=2)
tensor_unsqueezed, tensor_unsqueezed.shape

(tensor([[[0.1872],
[0.7857],
[0.0147],
[0.0184]],

[[0.7243],
[0.0842],
[0.8350],
[0.3980]],

[[0.6132],
[0.1699],
[0.5776],
[0.1239]]]),
torch.Size([3, 4, 1]))

tensor_unsqueezed = tensor_squeezed.unsqueeze(dim=3)
tensor_unsqueezed, tensor_unsqueezed.shape

在这里插入图片描述

好,相信通过实验都懂了,unsqueeze(dim = ) 这个函数中必须要有dim的值,同时注意 dim 的范围
这个范围也很好理解,看我们刚开始的张量形状是 torch.Size([3, 4]) 3的维度是0, 4的维度是1,
那我们选择一个地方插入一维向量,0就插入最左边, 1就插入中间,2就插入最右边,相信很好理解啊

7 torch.permute(input, dims)

作用是调换三个维度的值,看例子咱们就瞬间明白了
tensor = torch.rand(size=(224, 224, 3)) # weight, height, color_channel
tensor_permuted = torch.permute(tensor, (2, 0, 1))
print(f"tensor shape:{tensor.shape}")
print(f"tensor_permuted shape:{tensor_permuted.shape}")

tensor shape:torch.Size([224, 224, 3])
tensor_permuted shape:torch.Size([3, 224, 224])

看结果是不是调换顺序啦!对,torch.permute(input, dims) 就是这个意思
torch.tensor 和 numpy 的 array
torch.form_numpy(ndarry) numpy array-> tensor
torch.Tensor.numpy() tensor->array
OK, 接下来我们来学习一下, torch 里面的张量和 numpy 里面的array

8 先导入包numpy

import numpy as np
tensor = torch.arange(1., 10.)
array = np.arange(1., 10.)
print(f"tensor:\n{tensor},{tensor.dtype}")
print(f"\narray:\n{array},{array.dtype}")

tensor:
tensor([1., 2., 3., 4., 5., 6., 7., 8., 9.]),torch.float32

array:
[1. 2. 3. 4. 5. 6. 7. 8. 9.],float64

array 怎么转换为 torch 中的tensor呢

array_to_tensor = torch.from_numpy(array)
array_to_tensor

tensor([1., 2., 3., 4., 5., 6., 7., 8., 9.], dtype=torch.float64)

注意到这里的 dtype=torch.float64 是因为从上面可以看出 array 的默认数据类型是 float64, 不是张量的默认数据类型
我们可以修改数据类型
array_to_tensor = array_to_tensor.type(torch.float32)
array_to_tensor.dtype

torch.float32

tensor 转换为 array

tensor_to_array = torch.Tensor.numpy(tensor)
tensor_to_array

array([1., 2., 3., 4., 5., 6., 7., 8., 9.], dtype=float32)

array = array + 1
array, array_to_tensor

(array([ 2., 3., 4., 5., 6., 7., 8., 9., 10.]),
tensor([1., 2., 3., 4., 5., 6., 7., 8., 9.]))

tensor = tensor + 1
tensor, tensor_to_array

(tensor([ 2., 3., 4., 5., 6., 7., 8., 9., 10.]),
array([1., 2., 3., 4., 5., 6., 7., 8., 9.], dtype=float32))

从上面我们可以看出,转换的数据与原来的数据不相关

9 切片,张量里面获取元素值

有时候,我们需要从张量中获取特定的元素,比如:第一列或者第二行,所以这个时候我们就需要进行切片操作了
创建一个tensor
x = torch.arange(1, 10).reshape(1, 3, 3)
x

tensor([[[1, 2, 3],
[4, 5, 6],
[7, 8, 9]]])

切片顺序是从外部再到里面的
让我们一步一步的开始切片吧
print(f"first square bracket:\n{x[0]}")
print(f"second square bracket:\n{x[0][0]}")
print(f"third square bracket:\n{x[0][0][0]}")

first square bracket:
tensor([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
second square bracket:
tensor([1, 2, 3])
third square bracket:
1

我老是把它写成x[0:0:0],试一下好吧,好像不对
x[0:0:0]

在这里插入图片描述

这里还有一个步长
x[0:0:1]
反正引以为戒,不要学我老写错

tensor([], size=(0, 3, 3), dtype=torch.int64)

使用’:‘来特指这个维度的所有值,然后使用’,'来增加其它的维度
获得 第0维 和 第一维的索引0的值
x,x[:,0],x.shape
获得所有 第0维 和 第1维 但是只有 第2维 的索引为 1 的值
x[:,:,1] 

tensor([[2, 5, 8]])

获得 第0维 的值但只有 第一维 和 第二维 索引为 1 的值
x[:,1,1]

tensor([5])

获得第一维和第二维索引为0的值,然后所有第二维的值
x,x[0, 0, :]

(tensor([[[1, 2, 3],
[4, 5, 6],
[7, 8, 9]]]),
tensor([1, 2, 3]))

10 结果的可复现性,随机种子

大家相比应该都知道,我们做实验的时候需要噪声数据来增加模型的泛化性
那如果我们需要复现结果时,随机数字不固定的话,是很难进行复现的
所以我们需要随机种子,这样它的结果就是固定的
tensor_E = torch.rand(3,4)
tensor_F = torch.rand(3,4)
print(tensor_E == tensor_F)

tensor([[False, False, False, False],
[False, False, False, False],
[False, False, False, False]])

使用随机种子

SEEDNUM = 42 #随便什么值都可以捏
torch.manual_seed(SEEDNUM)
tensor_E = torch.rand(3,4)
tensor_F = torch.rand(3,4)
print(tensor_E == tensor_F)

tensor([[False, False, False, False],
[False, False, False, False],
[False, False, False, False]])

怎么个事,怎么不一样, 好,原来是每使用一次都需要随机种子
SEEDNUM = 42 #随便什么值都可以捏
torch.manual_seed(SEEDNUM)
tensor_E = torch.rand(3,4)
torch.manual_seed(SEEDNUM)
tensor_F = torch.rand(3,4)
print(tensor_E == tensor_F)

tensor([[True, True, True, True],
[True, True, True, True],
[True, True, True, True]])

好,这一下是不是都相等啦!

11 总结一下

咱们学习了
(1) reshape, view, squeeze(), unsqueeze(), permute()
(2) array 和 tensor 的转化
(3) 切片, 随机种子

妈呀,今天我咋学了这么多呢,根本搞不完,明天搞咯,都没时间洗澡了,忙得很

今天被黄焖鸡那个服务员气炸了,不过,没关系,晚上咱们吃的锅包肉很好吃,毛血旺里面都没有什么肉肉,猪血还挺好吃的呢

下次吃小鸡炖蘑菇,肯定很好吃
BB,如果这里的学习内容对你有用的话,记得给俺点一个赞啊,点个赞赞

谢谢BB, 靴靴!

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

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

相关文章

浮点数存储方法(float,double,long double)

前言: 浮点数家族包括float、double、long double 类型。 如果你打出3.14,编译器默认是double类型的。若想让他为float类型,则要在前面加f; 1E10是科学计数法,代表1.010^10 (1) 浮点型如何在内存中存放?…

husky 和 lint-staged 构建代码项目规范

目录 前言 最简单的方法 过 scripts 来解决如果检测工具多,需要多次处理 通过 husky(哈士奇)来解决容易遗忘的问题 1. 安装 2. husky init 3. 试一试​ lint-stadge 只 lint 改动的 1. 安装 2. 修改 package.json 配置 3. 添加 npm 脚本: 4.使用 Husky…

Linux的load(负载)

负载(load)是Linux机器的一个重要指标,直观了反应了机器当前的状态。 在Linux系统中,系统负载是对当前CPU工作量的度量,被定义为特定时间间隔内运行队列中的平均线程数。 Linux的负载高,主要是由于CPU使用、内存使用、10消…

【AI】目标检测算法【R-CNN:Regions with CNN features】

1. 常用目标检测算法介绍 目标检测是计算机视觉领域的一个重要分支,它旨在识别并定位图像中的各种对象。以下是一些流行的目标检测算法: 1.1 二阶段目标检测算法 R-CNN (Regions with CNN features): 通过选择性搜索算法选取候选区域,然后…

【C语言】详解结构体(上)

文章目录 前言1. 结构体类型的含义2.结构体的声明2.1 结构体声明的语法2.2 结构体变量的创建和初始化 3.结构体的特殊声明4. 结构体的自引用5.小结 前言 C语言的数据类型分为内置数据类型和自定义的数据类型。所谓的内置的数据类型可以认为是C语言自带的数据类型(c…

【网络安全】基于PHP study的DVWA靶场搭建教程

PHP study的安装本文略过 DVWA安装地址 https://github.com/digininja/DVWA?tabreadme-ov-file将zip文件安装至PHP study的www目录下: 解压,进入config目录中,将.dist后缀删除: 接着打开该php文件,将用户名、密码改为…

程序包不存在【java: 程序包org.springframework.boot不存在】

1、问题提示:java: 程序包org.springframework.boot不存在 注意:已经下载好了程序包,就是提示不存在 2、解决办法

Qt5离线安装包无法下载问题解决办法

Qt5离线安装包无法下载问题解决办法 文章目录 Qt5离线安装包无法下载问题解决办法1、前言2、Qt5安装包下载办法 更多精彩内容👉个人内容分类汇总 👈👉Qt开发经验 👈 1、前言 Qt安装包官方下载地址 Qt5离线安装包目前在国内已经被墙…

链表的回文结构(链表的中间节点+反转链表)

链表的回文结构 一.链表的中间节点思路1:暴力求解思路2:快慢指针 二.返回倒数第k个节点思路1:暴力求解思路2:快慢指针 三.反转链表思路1:头插法思路2:反转指针的指向 四.链表的回文结构思路1:利…

react + redux 状态管理操作

目录 1 概念2 Redux 安装3 创建子模块并导入4 中间件为 react 注入 store5 在组件中使用 store 数据6 修改 store 数据7 提交 action 传参8 异步状态操作9 redux 调试工具 1 概念 Redux 是一个全局状态管理的 JS 库 2 Redux 安装 在react中使用redux,官方要求安…

css设置弹性flex后,如果设置100vh高度不撑满的原因

问题 父元素设置height为100%,有两个子元素,第一个设置height:100vh,第二个设置flex:1,此时第一个高度无法撑满盒子 原因解决方式 当父元素设置display为flex,第一个div设置高度64px,剩一个div设置高度为flex:1,这时…

DROO论文笔记

推荐文章DROO源码及论文学习 读论文《Deep Reinforcement Learning for Online Computation Offloading in Wireless Powered Mobile-Edge Computing Networks》的笔记 论文地址:用于无线移动边缘计算网络在线计算卸载的深度强化学习 论文代码地址:DR…

AG32 的MCU与FPGA的主频可以达到568MHz吗

Customers: AG32/ AGRV2K 这个芯片主频和定时器最高速度是多少?用户期望 CPLD计时器功能0.1ns以下。 AGM RE: CPLD做不到 0.1ns的速率,这个需要10G以上的时钟。 那AGRV2K最高多少MHz呢? 一般200MHZ比较容易实现。 进一步说明&#xff1…

Vulnhub靶场DC-3-2练习

目录 0x00 准备0x01 主机信息收集0x02 站点信息收集0x03 漏洞查找与利用1. joomla漏洞查找2. SQL注入漏洞3. 破解hash4. 上传一句话木马5. 蚁剑连接shell6. 反弹shell7. 提权 0x04 总结 0x00 准备 下载链接:https://download.vulnhub.com/dc/DC-3-2.zip 介绍&#…

51单片机5(GPIO简介)

一、序言:不论学习什么单片机,最简单的外设莫过于I口的高低电平的操作,接下来,我们将给大家介绍一下如何在创建好的工程模板上面,通过控制51单片机的GPIO来使我们的开发板上的LED来点亮。 二、51单片机GPIO介绍&#…

数据结构初阶(C语言)-复杂度的介绍

在学习顺序表之前,我们需要先了解下什么是复杂度: 一,复杂度的概念 我们在进行代码的写作时,通常需要用到许多算法,而这些算法又有优劣之分,区分算法的优劣则是通过算法的时间复杂度和空间复杂度来决定。 …

python 怎样生成窗体

通过import tkinter导入Tkinter模块,没有这句下面的都不成立了。 wintkinter.Tk(),这句是创建windows的窗口对象,注意后面的Tk,大小写。 win.title("窗口"),这段是设置窗口上的标题。 另外窗口的大小你可以通…

Linux命令更新-Vim 编辑器

简介 Vim 是 Linux 系统中常用的文本编辑器,功能强大、可扩展性强,支持多种编辑模式和操作命令,被广泛应用于程序开发、系统管理等领域。 1. Vim 命令模式 Vim 启动后默认进入命令模式,此时键盘输入的命令将用于控制编辑器本身&…

云计算【第一阶段(31)】PXE高效批量网络装机

一、系统安装 1.1、系统装机的三种引导方式 1. 硬盘 2. 光驱( u 盘) 3. 网络启动 pxe 1.2、系统安装过程 加载boot loader Boot Loader 是在操作系统内核运行之前运行的一段小程序。通过这段小程序,我们可以初始化硬件设备、建立内存空间的映…

解决mysql,Navicat for MySQL,IntelliJ IDEA之间中文乱码

使用软件版本 jdk-8u171-windows-x64 ideaIU-2021.1.3 mysql-essential-5.0.87-win32 navicat8_mysql_cs 这个问题我调试了好久,网上的方法基本上都试过了,终于是解决了。 三个地方结果都不一样。 方法一 首先大家可以尝试下面这种方法&#xff1a…