向量#

pytorch 一般使用 torch.tensor() 创建向量。

tensor 称为张量、向量,但是数据概念上还有点区别:

  1. 标量: 零维, 只包含一个数字,比如 tensor.tensor(2)

  2. 向量: 一维或更高维度,多维数组数组,比如 tensor.tensor([1,2,3])tensor.tensor([[1,2,3], [4,5,6]])

向量拥有类型. 下面的例子,传入了浮点数,但是指定为 int 类型,所有数据最终被转为了 int:

a = tensor.tensor([1.9, 2.2], dtype=torch.int32)
print(a)
# tensor([1,2], dtype=torch.int32)

通过 numpy 创建 torch 向量#

import numpy as np
import torch

np_array = np.array(data)
x_np = torch.from_numpy(np_array)

通过其他 torch 向量创建#

这种方式一般用来创建与目标向量 相似 的向量. 如果要创建相同的向量,可以用 .copy().clone() 方法。

# 创建和 x_data 维度、类型一样的全 1 向量
x_ones = torch.ones_like(x_data)
print(f"Ones Tensor: \n {x_ones} \n")

# 创建和 x_data 维度、类型一样的随机向量,类型指定为 float
x_rand = torch.rand_like(x_data, dtype=torch.float)
print(f"Random Tensor: \n {x_rand} \n")

可以关注 torch 中 _like 后缀的一系列方法, 包括: empty_like/full_like/ones_like/rand_like/randint_like/randn_like/zeros_like

创建常见向量#

# 指定维度为 2 x 3
shape = (2, 3,)

rand_tensor = torch.rand(shape)
ones_tensor = torch.ones(shape)
zeros_tensor = torch.zeros(shape)

print(f"Random Tensor: \n {rand_tensor} \n")
print(f"Ones Tensor: \n {ones_tensor} \n")
print(f"Zeros Tensor: \n {zeros_tensor}")
Random Tensor:
 tensor([[0.3904, 0.6009, 0.2566],
        [0.7936, 0.9408, 0.1332]])

Ones Tensor:
 tensor([[1., 1., 1.],
        [1., 1., 1.]])

Zeros Tensor:
 tensor([[0., 0., 0.],
        [0., 0., 0.]])

向量维度#

向量维度是一个元组,即向量在每个维度上的长度

one_tensor = torch.tensor([[1,2,3], [4,5,6]])
print(one_tensor.shape) # (2, 3)

one_tensor 是一个 \(2*3\) 的向量,按顺序第 0 维长度是 2, 第 1 维长度是 3. 所以前面的是高维,后面是低维。 这个概念会在某些函数的 axis 参数上用到。

以 max 函数为例,我们创建一个 3x3x3 随机数矩阵: a = torch.rand((3,3,3)), 注意下面的维度对应关系:

  • b = a.max(axis=0): \(b_{j,k} = \max(a_{i,j,k})\)

  • b = a.max(axis=1): \(b_{i,k} = \max(a_{i,j,k})\)

向量类型和 device#

tensor = torch.rand(3, 4)

print(f"Shape of tensor: {tensor.shape}")
print(f"Datatype of tensor: {tensor.dtype}")
print(f"Device tensor is stored on: {tensor.device}")
Shape of tensor: torch.Size([3, 4])
Datatype of tensor: torch.float32
Device tensor is stored on: cpu

向量索引#

tensor = torch.tensor([[1,2,3], [4,5,6]])
print(tensor[0])  # tensor([1,2,3])
print(tensor[0, 1])  # tensor(2)
print(tensor[0, -1])  # tensor(3)
print(tensor[:, 1])  # tensor([2, 5])
print(tensor[..., 1])  # tensor([2, 5])

向量操作#

一般向量的运算不会改变向量本身,例如:

a = torch.rand((3, 3))
b = torch.rand((3, 3))

c = a + b
# 等价于 c=a+b
c = a.add(b)

以上操作会生成新的向量 c, 而不会改变 a/b ,如果要原地运算,可以使用带有下划线后缀的系列函数: a.add_(b), 运算结果会直接存放在 a 中。

torch 与 numpy 的互操作#

通过 .numpy() .from_numpy() 函数可以实现 numpy 向量与 torch 向量之间的互转。

one_tensor = torch.ones(5)

np_data = torch_tensor.numpy()
two_tensor = torch.from_numpy(np_data)

通过这两个方法转换后,他们的底层的数据其实是共享的。也就是说,修改 torch 向量后,对应的 numpy 向量也会改变,反之亦然。

tensor = torch.ones(3) # [1,1,1]
np_tensor = tensor.numpy()

np_tensor += 1 # np_tensor => [2,2,2]
print(tensor) # [2,2,2]