【PyTorch与深度学习】2、PyTorch张量的运算API(上)

课程地址
最近做实验发现自己还是基础框架上掌握得不好,于是开始重学一遍PyTorch框架,这个是课程笔记,这个课还是讲的简略,我半小时的课听了一个半小时。

1. 张量

1.1 张量操作

(1)chunk:将一个张量分割为特定数目的张量,每个块都是输入张量的视图。

  • 按维度0分割:
import torch

b = torch.rand([3, 2])  # 随机生成3x2维度的张量
print("b=", b)
c, d = torch.chunk(b, chunks=2)  # 将b分割为c和d两个张量,默认沿着维度0去分割(按行分割)
print("c=", c)
print("d=", d)  # 最后一个张量维度会稍微小一点,因为3不能被2整除

运行结果:
b= tensor([[0.7704, 0.8685],
[0.0165, 0.5076],
[0.2730, 0.2270]])
c= tensor([[0.7704, 0.8685],
[0.0165, 0.5076]])
d= tensor([[0.2730, 0.2270]])

  • 按维度1分割:
import torch

b = torch.rand([3, 2])  # 随机生成3x2维度的张量
print("b=", b)
c, d = torch.chunk(b, chunks=2, dim=1)  # 将b分割为c和d两个张量,默认沿着维度1去分割(按列分割)
print("c=", c)
print("d=", d)  # 最后一个张量维度会稍微小一点,因为3不能被2整除

运行结果:
b= tensor([[0.1275, 0.9670],
[0.5189, 0.0748],
[0.6840, 0.7675]])
c= tensor([[0.1275],
[0.5189],
[0.6840]])
d= tensor([[0.9670],
[0.0748],
[0.7675]])
(2)dsplit:将具有三个或更多维度的张量按深度拆分为多个张量。

import torch

# 按深度划分(按最后一个维度划分),看打印结果
a = torch.arange(16.0).reshape(2, 2, 4)
print(a)
b = torch.dsplit(a, 2)  # 均分两份
print(b)
c = torch.dsplit(a, [3, 6])  # 第一份是按最后一个维度取前三个值,第二份是6个
print(c)
d = torch.dsplit(a, [2, 4])  # 第一份是1个,第二份是4个
print(d)
e = torch.dsplit(a, [1, 1, 2])  # 第一份是1个,第二份是1个,第三分是2个
print(e)

运行结果:
tensor([[[ 0., 1., 2., 3.],
[ 4., 5., 6., 7.]],
[[ 8., 9., 10., 11.],
[12., 13., 14., 15.]]])
(tensor([[[ 0., 1.],
[ 4., 5.]],
[[ 8., 9.],
[12., 13.]]]), tensor([[[ 2., 3.],
[ 6., 7.]],
[[10., 11.],
[14., 15.]]]))
(tensor([[[ 0., 1., 2.],
[ 4., 5., 6.]],
[[ 8., 9., 10.],
[12., 13., 14.]]]), tensor([[[ 3.],
[ 7.]],
[[11.],
[15.]]]), tensor([], size=(2, 2, 0)))
(tensor([[[ 0., 1.],
[ 4., 5.]],
[[ 8., 9.],
[12., 13.]]]), tensor([[[ 2., 3.],
[ 6., 7.]],
[[10., 11.],
[14., 15.]]]), tensor([], size=(2, 2, 0)))
(tensor([[[ 0.],
[ 4.]],
[[ 8.],
[12.]]]), tensor([], size=(2, 2, 0)), tensor([[[ 1.],
[ 5.]],
[[ 9.],
[13.]]]), tensor([[[ 2., 3.],
[ 6., 7.]],
[[10., 11.],
[14., 15.]]]))

(3)dstack:按深度顺序(沿第三轴)堆叠张量。

import torch

a = torch.tensor([1, 2, 3])  # 行向量
b = torch.tensor([4, 5, 6])
print(torch.dstack((a,b)))
a = torch.tensor([[1],[2],[3]])  # 列向量
b = torch.tensor([[4],[5],[6]])
print(torch.dstack((a,b)))

