PyTorch核心概念:从梯度、计算图到连续性的全面解析(三)

文章目录

  • Contiguous vs Non-Contiguous Tensor
    • Tensor and View
    • Strides
    • 非连续数据结构:Transpose( )
    • 在 PyTorch 中检查Contiguous and Non-Contiguous
      • 将不连续张量(或视图)转换为连续张量
      • view() 和 reshape() 之间的区别
      • 总结
  • 参考文献

Contiguous vs Non-Contiguous Tensor

Tensor and View

View使用与原始张量相同的数据块,只是“view”其维度的方式不同
视图只不过是解释原始张量维度的另一种方法,而无需在内存中进行物理复制。例如,我们有一个 1x12 张量,即 [1,2,3,4,5,6,7,8,9,10,11,12],然后使用 .view(4,3) 来改变形状将张量转换为 4x3 结构

x = torch.arange(1,13)
print(x)
>> tensor([ 1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12])

x = torch.arange(1,13)
y = x.view(4,3)
print(y)
>>
tensor([[ 1,  2,  3],
        [ 4,  5,  6],
        [ 7,  8,  9],
        [10, 11, 12]])

如果更改原始张量 x 中的数据,它也会反映在视图张量 y 中,因为视图张量 y 不是创建原始张量 x 的另一个副本,而是从与原始张量相同的内存地址读取数据X。反之亦然,视图张量中的值的更改将同时更改原始张量中的值,因为视图张量及其原始张量共享同一块内存块

x = torch.arange(1,13)
y = x.view(4,3)
x[0] = 100
print(y)
>> 
tensor([[100,   2,   3],
        [  4,   5,   6],
        [  7,   8,   9],
        [ 10,  11,  12]])
        
x = torch.arange(1,13)
y = x.view(4,3)
y[-1,-1] = 1000
print(x)
>> tensor([   1,    2,    3,    4,    5,    6,    7,    8,    9,   10,   11, 1000])

可以以连续的方式查看不同维度的数据序列
一维张量A中的元素数量为T,经过view()处理之后的张量B,shape为(K,M,N),则需满足 K × M × N = T K\times M\times N=T K×M×N=T

Strides

在这里插入图片描述

# x is a contiguous data. Recall that view() doesn't change data arrangement in the original 1D tensor
x = torch.arange(1,13).view(6,2)
x
>>
tensor([[ 1,  2],
        [ 3,  4],
        [ 5,  6],
        [ 7,  8],
        [ 9, 10],
        [11, 12]])
        
# Check stride
x.stride()
>> (2, 1)

步长 (2, 1) 告诉我们:我们需要跨过 1 个(维度 0)数字才能到达沿轴 0 的下一个数字,并且需要跨过 2 个(维度 1)数字才能到达沿轴 1 的下一个数字

y = torch.arange(0,11).view(2,2,3)
y
>>
tensor([[[ 0,  1,  2],
         [ 3,  4,  5]],
        [[ 6,  7,  8],
         [ 9, 10, 11]]])
         
# Check stride
y.stride()
>> (6, 3, 1)

检索一维张量中 (A, B, C) 位置的公式如下: A × 6 + B × 3 + C × 1 A \times 6 + B \times 3 + C \times 1 A×6+B×3+C×1

非连续数据结构:Transpose( )

首先,Transpose(axis1, axis2) 只是“swapping the way axis1 and axis2 strides”
在这里插入图片描述

# Initiate a contiguous tensor
x = torch.arange(0,12).view(2,2,3)
x
>>
tensor([[[ 0,  1,  2],
         [ 3,  4,  5]],
        [[ 6,  7,  8],
         [ 9, 10, 11]]])
         
x.stride()
>> (6,3,1)

# Now let's transpose axis 0 and 1, and see how the strides swap
y = x.transpose(0,2)
y
>>
tensor([[[ 0,  6],
         [ 3,  9]],
        [[ 1,  7],
         [ 4, 10]],
        [[ 2,  8],
         [ 5, 11]]])
         
y.stride()
>> (1,3,6)

y 是 x.transpose(0,2),它交换 x 张量在轴 0 和轴 2 上的stride,因此 y 的stride是 (1,3,6)。这意味着我们需要跳转 6 个数字才能获取第 0 轴的下一个数字,跳转 3 个数字才能获取第 1 轴的下一个数字,跳转 1 个数字才能获取第 2 轴的下一个数字(stride公式: A × 1 + B × 3 + C × 6 A \times 1+ B \times 3+C \times 6 A×1+B×3+C×6)
transpose的不同之处在于:现在数据序列不再遵循连续的顺序。它不会从最内层维度逐一填充顺序数据,填满后跳转到下一个维度。现在它在最里面的维度跳跃了6个数字,所以它不是连续的
transpose( ) 具有不连续的数据结构,但仍然是视图而不是副本 ⇒ \Rightarrow 它是一个不连续的“视图”,改变了原始数据的stride方式

