维度扩展
x.unsqueeze(n)
在 n 号位置添加一个维度
例子:
import torch
x = torch.rand(3,2)
x1 = x.unsqueeze(0) # 在第一维的位置添加一个维度
x2 = x.unsqueeze(1) # 在第二维的位置添加一个维度
x3 = x.unsqueeze(2) # 在第三维的位置添加一个维度
print(x1.shape)
print(x2.shape)
print(x3.shape)
>> torch.Size([1, 3, 2])
>> torch.Size([3, 1, 2])
>> torch.Size([3, 2, 1])
由上面的例子可见,tensor.unsqueeze(n) 可以很方便的为tensor添加一个维度,那么是不是可以在tensor的任意维度上添加一个维度呢,答案是否定的,即参数 n 存在范围,n 位于 [-(dim+1), dim]; 其中 dim为tensor的维度的个数,比如在上例中,tensor x 的dim = 2, 即在上例中 n 不位于 [-3, 2] 时会报错。如下:
import torch
x = torch.rand(3,2)
x1 = x.unsqueeze(3)
x2 = x.unsqueeze(-4)
print(x1.shape)
print(x2.shape)
>> IndexError: Dimension out of range (expected to be in range of [-3, 2], but got 3)
>> IndexError: Dimension out of range (expected to be in range of [-3, 2], but got -4)
没错,n 的值还能是负数,其负数表示的是在从右往左的 |n| 的维数上增加一维,例:
import torch
x = torch.rand(3,2)
x1 = x.unsqueeze(-1)
x2 = x.unsqueeze(-2)
print(x1.shape)
print(x2.shape)
>> torch.Size([3, 2, 1])
>> torch.Size([3, 1, 2])
此外还有一种语法的变体torch.unsqueeze(x,n)
, 作用同 x.unsqueeze(n)
,都表示在第n位的位置添加1维,只不过语法稍有区别。
维度压缩
x.squeeze(n)
对 第 n 维 的位置进行维度压缩,如果该位置的维度值为1 ,则压缩,否则不进行任何操作。而当不设置 参数 n 时 即:x.squeeze()
,则对tensor x 的所有维度值为1的维度进行压缩,而其余不为1 的维度不进行处理。如下:
import torch
x = torch.rand(3,2,1)
x1 = x.squeeze(2) # n号位置上的维度为1。 压缩
x2 = x.squeeze(1) # n号位置上的维度不为1。 不处理
x3 = x.unsqueeze(0)
x3 = x3.squeeze() # 对tensor x3 的所有维度为1的维度压缩
>> torch.Size([3, 2])
>> torch.Size([3, 2, 1])
>> torch.Size([3, 2])
同样的,与 unsqueeze()
一样,squeeze(n)
的 参数 n 一样存在范围,且均为 [-(dim+1), dim]; 其中 dim为tensor的维度的个数,在上例中,tensor x 的dim = 2。当n超过这个范围时就会报错。如下:
import torch
x = torch.rand(3,2,1)
x1 = x.squeeze(4)
print(x1)
>> IndexError: Dimension out of range (expected to be in range of [-3, 2], but got 4)
也同样的,此外还有一种语法的变体torch.squeeze(x,n)
, 作用同 x.squeeze(n)
,都表示在第n位的位置压缩维度(如果该位置维度为1),只不过语法稍有区别。
Tips -- .size() 和 .shape 的异同
同:两者都可以获得tensor的维度大小:
import torch
x = torch.rand(3,2,1)
print(x.shape)
print(x.size())
>> torch.Size([3, 2, 1])
>> torch.Size([3, 2, 1])
异: shape 是一个Tensor类中的属性,作为Tensor类的实例可以直接通过 . 的方式获得shape属性,即获得tensor的维度的大小;
size() 是 Tensor类继承来的无参方法,所以其要带小括号,Tensor类的实例也可以调用类的成员方法。
另外,在 python 的库 numpy 中,size和shape 是numpy中的函数,size()计算矩阵中所有元素的个数;shape()返回矩阵的维度值。如下:
import numpy as np
x = np.array([[1,2,3],[4,5,6],[7,8,9]])
print(np.shape(x))
print(np.size(x))
print(x.shape[0]) # 显示矩阵的行数
>> (3, 3)
>> 9
>> 3