【PyTorch】Tensor相关操作记录

最近毕业论文写得差不多了,就打算把一些平时经常会用到知识记录一下,方便以后忘了可以看看。先把本文参考的资料列在前面:

  • https://deeplizard.com/learn/video/AglLTlms7HU

目录

  • 一、数据类型变换
    • (一)其他类型转换为Tensor类型
    • (二)Tensor类型转换为其他类型
  • 二、获取Tensor的shape
  • 三、squeeze和unsqueeze
  • 四、cat
  • 五、stack
  • 六、sum
  • 七、max和argmax
  • 八、Element-wise运算
  • 九、四种乘法运算
    • (一)按位相乘
    • (二)矩阵乘法

一、数据类型变换

(一)其他类型转换为Tensor类型

创建Tensor有四种方式:

  1. torch.Tensor(data)Tensor类的构造函数;数据类型只能是float32;不共享内存。
  2. torch.tensor(data):数据类型根据传入的数据而定,或通过传入dtype来指定;不共享内存。
  3. torch.as_tensor(data):根据传入数据或传入dtype来决定数据类型;共享内存。
  4. torch.from_numpy(data):仅接受np.array的输入数据;根据传入数据或传入dtype来决定数据类型;共享内存。

综上,更推荐使用torch.tensor(data)torch.as_tensor(data)来创建Tensor。

> data = np.array([1,2,3])

> o1 = torch.Tensor(data)
> o2 = torch.tensor(data)
> o3 = torch.as_tensor(data)
> o4 = torch.from_numpy(data)

> print(o1)
> print(o2)
> print(o3)
> print(o4)
tensor([1., 2., 3.])
tensor([1, 2, 3], dtype=torch.int32)
tensor([1, 2, 3], dtype=torch.int32)
tensor([1, 2, 3], dtype=torch.int32)

> print(o1.dtype)
> print(o2.dtype)
> print(o3.dtype)
> print(o4.dtype)
torch.float32
torch.int32
torch.int32
torch.int32

# 是否共享内存
> print('old:', data)
old: [1 2 3]

> data[0] = 0

> print('new:', data)
new: [0 2 3]

> print(o1)
> print(o2)
> print(o3)
> print(o4)

tensor([1., 2., 3.])
tensor([1, 2, 3], dtype=torch.int32)
tensor([0, 2, 3], dtype=torch.int32)
tensor([0, 2, 3], dtype=torch.int32)

(二)Tensor类型转换为其他类型

  • Tensor → Scaler
  • Tensor → List
  • Tensor → Array
> t = torch.tensor([
    [1,2,3],
    [4,5,6],
    [7,8,9]
], dtype=torch.float32)

> t.mean()
tensor(5.)

# Tensor → Scaler
> t.mean().item()
5.0

# Tensor → List
> t.mean(dim=0).tolist()
[4.0, 5.0, 6.0]

# Tensor → Array
> t.mean(dim=0).numpy()
array([4., 5., 6.], dtype=float32)

二、获取Tensor的shape

获取Tensor的shape有两种种方式:

  1. t.size()
  2. t.shape
> t = torch.tensor([
    [1,1,1,1],
    [2,2,2,2],
    [3,3,3,3]
], dtype=torch.float32)

> t.size()
> t.shape
torch.Size([3, 4])
torch.Size([3, 4])

> t.size(0)
> t.shape[0]
3
3

三、squeeze和unsqueeze

  1. torch.squeeze(input, dim=None, out=None) → Tensor
    - 指定dim:如果指定的维度的维数是1,则删除该维度;否则,不作任何操作。
    - 不指定dim:删除所有维数为1的维度。
  2. torch.unsqueeze(input, dim, out=None) → Tensor
    在指定维度dim上增加一个维度。
> t = torch.tensor([
    [1,1,1,1],
    [2,2,2,2],
    [3,3,3,3]
], dtype=torch.float32)

> t.size()
torch.Size([3, 4])

# squeeze - 指定维度的维数不为1
> torch.squeeze(t, dim=0)
tensor([[1., 1., 1., 1.],
        [2., 2., 2., 2.],
        [3., 3., 3., 3.]])

> t = t.reshape([1,12])
> t.size()
torch.Size([1, 12])

# squeeze - 指定维度的维数为1
> torch.squeeze(t, dim=0)
> torch.squeeze(t, dim=0).size()
tensor([1., 1., 1., 1., 2., 2., 2., 2., 3., 3., 3., 3.])
torch.Size([12])

# unsqueeze
 > t = torch.unsqueeze(t, dim=2)
 > t.size()
torch.Size([1, 12, 1])

# unsqueeze - 不指定维度
 > t = torch.squeeze(t)
 > t.size()
torch.Size([12])

四、cat

torch.cat(tensors, dim=0, out=None) → Tensor:在指定dim上对Tensor进行拼接。

 > t = torch.cat((t1,t2,t3), dim=0)
 > t.size()
 torch.Size([3, 12, 1])

t1,t2,t3的维度都是(1,12,1),在dim=0上进行拼接,则得到为维度是(3,12,1)

五、stack

torch.stack(tensors, dim=0, out=None) → Tensor:在指定dim上增加一维,并在新增维度上对Tensor进行拼接。

 > t = torch.stack((t1,t2,t3), dim=0)
 > t.size()
 torch.Size([3, 1, 12, 1])