# Change the value in a transpose tensor y
x = torch.arange(0,12).view(2,6)
y = x.transpose(0,1)
y[0,0] = 100
y
>>
tensor([[100,   6],
        [  1,   7],
        [  2,   8],
        [  3,   9],
        [  4,  10],
        [  5,  11]])
# Check the original tensor x
x
>>
tensor([[100,   1,   2,   3,   4,   5],
        [  6,   7,   8,   9,  10,  11]])

在 PyTorch 中检查Contiguous and Non-Contiguous

使用PyTorch中的 .is_contigious() 检查张量是否连续

x = torch.arange(0,12).view(2,6)
x.is_contiguous()
>> True

y = x.transpose(0,1)
y.is_contiguous()
>> False

将不连续张量(或视图)转换为连续张量

使用PyTorch中的 .contigious() 将不连续的张量转换成连续的张量

z = y.contiguous()
z.is_contiguous()
>> TRUE

** .contigious() 复制原始的“non-contiguous”张量,然后按照连续顺序将其保存到新的内存块中**

# This is contiguous
x = torch.arange(1,13).view(2,3,2)
x.stride()
>> (6, 2, 1)

# This is non-contiguous
y = x.transpose(0,1)
y.stride()
>> (2, 6, 1)

# This is a converted contiguous tensor with new stride
z = y.contiguous()
z.stride()
>> (4, 2, 1)

print(z.shape)
>> (3, 2, 2)

# The stride across the first dimension is 2*2
# The stride across the second dimension is 2*1
# The stride across the third dimension is 1
(4, 2, 1)=>(2*2, 2*1, 1)

用来区分张量/视图是否连续的一种方法是观察stride中的 ( A , B , C ) (A, B, C) (A,B,C) 是否满足 A > B > C A > B > C A>B>C。如果不满足,则意味着至少有一个维度正在跳过的距离比其上方的维度更长,这使得它不连续
我们还可以观察转换后的连续张量 z 如何以新的顺序存储数据

# y is a non-contiguous 'view' (remember view uses the original chunk of data in memory, but its strides implies 'non-contiguous', (2,6,1).
y.storage()
>>
 1
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 
# Z is a 'contiguous' tensor (not a view, but a new copy of the original data. Notice the order of the data is different). It strides implies 'contiguous', (4,2,1)
z.storage()
>>
 1
 2
 7
 8
 3
 4
 9
 10
 5
 6
 11
 12

view() 和 reshape() 之间的区别

虽然这两个函数都可以改变张量的维度,但两者之间的主要区别是:

  1. view():不复制原始张量,使用与原始张量相同的数据块,仅适用于连续数据
  2. reshape():当数据连续时,尽可能返回视图;当数据不连续时,则将数据复制到连续的数据块中,作为副本,它会占用内存空间,而且新张量的变化不会影响原始张量中的原始数值
# When data is contiguous
x = torch.arange(1,13)
x
>> tensor([ 1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12])

# Reshape returns a view with the new dimension
y = x.reshape(4,3)
y
>>
tensor([[ 1,  2,  3],
        [ 4,  5,  6],
        [ 7,  8,  9],
        [10, 11, 12]])
        
# How do we know it's a view? Because the element change in new tensor y would affect the value in x, and vice versa
y[0,0] = 100
y
>>
tensor([[100,   2,   3],
        [  4,   5,   6],
        [  7,   8,   9],
        [ 10,  11,  12]])
        
print(x)
>>
tensor([100,   2,   3,   4,   5,   6,   7,   8,   9,  10,  11,  12])

接下来,让我们看看 reshape() 如何处理非连续数据:

# After transpose(), the data is non-contiguous
x = torch.arange(1,13).view(6,2).transpose(0,1)
x
>>
tensor([[ 1,  3,  5,  7,  9, 11],
        [ 2,  4,  6,  8, 10, 12]])
        
# Reshape() works fine on a non-contiguous data
y = x.reshape(4,3)
y
>>
tensor([[ 1,  3,  5],
        [ 7,  9, 11],
        [ 2,  4,  6],
        [ 8, 10, 12]])
        
# Change an element in y
y[0,0] = 100
y
>>
tensor([[100,   3,   5],
        [  7,   9,  11],
        [  2,   4,   6],
        [  8,  10,  12]])
        
