Pytorch量处理中的一些小细节(reshape和view,cat和Unet中心剪裁以及警告:UserWarning: non-inplace resize is deprecated warn)

view与reshape

关于连续

 reshape和view区别的验证

张量不连续如何解决

关于cat()

 举几个例子

两个维度数不一样的张量进行cat拼接

两个二维张量进行沿行拼接,列不变

 两个二维张量进行沿列拼接,行不变

两个三位张量进行沿通道拼接, 其他维度数不变

 关于中心裁剪

关于UserWarning: non-inplace resize is deprecated warnings.warn("non-inplace resize is deprecated")


view与reshape

reshape方法会尝试创建一个新的张量,其元素与原始张量共享内存空间。如果原始张量在内存中是连续的,reshape将返回一个指向相同数据的新张量视图;如果原始张量在内存中不连续,reshape可能会先将其复制为连续的张量,然后再返回新形状的张量。这意味着,在某些情况下,reshape可能会导致额外的内存开销。

view方法则不会创建一个新的张量,而是直接返回一个与原始张量共享数据存储的新视图。如果原始张量和新的视图张量上的元素被修改,它们会互相影响,因为它们共享相同的数据。

注意:上述话的的意思其实就是,reshape方法会创建一个新张量,而view方法不会,他们两个返回的数据都是和原始张量在同一片空间,这一点我们可以使用resize_()方法进行验证,然后reshape会依据原始张量是否连续来进行相应的操作,但是view不行,如果原始数据不连续的话他就没办法操作里,(就会报错)。

这里提到了张量的连续性,那么这个连续性究竟是什么?

关于连续

如果原始张量是连续的,那么它的一维展开顺序与按行优先存储的顺序一致。

举个例子:        

首先我们要知道:在PyTorch中,张量(Tensor)的实际数据以一维数组(storage)的形式存储于连续的内存中,通常采用“行优先”的存储方式。这意味着,当张量被视为多维数组时,其元素在内存中的排列顺序是按照行(或称为“外层维度”)来确定的。

而转置(transpose)操作会改变张量的维度顺序,但不会改变其底层数据的物理位置。例如,一个形状为(m, n)的二维张量在转置后,其形状变为(n, m),但转置前后的张量共享同一个底层存储(storage)

例如:

假设有一个形状为(2, 3)的二维张量a,其内容为[[1, 2, 3], [4, 5, 6]]。在内存中,这个张量的一维展开顺序是[1, 2, 3, 4, 5, 6]。当对a进行转置操作得到张量b(形状为(3, 2))时,虽然b的内容仍然是[1, 2, 3, 4, 5, 6],但按照(3, 2)的形状来访问时,其元素在内存中的排列顺序就不再是[1, 2, 3, 4, 5, 6]了(实际上,由于共享同一个storage,物理上的排列顺序并未改变,但逻辑上的访问顺序变了)。因此,b被视为非连续张量。

所以我们就说,如果一个连续的数据转置后,他一维展开顺序发生变化,但是他在物理存储顺序还是和之前一样,所以就不连续。

判断是否连续的方法:.is_contiguous()

 reshape和view区别的验证

import torch

