张量

Tensor(张量)是 Pytorch 里最基本的操作对象,它表示的是一个多维矩阵,并可以进行矩阵运算操作。

基本数据类型

Python 中的数据类型在 Pytorch 中基本都有对应,如 Python 中的 Int 类型对应 Pytorch 中的 IntTensor,不过这个 Tensor 的维度为 0,下面是两者完整的数据类型对应表:

| Python 数据类型 | Pytorch 数据类型 | CPU Tensor | | :—-: | :—-: | :—-: | | 32-bit floating point | torch.float32 / torch.float | torch.FloatTensor | | 64-bit floating point | torch.float64 / torch.double | torch.DoubleTensor | | 16-bit floating point | torch.float16 / torch.half | torch.HalfTensor | | 8-bit integer (unsigned) | torch.unit8 | torch.ByteTensor | | 8-bit integer (signed) | torch.int8 | torch.CharTensor | | 16-bit integer (signed) | torch.int16 / torch.short | torch.ShortTensor | | 32-bit integer (signed) | torch.int32 / torch.int | torch.IntTensor | | 64-bit integer (signed) | torch.int64 / torch.long | torch.LongTensor |

另外,Pytorch 作为一个数据计算库,它是没有内建的 String 类型支持的,但我们有两种方式可以在 Pytorch 中用数字表示 String 类型。

  • One-hot 编码

我们可以通过一个 0/1 单位向量来表示一个字符串,1 的位置标识字符串。比如某个环境下有 cat 和 dog 两种动物,可以使用 [1, 0] 表示字符串 “cat”,使用 [0, 1] 表示字符串 “dog”。

  • Embedding 嵌入

由于 One-hot 编码方式中的字符串由 1 的位置标识,字符串之间的联系就被忽略了,另外 One-hot 编码中的 0 比较多,浪费了很多空间,嵌入的方式可以解决这两个问题。我们可以通过一些方法对语料库进行提取来生成一个 Embedding 嵌入矩阵,矩阵可以给每个单词分配一个固定长度的向量表示(长度自定,一般会远小于语料库中所有单词的个数),使用单词向量之间的夹角值(如余弦函数值)表示单词之间的联系。常见的嵌入模型有 Word2Vec 和 Glove。

创建 Tensor

Pytorch 提供的创建 Tensor 的接口比较多,大体可以分为从 numpy 数组创建 Tensor、从列表数据创建 Tensor、未定义初始化创建 Tensor、随机初始化创建 Tensor 和指定初始化创建 Tensor。

从 numpy 数组创建 Tensor

使用torch.from_numpy()创建 Tensor,函数参数接收 numpy 数组,新建 Tensor 的数据类型对应原 numpy 数组的数据类型。

  1. import numpy as np
  2. import torch
  3. # # 从 numpy 数组创建 Tensor
  4. # 创建的 Tensor 的数据类型对应原 numpy 数组的数据类型
  5. a = np.array([1, 2])
  6. print(a.dtype) # int32
  7. tensor_a = torch.from_numpy(a)
  8. print(tensor_a) # tensor([1, 2], dtype=torch.int32)
  9. b = np.array([2, 3.2])
  10. print(b.dtype) # float64
  11. tensor_b = torch.from_numpy(b)
  12. print(tensor_b) # tensor([2.0000, 3.2000], dtype=torch.float64)

从列表创建 Tensor

通过列表数据创建 Tensor 的常用接口有torch.tensor()torch.Tensor(),两者都可以接收 List 类型的数据。与前者不同的是,torch.Tensor()也可以通过接收维度信息创建 Tensor,例如torch.Tensor(3, 2)可以创建一个未初始化三行两列的 Tensor。至于新建 Tensor 的数据类型,我们可以通过torch.set_default_tensor_type()设置创建 Tensor 的默认数据类型。

  1. # # 从列表创建 Tensor
  2. # 使用 torch.tensor 创建
  3. # 一维
  4. tensor_c = torch.tensor([1, 0])
  5. print(tensor_c) # tensor([1, 0])
  6. print(torch.tensor([1., 2.]).type()) # torch.FloatTensor
  7. # 设置 tensor 的默认类型
  8. torch.set_default_tensor_type(torch.DoubleTensor)
  9. print(torch.tensor([1., 2.]).type()) # torch.DoubleTensor
  10. # 二维
  11. tensor_c = torch.tensor([[1], [0]])
  12. print(tensor_c)
  13. # tensor([[1],
  14. # [0]])
  15. # 查看数据类型
  16. print(tensor_c.type()) # torch.LongTensor
  17. # 使用 torch.Tensor 创建
  18. # 通过数据创建 Tensor
  19. tensor_d = torch.Tensor([1, 0])
  20. print(tensor_d) # tensor([1., 0.])
  21. # 通过维度创建 Tensor
  22. tensor_d = torch.Tensor(2, 3)
  23. print(tensor_d) # 产生初始化的数据,随机结果
  24. # tensor([[1.7802e-306, 1.0681e-306, 1.2461e-306],
  25. # [9.3461e-307, 2.2252e-306, 1.1126e-306]])

未定义初始化创建 Tensor

通过 torch.Tensor 可以衍生出torch.FloatTensor()torch.IntTensor(),它们都可以通过接收维度信息创建未初始化的 Tensor,以申请内存空间,它们生成的数据是未定义无规律的,同样可以这样创建 Tensor 的接口还有torch.empty()。因为未定义初始化生成的数据没有定义,经常会出现一些极大或极小的值,我们通常不使用这一方式创建 Tensor 以避免一些隐患。

随机初始化创建 Tensor

更多地我们会使用随机初始化创建 Tensor,常用的随机初始化函数有 torch.rand() 和 torch.randint()。Rand 函数接收维度参数,生成的 Tensor 中的每一个数据都是在 [0, 1] 分布中均匀取样出来的。同 rand 函数类似,randint 用于生成随机整数数据。torch.randint(a, b, *c) 接收三个参数,a、b 参数限定取样的范围在 [a, b) 中,c 参数接收维度信息列表。在实验过程中,我们可能需要随机初始化一些未知维度的 Tensor,可以通过 torch.rand_like() 和另外一个 Tensor 生成与该 Tensor 维度相同的 Tensor。