Pytorch深度学习实战3-3:张量Tensor的分块变形排序极值与in-place操作
Posted Mr.Winter`
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Pytorch深度学习实战3-3:张量Tensor的分块变形排序极值与in-place操作相关的知识,希望对你有一定的参考价值。
目录
以下示例均假设
a = torch.Tensor([[0,1,2],[3,4,5]])
b = torch.Tensor([[6,7,8],[9,10,11]]))
1 张量分块
分块方法
torch.chunk(tensor,num,dim)
:将张量沿dim分成num块torch.split(tensor,size,dim)
:将张量沿dim按size均分
实例
torch.chunk(a, 2, dim=0)
>> (tensor([[0., 1., 2.]]),
tensor([[3., 4., 5.]]))
torch.chunk(a, 2, dim=1)
>> (tensor([[0., 1.], [3., 4.]]),
tensor([[2.],[5.]]))
torch.split(a, [1,2], dim=1)
>> (tensor([[0.],[3.]]),
tensor([[1., 2.], [4., 5.]]))
2 张量组合
组合方法
torch.cat([tensor...],dim)
:沿已有维度dim拼接,除dim外其他维度与原先相同torch.stack([tensor...],dim)
:新增维度dim堆叠
实例
torch.cat([a,b],dim=0)
>> tensor([[ 0., 1., 2.],
[ 3., 4., 5.],
[ 6., 7., 8.],
[ 9., 10., 11.]])
torch.cat([a,b],dim=1)
>> tensor([[ 0., 1., 2., 6., 7., 8.],
[ 3., 4., 5., 9., 10., 11.]])
torch.stack([a,b],dim=0)
>> tensor([[[ 0., 1., 2.],
[ 3., 4., 5.]],
[[ 6., 7., 8.],
[ 9., 10., 11.]]])
torch.stack([a,b],dim=1)
>> tensor([[[ 0., 1., 2.],
[ 6., 7., 8.]],
[[ 3., 4., 5.],
[ 9., 10., 11.]]])
torch.stack([a,b],dim=2)
>> tensor([[[ 0., 6.],
[ 1., 7.],
[ 2., 8.]],
[[ 3., 9.],
[ 4., 10.],
[ 5., 11.]]])
Tensor的stack()
堆叠机制阐述如下。堆叠维度dim
是相对待堆叠张量而言,若dim=0
则表明在新增维度上依次堆叠,而原张量在该维度下没有分量,故将整个张量视为整体;若dim>0
则表明以已有维度为基准依次堆叠。
3 张量变形
3.1 维度变换
变形方法
torch.reshape(newshape)
torch.resize_(newshape)
实例
a.reshape(3,2)
a.reshape(-1,2) # 用-1占位隐式表示3x2
>> tensor([[0., 1.],
[2., 3.],
[4., 5.]])
3.2 维度交换
变形方法
tensor.transpose(dim0,dim1)
tensor.permute([newdim])
实例
# 维度交换
c = torch.stack([a,b],dim=0) # 2x2x3
>> tensor([[[ 0., 1., 2.],
[ 3., 4., 5.]],
[[ 6., 7., 8.],
[ 9., 10., 11.]]])
# transpose交换两个指定维度
c.transpose(0,1) # 2x2x3
>> tensor([[[ 0., 1., 2.],
[ 6., 7., 8.]],
[[ 3., 4., 5.],
[ 9., 10., 11.]]])
# permute指定新的维度顺序
c.permute(2,1,0) # 3x2x2
>> tensor([[[ 0., 6.],
[ 3., 9.]],
[[ 1., 7.],
[ 4., 10.]],
[[ 2., 8.],
[ 5., 11.]]])
3.3 序列化与反序列化
变形方法
torch.squeeze(N)
torch.unsqueeze(N)
实例
# 将a(2x3)第1维序列化为(2x1x3)
c = a.unsqueeze(1)
>> c: tensor([[[0., 1., 2.]],
[[3., 4., 5.]]])
# 将c(2x1x3)第1维反序列化为(2x3)
c.squeeze(1)
>> tensor([[0., 1., 2.],
[3., 4., 5.]])
3.4 扩展
变形方法
tensor.expand(newshape)
tensor.expand_as(tensor)
实例
a.expand(2,2,3)
>> tensor([[[0., 1., 2.],
[3., 4., 5.]],
[[0., 1., 2.],
[3., 4., 5.]]])
a.expand_as(torch.randn(2,2,3))
>> tensor([[[0., 1., 2.],
[3., 4., 5.]],
[[0., 1., 2.],
[3., 4., 5.]]])
以复制元素形式扩展新维度或已存在的单维度,所有复制元素都与源元素共享内存
4 张量排序
Pytorch中使用tensor.sort()
函数对张量沿指定维度排序,返回排序后的张量及对应索引位置,其中descending=True
表示降序,descending=False
表示升序。
举例
a= torch.randn(3,3)
>> tensor([[ 1.1976, 0.2529, -0.9852],
[-0.2465, -0.2176, -1.4343],
[ 0.9259, -0.7622, 0.1692]])
# 沿第0维即沿行排序,每列均为降序排列
a.sort(0, descending=True)
>> (tensor([[ 1.1976, 0.2529, 0.1692],
[ 0.9259, -0.2176, -0.9852],
[-0.2465, -0.7622, -1.4343]]),
tensor([[0, 0, 2],
[2, 1, 0],
[1, 2, 1]]))
5 张量极值
Pytorch中使用tensor.max()
和tensor.min()
函数对张量沿指定维度取极值,并返回极值组成的向量和极值在指定维度的索引。
举例
a= torch.randn(3,3)
>> tensor([[ 0.8160, 1.5793, -0.6898],
[ 0.5470, -1.2048, 0.7410],
[ 0.6604, 0.1297, -1.2990]])
# 沿第0维即沿行取最大值,输出向量为每列最大值
a.max(0)
>> (tensor([0.8160, 1.5793, 0.7410]), tensor([0, 0, 1]))
6 in-place操作与共享内存
Pytorch中部分操作会产生内存共享的变量,主要包括:
- 通过组合、分块、索引、变形等手段,用Tensor初始化另一个Tensor,此时这两个Tensor指向同一片内存数据;
- Tensor和Numpy数据转换前后的变量指向同一片内存数据。
举例
a=torch.Tensor([[0,1,2],[3,4,5]])
b = a.reshape(3,2)
b[0,0]=100
>> b:tensor([[100., 1.],
[ 2., 3.],
[ 4., 5.]])
>> a:tensor([[100., 1., 2.],
[ 3., 4., 5.]])
本质上共享内存是由Python引用对象造成的,若要改变这种浅拷贝,需要借助copy.deepcopy()
等深拷贝方式。
为实现高效计算,Pytorch提供原地操作in-place operation
机制,即不经过拷贝,直接在原内存地址的数据上进行操作,降低内存占用的同时提高运算速度。Pytorch中以_
为后缀的方法属于in-place operation
,这种方法只要被执行,调用该方法的Tensor随即发生相应改变。
举例
a=torch.Tensor([[0,1,2],[3,4,5]])
>> a:tensor([[100., 1., 2.],
[ 3., 4., 5.]])
a.resize_(3,2)
>> a:tensor([[0., 1.],
[2., 3.],
[4., 5.]])
必须指出,以下场合不能使用in-place operation
,否则发生RuntimeError
:
- 对于在求梯度阶段需要用到的张量,不能使用
in-place operation
; - 对于
requires_grad=True
的叶子张量不能使用in-place operation
🔥 更多精彩专栏:
以上是关于Pytorch深度学习实战3-3:张量Tensor的分块变形排序极值与in-place操作的主要内容,如果未能解决你的问题,请参考以下文章
深度学习-Pytorch张量tensor详解(线性回归实战)