a=[[1,2,3],[1,2,3]]
b1=torch.tensor(a)
b2=torch.tensor(a)
b3=torch.tensor(a)
print('b1是否连续:',b1.is_contiguous())
print('b2是否连续:',b2.is_contiguous())
print('b3是否连续:',b2.is_contiguous())
print('b1.shape:',b1.shape)
print('b2.shape:',b1.shape)
print('b3.shape:',b2.shape)
print('*---------------------------*')
c1=b1.reshape(3,2)
c2=b2.view(3,2)
print('c1:',c1)
print('c1的地址:',id(c1))
c1.resize_(2,3)
print('c1',c1)
print('b1:',b1)
print('c1的地址:',id(c1))
print('c1是否连续:',c1.is_contiguous())
print('*---------------------------*')
print('c2:',c2)
print('c2的地址:',id(c2))
c2.resize_(2,3)
print('c2',c2)
print('b2:',b2)
print('c2的地址:',id(c2))
print('c2是否连续:',c2.is_contiguous())
print('*---------------------*')
b3=torch.t(b3)
print('b3:',b3)
print('b3是否连续:',b3.is_contiguous())
print('对b3使用view方法:')
print(b3.view(2,3))
<think>好的,我现在需要解决用户关于PyTorch中出现的“UserWarning: non-inplace resize is deprecated警告的问题。用户已经提供了一些相关的引用内容,我需要仔细分析这些信息,并结合自己的知识来给出准确的解决方案。 首先,用户提到的引用[1]中说明,这个警告是因为使用了非原地(non-inplace)的resize方法,而PyTorch推荐使用带有下划线的resize_方法来进行原地操作。原地操作可以避免创建新的张对象,从而节省内存并提升性能。因此,解决方案的第一步应该是检查代码中是否有使用torch.Tensor.resize的地方,并将其替换为resize_。 不过,我需要考虑可能存在的例外情况。例如,如果原张是不可变的或者需要保留原始数据,直接使用resize_可能会修改原始数据,导致问题。这时候可能需要先复制张,再进行操作。但一般来说,在PyTorch中,张默认是可变的,所以多数情况下可以直接替换。 另外,引用[2]提到PIL库中的resize函数也有类似的弃用警告,但用户的问题是关于PyTorch的,所以暂时不需要处理PIL的部分。但需要确认用户是否在代码中同时使用了这两个库,避免混淆。 接下来,我需要确保给出的步骤清晰易懂。用户可能需要知道如何找到代码中使用resize的地方,并正确替换为resize_。同时,需要提醒他们在使用原地操作时要注意张是否被其他部分引用,避免意外的副作用。 可能的疑问点包括:为什么原地操作更好?如何判断何时可以使用resize_?如果替换后出现错误该怎么办?这些都需要在回答中简要说明,以帮助用户理解背后的原因,而不仅仅是机械地替换代码。 最后,生成的相关问题需要围绕这个警告展开,比如原因、其他类似警告、性能影响等,这样用户可以进一步扩展知识。</think>关于PyTorch中出现的`UserWarning: non-inplace resize is deprecated`警告,以下是详细解决方案及背景说明: ### 问题原因 1. **方法区分**:PyTorch中`resize`(非原地操作)与`resize_`(原地操作)的区别在于: - `resize`会创建新张并返回,原张不变 - `resize_`直接修改原张的形状(带下划线的为原地操作) 2. **弃用逻辑**:PyTorch推荐使用原地操作以提高内存效率,避免不必要的内存分配[^1] ### 解决方案 #### 方法1:直接替换为原地操作(推荐) ```python # 原始代码(触发警告) tensor = tensor.resize(new_shape) # 修改后代码 tensor.resize_(new_shape) # 注意下划线赋值方式 ``` #### 方法2:使用更安全的替代方案 当需要保留原始张时: ```python # 创建副本后再修改 new_tensor = tensor.clone().resize_(new_shape) ``` #### 方法3:使用view/reshape方法(需满足连续性) ```python # 当张内存连续时可用 tensor = tensor.view(new_shape) # 或.reshape() ``` ### 注意事项 1. **形状兼容性**:新形状元素总数必须与原张一致(如原shape是(2,3),新shape可以是(3,2)但不能是(4,2)) 2. **梯度传播**:原地操作会中断梯度计算链,训练时需谨慎使用`resize_` 3. **设备一致性**:确保操作在相同设备上执行(CPU/GPU) ### 验证示例 ```python import torch # 原始触发警告的写法 x = torch.randn(2,3) y = x.resize(3,2) # 触发UserWarning # 正确修改方案 x = torch.randn(2,3) x.resize_(3,2) # 不产生警告且内存地址不变 print(x.data_ptr() == x.data_ptr()) # 输出True ``` ### 扩展建议 - 使用`torch.reshape()`可自动处理连续性问题 - 通过`tensor.contiguous()`确保内存连续性 - 使用`torch.utils.data._utils.pin_memory.pinned_batch_resize`处理特殊场景
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值