# Check the original tensor, and nothing was changed
x
>>
tensor([[ 1,  3,  5,  7,  9, 11],
        [ 2,  4,  6,  8, 10, 12]])

最后,让我们看看 view() 是否可以处理非连续数据。No, it can’t!

# After transpose(), the data is non-contiguous
x = torch.arange(1,13).view(6,2).transpose(0,1)
x
>>
tensor([[ 1,  3,  5,  7,  9, 11],
        [ 2,  4,  6,  8, 10, 12]])
        
# Try to use view on the non-contiguous data
y = x.view(4,3)
y
>>
-------------------------------------------------------------------
RuntimeError Traceback (most recent call last)
----> 1 y = x.view(4,3)
      2 y
RuntimeError: view size is not compatible with input tensor's size and stride (at least one dimension spans across two contiguous subspaces). Use .reshape(...) instead.

总结

  1. view”使用与原始张量相同的内存块,因此该内存块中的任何更改都会影响所有视图以及与其关联的原始张量
  2. 视图可以是连续的或不连续的。一个不连续的张量视图可以转换为连续的张量视图,并且会复制不连续的视图张量到新的内存空间中,因此数据将不再与原始数据块关联
  3. stride位置公式:给定一个stride ( A , B , C ) (A,B,C) (ABC),索引 ( j , k , v ) (j, k, v) (j,k,v) 在 1D 数据数组中的位置为 ( A × j + B × k + C × v ) (A \times j + B \times k + C \times v) (A×j+B×k+C×v)
  4. view()reshape() 之间的区别:view() 不能应用于 '非连续的张量/视图,它返回一个视图;reshape() 可以应用于“连续”和“非连续”张量/视图

《PyTorch核心概念:从梯度、计算图到连续性的全面解析(一)》
《PyTorch核心概念:从梯度、计算图到连续性的全面解析(二)》

参考文献

1、Contiguous vs Non-Contiguous Tensor / View — Understanding view(), reshape(), transpose()

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

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

相关文章

DeBiFormer实战:使用DeBiFormer实现图像分类任务(二)

文章目录 训练部分导入项目使用的库设置随机因子设置全局参数图像预处理与增强读取数据设置Loss设置模型设置优化器和学习率调整策略设置混合精度,DP多卡,EMA定义训练和验证函数训练函数验证函数调用训练和验证方法 运行以及结果查看测试完整的代码 在上…

iOS SmartCodable 替换 HandyJSON 适配记录

前言 HandyJSON群里说建议不要再使用HandyJSON,我最终选择了SmartCodable 来替换,原因如下: 首先按照 SmartCodable 官方教程替换 大概要替换的内容如图: 详细的替换教程请前往:使用SmartCodable 平替 HandyJSON …

Sqoop学习

目录 一、Soop简介 二、Sqoop的安装 1. 上传压缩包到/opt/install目录下 2.解压 3.修改文件名 4.拷贝sqoop-1.4.7.bin__hadoop-2.6.0目录下的sqoop-1.4.7.jar包到/opt/soft/sqoop147目录下 5.拷贝sqoop-1.4.7.bin__hadoop-2.6.0/lib目录下该jar包到sqoop/lib目录下 6.复…

WiFi一直获取不到IP地址是怎么回事?

在当今这个信息化时代,WiFi已成为我们日常生活中不可或缺的一部分。无论是家庭、办公室还是公共场所,WiFi都为我们提供了便捷的无线互联网接入。然而,有时我们可能会遇到WiFi连接后无法获取IP地址的问题,这不仅影响了我们的网络使…

FasterNet中Pconv的实现、效果与作用分析

发表时间:2023年3月7日 论文地址:https://arxiv.org/abs/2303.03667 项目地址:https://github.com/JierunChen/FasterNet FasterNet-t0在GPU、CPU和ARM处理器上分别比MobileViT-XXS快2.8、3.3和2.4,而准确率要高2.9%。我们的大型…

如何快速搭建一个spring boot项目

一、准备工作 1.1 安装JDK:确保计算机上已安装Java Development Kit (JDK) 8或更高版本、并配置了环境变量 1.2 安装Maven:下载并安装Maven构建工具,这是Spring Boot官方推荐的构建工具。 1.3 安装代码编辑器:这里推荐使用Inte…

从零开始训练一个大语言模型需要多少天?

一,前言 在AI领域,训练一个大型语言模型(LLM)是一个耗时且复杂的过程。几乎每个做大型语言模型(LLM)训练的人都会被问到:“从零开始,训练大语言模型需要多久和花多少钱?”…

成大事者,不外传的心计