运行结果:
tensor([[[1, 4],
[2, 5],
[3, 6]]])
tensor([[[1, 4]],
[[2, 5]],
[[3, 6]]])

(4)hstack:按水平顺序堆叠张量(按列)

import torch

a = torch.tensor([1, 2, 3])  # 行向量
b = torch.tensor([4, 5, 6])
print(torch.hstack((a,b)))
a = torch.tensor([[1],[2],[3]])  # 列向量
b = torch.tensor([[4],[5],[6]])
print(torch.hstack((a,b)))

运行结果:
tensor([1, 2, 3, 4, 5, 6])
tensor([[1, 4],
[2, 5],
[3, 6]])

(5)gather:沿着某一个维度取变量(根据索引取变量,这个一看就晕,但是我找到了一篇比较好的文章讲解这个)
torch.gather() 和torch.sactter_()的用法简析,这个讲的最好,我就是按照这个学的

import torch

t = torch.tensor([[1, 2], [3, 4]])
a = torch.gather(t, 1, torch.tensor([[0, 0], [1, 0]]))  # 按维度1和[[0, 0], [1, 0]]的下标取张量t的元素
# out[i,j] = t[i][a[i, j]]
# out[0,0] = t[0][a[0, 0]]=t[0][0]=1
# out[0,1] = t[0][a[0, 1]]=t[0][0]=1
# 所以out[0]=[1, 1]
# out[1,0] = t[1][a[1, 0]]=t[1][1]=4
# out[1,1] = t[1][a[1, 1]]=t[1][0]=3
# 所以out[1]=[4, 5]
# 所以out=[[1, 1], [4, 3]]
print(a)
a = torch.gather(t, 0, torch.tensor([[0, 0], [1, 0]]))  # 按维度0和[[0, 0], [1, 0]]的下标取张量t的元素
# out[i,j] = t[a[i, j]][j]
# out[0,0] = t[a[0, 0]][0]=t[0][0]=1
# out[0,1] = t[a[0, 1]][1]=t[0][1]=2
# 所以out[0]=[1, 2]
# out[1,0] = t[a[1, 0]][0]=t[1][0]=3
# out[1,1] = t[a[1, 1]][1]=t[0][1]=2
# 所以out[1]=[3, 2]
# 所以out=[[1, 2], [3, 2]]
print(a)

运行结果:
tensor([[1, 1],
[4, 3]])
tensor([[1, 2],
[3, 2]])

(6)reshape:返回一个张量,其数据和元素数量与输入相同,但具有指定的形状,改变形状,不改变顺序,比如原来是从左到右,然后改成多行后,是按从左到右从上到下顺序重新改变形状。

import torch

a = torch.arange(4.)  # 生成从0到3的一维张量
print(torch.reshape(a, (2, 2)))  # 改成2X2张量
b = torch.tensor([[0, 1], [2, 3]])
print(torch.reshape(b, (-1,)))  # -1,自动推断变成一维

运行结果:
tensor([[0., 1.],
[2., 3.]])
tensor([0, 1, 2, 3])
【注】一般在方法名后面加下划线的都是原地操作,内存位置不会发生改变
(7)scatter_: torch.gather() 和torch.sactter_()的用法简析,按索引张量更新元素。

import torch

src = torch.arange(1, 11).reshape((2, 5))
print(src)
index = torch.tensor([[0, 1, 2, 0]])
a = torch.zeros(3, 5, dtype=src.dtype)  # 初始化一个和src张量数据类型一样的3X5的0张量,
# 这样方便观察,非0的部分就是修改过的
z = a.scatter_(0, index, src)  # 按索引张量将src中的元素写入到z中,按维度0写入
# z[index[i][j],j]=src[i][j],index中i只有0,j从0到3
# z[index[0][0],0]=z[0,0]=src[0][0]=1
# z[index[0][1],1]=z[1,1]=src[1][1]=6
# z[index[0][2],2]=z[2,2]=src[2][2](i越界1个,相当于又变回0,索引只有(0,1),则2对应的应该是0,1,0的0,以此类推循环)=src[0][2]=3
# z[index[0][3],3]=z[0,3]=src[0][3]=4
print(z)
a = torch.zeros(3, 5, dtype=src.dtype)
z = a.scatter_(1, index, src)  # 按索引张量将src中的元素写入到z中,按维度1写入
# z[i,index[i][j]]=src[i][j],index中只有0,j从0到3
# z[0,index[0][0]]=z[0,0]=src[0][0]=1
# z[0,index[0][1]]=z[0,1]=src[0][1]=2
# z[0,index[0][2]]=z[0,2]=src[0][2]=3
# z[0,index[0][3]]=z[0,0]=src[0][3]=4(被覆盖,最终z[0,0]=4)
print(z)