t1,t2,t3的维度都是(1,12,1)torch.stack()dim=0上先新增一个维度,再在该维度上进行拼接,则得到为维度是(3,1,12,1)

六、sum

torch.sum(input, dim=None) → Tensor:求和。

# 不指定dim
> t = torch.tensor([
    [0,1,0],
    [2,0,2],
    [0,3,0]
], dtype=torch.float32)
> t.sum()
tensor(8.)

# 指定dim
> t = torch.tensor([
    [1,1,1,1],
    [2,2,2,2],
    [3,3,3,3]
], dtype=torch.float32)
> t.sum(dim=0)
tensor([6., 6., 6., 6.])

七、max和argmax

torch.max(input, dim=None) → Tensor:求最大值。
torch.argmax(input, dim=None) → Tensor:求最大值对应的下标。

 > t = torch.tensor([
    [1,0,0,2],
    [0,3,3,0],
    [4,0,0,5]
], dtype=torch.float32)

# 不指定dim,返回整个Tensor最大值的下标
> t.max()
tensor(5.)

> t.argmax()
tensor(11)

# 指定dim,返回指定轴上最大值下标
> t.max(dim=0)
(tensor([4., 3., 3., 5.]), tensor([2, 1, 1, 2]))

> t.argmax(dim=0)
tensor([2, 1, 1, 2])

八、Element-wise运算

逐元素运算有四种情况:

  1. t1+t2t1t2shape相同:两者直接按位进行运算。
  2. t1+2t1-2t1*2t1/2:先对2进行了broadcasting,然后再和t1运算。
  3. t1+t2,rank相同,shape不同。首先判断两个Tensor的各个维度是否兼容,满足兼容的情况有两个,二者满足其一即可:
    - 两个维度的维数相等
    - 有一个维度的维数是1
    例如:t1的shape是(1,2)t2的shape是(3,1)从后往前对比,各维度均满足上述的第二个条件,因此二者兼容。从后往前对比,先看第二维度,取最大值作为输出维度,即2,再看第一维度也是取最大值,即3。则输出的shape是(3,2),分别将t1t2广播成(3,2),然后再逐元素进行相加,得到最终的结果。
  4. t1+t2,rank不同。同样,首先判断两个Tensor的各个维度是否兼容,例如:
    - 例1:t1的维度(2,4)t2的维度是(4,)从后往前对比,最后一维相等,但是t2只有一维,那就在缺失的维度上补1,变成(1,4),然后再广播成(2,4),再和t1计算。
    - 例2:t1的维度(2,4)t2的维度是(2,)从后往前对比,最后一维不相等,因此t1t2的shape不兼容,无法进行下一步运算。
# Case 1
> t1 = torch.tensor([
    [1,2],
    [3,4]
], dtype=torch.float32)

> t2 = torch.tensor([
    [9,8],
    [7,6]
], dtype=torch.float32)

> t1 + t2
tensor([[10., 10.],
        [10., 10.]])

# Case 2
> t1 + 2
tensor([[3., 4.],
        [5., 6.]])

> t1 - 2
tensor([[-1.,  0.],
        [ 1.,  2.]])

> t1 * 2
tensor([[2., 4.],
        [6., 8.]])

> t1 / 2
tensor([[0.5000, 1.0000],
        [1.5000, 2.0000]])

除了四则运算外,以下运算也是Element-wise运算:

  • 比较:<,>,==,!=
  • 取绝对值:torch.abs()
  • 取反:torch.neg()
  • 开根:torch.sqrt()
> t = torch.tensor([
    [0,5,0],
    [6,0,7],
    [0,8,0]
], dtype=torch.float32)

# 比较
> t == 0
tensor([[True, False, True],
        [False, True, False],
        [True, False, True]])

# 取绝对
> t.abs() 
tensor([[0., 5., 0.],
        [6., 0., 7.],
        [0., 8., 0.]])

# 取反
> t.neg()
tensor([[-0., -5., -0.],
        [-6., -0., -7.],
        [-0., -8., -0.]])

# 开根
> t.sqrt()
tensor([[0.0000, 2.2361, 0.0000],
        [2.4495, 0.0000, 2.6458],
        [0.0000, 2.8284, 0.0000]])

九、四种乘法运算

(一)按位相乘

按位相乘的实现方法有两种,二者用法相同:

  • *:支持broadcast。
  • torch.mul(input, other, *, out=None)→ Tensor:支持broadcast。

(二)矩阵乘法

按位相乘的实现方法有两种:

  • torch.mm(input, mat2, *, out=None) → Tensor:只接受二维矩阵作为输入,且两个矩阵的shape满足矩阵乘法的要求,不支持broadcast。
  • torch.matmul(input, other, *, out=None) → Tensor:接受高维矩阵作为输入,支持broadcast。
    • 当输入都是二维Tensor时,就是普通的矩阵乘法,与tensor.mm用法相同。
    • 当输入有多维时,其余维度先广播到维数一致,然后最后两维做矩阵乘法。
# 二维的矩阵乘法
>>> a = torch.ones(3,4)
>>> b = torch.ones(4,5)
>>> c = torch.matmul(a,b)
>>> c.shape
torch.Size([3, 5])

# 高维的矩阵乘法
>>> a = torch.ones(2,1,3,4)
>>> b = torch.ones(5,4,2)
>>> c = torch.matmul(a,b)
>>> c.shape
torch.Size([2, 5, 3, 2])

你可能感兴趣的:(PyTorch)