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()
>> Truey = 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()
>>123456789101112# 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()
>>127834910561112

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()

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何解决导入aioredis报错TypeError: duplicate base class TimeoutError的问题(轻松解决,亲测有效)

下面是根据你的要求撰写的文章: 文章目录 📖 介绍 📖🏡 演示环境 🏡📒 aioredis导包报错 📒📝 解决方案📝 小贴士⚓️ 相关链接 ⚓️📖 介绍 📖 最近在使用Python异步redis模块aioredis的时候遇到了一个错误,导包报错提示 TypeError: duplicate base cla…

基于Springboot+Android的智慧社区互助平台 (含源码数据库)

1.开发环境 开发系统:Windows10/11 架构模式:MVC/前后端分离 JDK版本: Java JDK1.8 开发工具:IDEA 数据库版本: mysql5.7或8.0 数据库可视化工具: navicat 服务器: SpringBoot自带 apache tomcat 主要技术: Java,Springboot,mybatis,mysql,vue 2.视频演示地址 3.功能 这个系…

讨论一个mysql事务问题

最近在阅读一篇关于隔离级别的文章,文章中提到了一种场景,我们下面来分析一下。 文章目录 1、实验环境2、两个实验的语句执行顺序3、关于start transaction和start transaction with consistent snapshot4、实验结果解释4.1、实验14.2、实验24.3、调整实…

Kubernetes-编排工具篇-01-Kustomize与Helm对比

Kustomize与Helm对比 0、前言 K8s 是一个开源容器编排平台,可自动执行容器化应用程序的部署、扩展和管理。近年来,K8s 已成为采用云原生架构和容器化技术的组织的标准。 但是由于K8s的复杂性,所以很多公司以及开源组织都在开发相关的工具来…

确定图像的熵和各向异性 Halcon entropy_gray 解析

1、图像的熵 1.1 介绍 图像熵(image entropy)是图像“繁忙”程度的估计值,它表示为图像灰度级集合的比特平均数,单位比特/像素,也描述了图像信源的平均信息量。熵指的是体系的混乱程度,对于图像而言&#…

数字IC后端设计实现之Innovus自动修复Min Step DRC Violation方案

在实际IC后端项目中我们经常会遇到min step的DRC Violation,如下图所示。 在咱们IC后端训练营项目中也会遇到这类DRC Violation。这类DRC Violation的本质是出现Metal的Notch,即metal有凹槽。 如果是pg net的 Min Step问题,我们可以使用下面的…

进程相关内容

进程内容 进程类型守护进程进程的概念查看进程信息父子进程创建子进程进程结束 – exit/_exit进程回收 –wait waitpid 进程类型 交互进程 (Interactive Process) 交互进程是由用户通过终端或图形界面直接启动的进程,例如我们在命令行输入的命令。它通常需要等待用…

石墨舟氮气柜:半导体制造中的关键保护设备

石墨舟是由高纯度石墨材料制成的,主要用于承载硅片或其他基板材料通过高温处理过程,是制造半导体器件和太阳能电池片的关键设备之一。 石墨舟在空气中容易与氧气发生反应,尤其是在高温处理后,表面可能更为敏感;石墨舟具…

rabbitMq双节点高可用集群安装(亲测可用)