运行结果:
tensor([[ 1, 2, 3, 4, 5],
[ 6, 7, 8, 9, 10]])
tensor([[1, 0, 0, 4, 0],
[0, 2, 0, 0, 0],
[0, 0, 3, 0, 0]])
tensor([[4, 2, 3, 0, 0],
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0]])

(8)scatter_add_:以与 scatter_() 类似的方式,将张量 src 中的所有值添加到索引张量中指定的索引处的 self 中。

import torch

src = torch.ones((2, 5))
print(src)
index = torch.tensor([[0, 1, 2, 0, 0]])
z = torch.zeros(3, 5, dtype=src.dtype).scatter_add_(0, index, src)  # 按维度0进行相加
print(z)
# z[index[i][j], j]=src[i][j],i只能为0,j从0到4
# z[index[0][0], 0]=z[0,0]=src[0][0]=1
# z[index[0][1], 1]=z[1,1]=src[0][1]=1
# z[index[0][2], 2]=z[2,2]=src[0][2]=1
# z[index[0][3], 3]=z[0,3]=src[0][3]=1
# z[index[0][4], 4]=z[0,4]=src[0][4]=1

运行结果:
tensor([[1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1.]])
tensor([[1., 0., 0., 1., 1.],
[0., 1., 0., 0., 0.],
[0., 0., 1., 0., 0.]])
(9)split:将张量划分为多块,每块都是原来张量的一部分。

import torch

a = torch.arange(10).reshape(5, 2)
print(a)
print(torch.split(a, 2))  # 分成两份,最后一份可能会少一点,要保证前面均分
print(torch.split(a, [1, 4]))  # 按1:4比例划分,不指定参数默认按0维度(行)划分

运行结果:
tensor([[0, 1],
[2, 3],
[4, 5],
[6, 7],
[8, 9]])
(tensor([[0, 1],
[2, 3]]), tensor([[4, 5],
[6, 7]]), tensor([[8, 9]]))
(tensor([[0, 1]]), tensor([[2, 3],
[4, 5],
[6, 7],
[8, 9]]))

chunk和split的区别:【GPT回答】chunk 函数将张量均匀分成几块,每块大小相等。split 函数可以根据指定的大小或部分来分割张量,每个块的大小可以不相等。总的来说,如果您需要将张量均匀地分成几块,可以使用 chunk 函数。如果您需要更灵活地指定每个块的大小或部分,可以使用 split 函数。

(10)squeeze:将张量中所有维度为1的那个维度移除掉

import torch

a = torch.tensor([[[1, 2, 3], [1, 2, 3]]])  # 2x3x1张量
a = torch.squeeze(a)  # 压缩维度为1的维度,变成2维张量,2X3
print(a)

a = torch.tensor([[[[1, 2, 3], [1, 2, 3]]]])  # 2x3x1x1张量
a = torch.squeeze(a)  # 压缩维度为1的维度,变成2维张量,2X3
print(a)

# 压缩指定的维度为1的维度(PyTorch低于2.0版本,指定的维度不能是list(就是相当于用list的元素多次指定要压缩的维度为1的维度的索引),所以这里写dim = 2)
a = torch.tensor([[[[1, 2, 3], [1, 2, 3]]]])  # 2x3x1x1张量
a = torch.squeeze(a, dim=2)  # 压缩维度为1的维度,且索引为2,变成3维张量,2X3x1
print(a)