成大事者,不外传的心计: 1.男人要避开闺蜜众多的女人。 2.追求女生,不可过于主动,心急难以品尝到热豆腐的美味。 3.倘若这个人身边没什么朋友,那就要赶快远离。 4.让利,是拓展人脉资源的有效法门。 5.…

如何将数据从 AWS S3 导入到 Elastic Cloud - 第 3 部分:Elastic S3 连接器

作者:来自 Elastic Hemendra Singh Lodhi 了解将数据从 AWS S3 导入 Elastic Cloud 的不同选项。这次我们将重点介绍 Elastic S3 Connector。 这是多部分博客系列的第三部分,探讨了将数据从 AWS S3 导入 Elastic Cloud 的不同选项。 在本博客中&#xf…

产品经理如何使用项目管理软件推进复杂项目按时上线

前言 相信很多产品同学或多或少都有过这样的经历:平时没有听到任何项目延期风险,但到了计划时间却迟迟无法提测……评审时没有任何argue,提测后发现开发的功能不是自己想要的……费劲九牛二虎之力终于让项目上线了,然而发现成果达…

K8S node节点没有相应的pod镜像运行故障处理办法

查看从节点状态 kubectl describe node k8s-node1以下是报错提示 解决办法 需要处理node1节点上的磁盘空间,磁盘空间需要在85%内 处理后的状态 处理正常

11.9.2024刷华为

文章目录 HJ31 单词倒排HJ32 密码提取语法知识记录 傻逼OD题目又不全又要收费,看毛线,莫名奇妙 HW这叼机构别搁这儿害人得不得? 我觉得我刷完原来的题目 过一遍华为机考的ED卷出处,就行了 HJ31 单词倒排 游戏本做过了好像 HJ3…

Colmap3.8 [CUDA]和[NO CUDA]版本

Colmap3.8 [CUDA]和[NO CUDA]版本的下载地址如下所示: 通过百度网盘分享的文件:colmap3.8 链接:https://pan.baidu.com/s/1kfbUqFI5N2t8Bx2MasFKXQ?pwd998n 提取码:998n 解压即可使用,运行时,点击下图…

sealos部署K8s,安装docker时master节点突然NotReady

1、集群正常运行中,在集群master-1上安装了dockerharbor,却发现master-1节点NotReady,使用的网络插件为 Cilium #安装docker和harbor(docker运行正常) rootmaster-1:/etc/apt# apt install docker-ce5:19.03.15~3-0~u…

NoETL自动化指标平台为数据分析提质增效,驱动业务决策

直觉判断往往来源于多年的经验和专业知识,能够在复杂和不确定的环境中快速做出决策反应。但这种方式普遍存在主观偏见,缺乏合理的科学依据,无法全面、客观、精准地评估和识别市场趋势与用户需求,从而造成决策失误,给业…

vscode的一些使用心得

问题1:/home目录空间有限 连接wsl或者remote的时候,会在另一端下载一个.vscode-server,vscode的插件都会安装进去,导致空间增加很多,可以选择更换这个文件的位置 参考:https://blog.csdn.net/weixin_4389…

《JavaEE进阶》----21.<基于Spring图书管理系统②(图书列表+删除图书+更改图书)>

PS: 开闭原则 定义和背景‌ ‌开闭原则(Open-Closed Principle, OCP)‌,也称为开放封闭原则,是面向对象设计中的一个基本原则。该原则强调软件中的模块、类或函数应该对扩展开放,对修改封闭。这意味着一个软…

Flutter错误: uses-sdk:minSdkVersion 16 cannot be smaller than version 21 declared

前言 今天要做蓝牙通信的功能,我使用了flutter_reactive_ble这个库,但是在运行的时候发现一下错误 Launching lib/main.dart on AQM AL10 in debug mode... /Users/macbook/Desktop/test/flutter/my_app/android/app/src/debug/AndroidManifest.xml Err…

【C++滑动窗口】1297. 子串的最大出现次数|1748

本文涉及的基础知识点 C算法:滑动窗口及双指针总结 固定长度滑动窗口 LeetCode1297. 子串的最大出现次数 给你一个字符串 s ,请你返回满足以下条件且出现次数最大的 任意 子串的出现次数: 子串中不同字母的数目必须小于等于 maxLetters 。…

信息宣传投稿栽跟头不可怕,关键是你要能再站起来

在繁忙的市郊,一家的事业基层单位,这里汇聚了各路英才,每个科室都有自己的专长。然而,有一项任务,让这些精英们头疼不已——单位信息宣传投稿。 起初,大家对这项任务并不以为然,以为不过是小菜一碟。李科长甚至开玩笑说:“不就是写篇文章,投个稿嘛,我们这些笔杆子还怕这个?”…