查询系统版本 cat /etc/redhat-release CentOS Linux release 7.7.1908 (Core) rabbitmq v3.9.13 (centos7支持比较大的版本了,后面版本貌似都是centos8以上) erlang erlang-23.3.4.11-1.el7.x86_64 (需要和rabbitmq版本匹配&…

简单介绍一下mvvm mvc mvp以及区别、历史

MVC(Model - View - Controller) 因MVC架构的灵活性,架构图形式很多,仅供参考 历史: MVC 是最早出现的软件架构模式之一,其历史可以追溯到 20 世纪 70 年代,最初被用于 Smalltalk - 80 环境。…

Nordic SoftDevice蓝牙主机操作流程

Nordic SoftDevice蓝牙主机操作流程 之前学习nordic的nus client 主机例程时做了些笔记,现在有空重新整理了一下发出来。 NRF_SDH_BLE_OBSERVER 宏介绍 这个宏可以设置多个BLE事件的回调函数,并按设置的优先级依次执行。这么一来,就可以将…

C++生成高斯分布随机数

简单实现 在 C 中&#xff0c;可以使用 头文件中的功能来生成正态分布&#xff08;高斯分布&#xff09;随机数。以下是一个示例&#xff0c;展示如何使用 C11 及以上版本的标准库生成正态分布随机数。 #include <iostream> #include <random> #include <cmat…

SL6115降压恒流 60V降压恒流芯片,高精度1%,PWM模拟调光

一、核心参数与性能 工作电压范围&#xff1a;5.5V至60V&#xff0c;宽输入电压范围使其能够适应多种应用场景。 最大输出电流&#xff1a;根据公开发布的信息&#xff0c;SL6115的最大输出电流可达到1.2A至1.5A&#xff0c;具体取决于不同版本或制造商的规格说明。这一高输出…

lnmp:自己的“百度网盘”

一、项目简介 有人会问&#xff0c;什么是lnmp储存&#xff0c;相信大家都用过百度网盘&#xff0c;他的原理和lnmp的作用相同&#xff0c;都是将数据储存在私有云中。LNMP也是用来储存自己的数据&#xff0c;可以假象成这是一个属于自己的数据库。 二、详细概述 所谓LNMP便是…

「实战应用」如何用图表控件LightningChart .NET在WPF中制作表格?(一)

LightningChart .NET完全由GPU加速&#xff0c;并且性能经过优化&#xff0c;可用于实时显示海量数据-超过10亿个数据点。 LightningChart包括广泛的2D&#xff0c;高级3D&#xff0c;Polar&#xff0c;Smith&#xff0c;3D饼/甜甜圈&#xff0c;地理地图和GIS图表以及适用于科…

鸿蒙进阶篇-网格布局 Grid/GridItem(二)

hello大家好&#xff0c;这里是鸿蒙开天组&#xff0c;今天让我们来继续学习鸿蒙进阶篇-网格布局 Grid/GridItem&#xff0c;上一篇博文我们已经学习了固定行列、合并行列和设置滚动&#xff0c;这一篇我们将继续学习Grid的用法&#xff0c;实现翻页滚动、自定义滚动条样式&…

SpringBoot框架:共享汽车管理的创新工具

5系统详细实现 5.1 管理员模块的实现 5.1.1 用户信息管理 共享汽车管理系统的系统管理员可以管理用户&#xff0c;可以对用户信息修改删除以及查询操作。具体界面的展示如图5.1所示。 图5.1 用户信息管理界面 5.1.2 投放地区管理 系统管理员可以对投放地区信息进行添加&#…

uniapp上拉刷新下拉加载

方法一&#xff1a; z-paging 的组件库&#xff1a; show-loading-more-no-more-view"false" 该属性控制是否显示 "加载更多" 或 "没有更多" 的提示。如果设为 false&#xff0c;则不会显示这些提示。如果设为 true&#xff0c;当数据加载完毕…

【Pikachu靶场:XSS系列】xss之过滤,xss之htmlspecialchars,xss之herf输出,xss之js输出通关啦

一、xss之过滤 <svg onloadalert("过关啦")> 二、xss之htmlspecialchars javascript:alert(123) 原理&#xff1a;输入测试文本为herf的属性值和内容值&#xff0c;所以转换思路直接变为js代码OK了 三、xss之href输出 JavaScript:alert(假客套) 原理&#x…

微分段如何防止勒索软件攻击

微分段通过隔离关键资产、限制网络横向移动、提供细粒度的最小特权访问、实现快速隔离、简化恢复、提高网络弹性以及减少爆炸半径来防止勒索软件攻击。 勒索软件攻击已成为各种规模的组织面临的越来越危险的威胁。 勒索软件利用横向移动技术来感染和加密尽可能多的端点和服务…