运行结果:
tensor([[1, 2, 3],
[1, 2, 3]])
tensor([[1, 2, 3],
[1, 2, 3]])
tensor([[[[1, 2, 3],
[1, 2, 3]]]])
(11)stack:沿着某一个新的维度将一系列张量拼接起来。

import torch

a = torch.ones(3, 2)  # 3x2 全是1的张量
b = torch.zeros(3, 2)  # 3x3 全是0的张量
c = torch.stack([a, b])  # dim 默认为0,它们合并到新的张量的第0维,新的张量的元素分别是a, b,相当于最后是一个三维张量
print(c)

c = torch.stack([a, b], dim=1)  # 按行拼接
print(c)

运行结果:
tensor([[[1., 1.],
[1., 1.],
[1., 1.]],
[[0., 0.],
[0., 0.],
[0., 0.]]])
tensor([[[1., 1.],
[0., 0.]],
[[1., 1.],
[0., 0.]],
[[1., 1.],
[0., 0.]]])

进程已结束,退出代码0

它们是这样的张量(接下来的看法可能不对):

如果按维度0进行拼接,

(后面全是1),按0维度这样看就是
tensor([[[1., 1.],
[1., 1.],
[1., 1.]],
[[0., 0.],
[0., 0.],
[0., 0.]]])
如果按维度1拼接,

按1维度这样看就是
tensor([[[1., 1.],
[0., 0.]],
[[1., 1.],
[0., 0.]],
[[1., 1.],
[0., 0.]]])

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

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

相关文章

华为手机ip地址怎么切换

随着移动互联网的普及,IP地址成为了我们手机上网的重要标识。然而,在某些情况下,我们可能需要切换手机的IP地址,以更好地保护个人隐私、访问特定地区的内容或服务,或者出于其他网络需求。华为手机作为市场上的热门品牌…

Kafka客户端工具:Offset Explorer 使用指南

Kafka作为一个分布式流处理平台,在大数据处理和实时数据流应用中扮演着至关重要的角色。管理Kafka的topics及其offsets对于维护系统稳定性和数据一致性至关重要。Offset Explorer是一个强大的桌面应用程序,它使得管理和监控Kafka集群变得简单直观。本文将…

2023 广东省大学生程序设计竞赛(部分题解)

目录 A - Programming Contest B - Base Station Construction C - Trading D - New Houses E - New but Nostalgic Problem I - Path Planning K - Peg Solitaire A - Programming Contest 签到题:直接模拟 直接按照题目意思模拟即可,为了好去…

【Unity】修改模型透明度

在 Unity 中修改模型透明度主要有两种方法:通过材质和通过着色器。以下是两种方法的步骤和解释: 方法 1:通过材质 在 Unity 编辑器中,选择你想要修改透明度的模型。在 Inspector 窗口中,找到模型的 Renderer 组件&am…

海康WEB3.3控件开发包 V3.3 前端vue项目调用实时监控画面

公司业务迭代, 需要前端vue项目里增加一个查看实时监控模块, 这个需求是之前离职的前端小哥没有研究明白的, 现在落在了我的肩上, 压力还是有的. 但是压力归压力, 问题还是要解决的. 一、调研设备和方案 第一步: 调研大佬们已经实现的方案, 找设备对接. 公司后端大佬提出用官…

Jenkins邮件发送失败问题解决

如下提示为 Extended E-mail Notification开启Debug模式下显示的错误信息, (Debug模式设置方法:Dashboard-> manage Jenkins->configure System)DEBUG SMTP: Attempt to authenticate using mechanisms: LOGIN PLAIN DIGEST-MD5 NTLM XOAUTH2 DEB…

Unity3d 学习之按钮绑定事件

创建测试脚本 using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI;public class myTest : MonoBehaviour {// Start is called before the first frame updatepublic Button _codeBindBtn null;void Start(){if (_codeBi…

LeetCode 213 —— 打家劫舍 II

阅读目录 1. 题目2. 解题思路3. 代码实现 1. 题目 2. 解题思路 此题是 LeetCode 198—— 打家劫舍 的升级版,多了一个首尾相连的设定。 因为首尾相连,所以第一个房屋和最后一个房屋只能偷窃其中一个。 所以,第一种方案就是不偷窃最后一个房…

每日OJ题_DFS爆搜深搜回溯剪枝⑧_力扣980. 不同路径 III

目录 力扣980. 不同路径 III 解析代码 力扣980. 不同路径 III 980. 不同路径 III 难度 困难 在二维网格 grid 上,有 4 种类型的方格: 1 表示起始方格。且只有一个起始方格。2 表示结束方格,且只有一个结束方格。0 表示我们可以走过的空…

HTML5实用大全(Part.1)

引言: 哈喽,各位小伙伴们,在本篇博客我将带领大家走进前端中的HTML5,利用HTML我们将可以在网页上自我创作内容,现在学起来,不久后自己也能制作一个花哨的项目了呢,那么,我们开始吧! …

【ROS2学习记录】—— 参考鱼香ROS

1 回顾Linux基础 (1)打开终端:Ctrl Alt T (2)ls (3)cd cd ~ cd /(4)pwd (5)mkdir -p catkin_ws/src (6)rm -rf &#…

LeetCode 198—— 打家劫舍

阅读目录 1. 题目2. 解题思路3. 代码实现 1. 题目 2. 解题思路 此题使用动态规划求解,假设 d p [ i ] [ 0 ] dp[i][0] dp[i][0] 代表不偷窃第 i i i 个房屋可以获得的最高金额,而 d p [ i ] [ 1 ] dp[i][1] dp[i][1] 代表偷窃第 i i i 个房屋可以获…

【右一的开发日记】全导航,持续更新...

文章目录 📚前端【跟课笔记】🐇核心技术🐇高级技术 📚捣鼓捣鼓🐇小小案例🐇喵喵大王立大功🐇TED自用学习辅助网站🐇世界top2000计算机科学家可视化大屏🐇基于CBDB的唐代历…

GitHub Copilot 简单使用

因为公司安全原因,并不允许在工作中使用GitHub Copilot,所以,一直没怎么使用。最近因为有一些其它任务,所以,试用了一下,感觉还是很不错的。(主要是C和Python编程) 一:常…

python中的进程线程和协程

目录 进程(Process)多进程代码实例 线程(Thread)多线程存在原因及其缺点多线程代码实例 协程(Coroutine)协程的优点协程代码实例 进程、线程和协程适合的任务性质和环境多进程更适合的场景多线程更适合的场…

LeetCode 11—— 盛最多水的容器

阅读目录 1. 题目2. 解题思路一3. 代码实现一4. 解题思路二5. 代码实现二 1. 题目 2. 解题思路一 暴力法,遍历所有可能的垂线对 ( i , j ) (i, j) (i,j),求取最大面积: a r e a m i n ( h [ i ] , h [ j ] ) ∗ ( j − i ) area min(h[i]…

Node.js -- MongoDB

文章目录 1. 相关介绍2. 核心概念3. 命令行交互3.1数据库命令3.2 集合命令3.3 文档命令 4. 数据库应用场景4.1 新增4.2 删除4.3 更新4.4 查询 1. 相关介绍 一、简介 Mongodb是什么 MongoDB是一个基于分布式文件存储的数据库,官方地址https://www.mongodb.com/try/d…

一个C++小程序调试过程记录

Top 20 C Projects With Source Code [2024 Update]https://www.interviewbit.com/blog/cpp-projects/ 这个网页有一些简单的C程序的源码,闲来无事,把第一个程序(Bookshop Management System Using C)的源码下载了下来。 源文件…

第N1周:one-hot独热编码

🍨 本文为🔗365天深度学习训练营 中的学习记录博客🍖 原作者:K同学啊 一、OneHot独热编码原理 独热编码(One-Hot Encoding)是一种将分类数据转换为二进制向量的方法,其中每个类别对应一个唯一的…

如何下载AndroidStudio旧版本

文章目录 1. Android官方网站2. 往下滑找到历史版本归档3. 同意软件下载条款协议4. 下载旧版本Androidstudio1. Android官方网站 点击 Android官网AS下载页面 https://developer.android.google.cn/studio 进入AndroidStuido最新版下载页面,如下图: 2. 往下滑找到历史版本归…
最新文章