以下内容来自于曾芃壹的《PyTroch 深度学习入门》。
第二章 Tensor 张量基础
Tensor
Tensor 即张量,是 PyTorch 最基础的数据类型,是进行数据存储和运算的基本单元。
1. 数学含义
张量用来表示高维数据(矩阵),之前接触过的标量、向量都是张量的特例。标量是 0 维张量,向量是 1 维张量,矩阵则是 2 维张量,如果需要表示三维张量,则需要三个维度的坐标。

2. 创建方法
想要使用 PyTorch 里的张量,自然需要先导入 PyTorch:
使用 torch.Tensor()
函数创建 Tensor。这里传入参数是创建一个 2 × 4 大小的矩阵:
1 2 3 4 5
| x= torch.Tensor(2, 4) x
|
查看变量的类型:
以下显示的树 Tensor 的 8 种数据类型:

创建 2 × 3 × 4 的 64 位浮点数 Tensor:
1 2 3 4 5 6 7 8 9 10 11
| y = torch.DoubleTensor(2, 3, 4) y
|
创建 Tensor 的时候可以进行初始化,可以通过传入 List 数据结构进行初始化:
1 2 3 4 5 6
| list = [[1, 2, 3], [4, 5, 6], [7, 8, 9]] torch.Tensor(list)
|
通过 Python 的索引来获取 Tensor 的值(就像使用 Python 列表一样,索引也从 0 开始):
1 2 3 4
| x = torch.Tensor([[2, 4, 5], [7, 6, 3]]) x[0][2]
|

3. 快速创建方法
torch.zeros()
函数:创建全为 0 的 Tensor。
torch.eye()
函数:创建对角线位置元素全为 1、其他位置全为 0 的 Tensor。
torch.ones()
函数:创建全为 1 的 Tensor。
torch.rand()
函数:创建随机初始化区间为 [0, 1)
的随机数 Tensor。
torch.arange()
函数:创建一个在指定区间内按指定步长递增的一维 Tensor,前两个参数指定区间范围,第三个参数指定步长。
1 2 3 4 5 6
| torch.arange(1, 4)
torch.arange(1, 4, 0.5)
|
常用 Tensor 创建方法:

4. 常用数学操作
Tensor 的数学操作方法有 90 多中,以下是常见的 25 种数学操作方法:


Tensor 的数学操作实现方法一般有两种:1. 直接用 Tensor 实例调用数学操作方法;2. 使用 torch 库方法。如在进行加法之前,如果不初始化两个形状相同的 Tensor,则不能进行相加。
下面是初始化两个性状 2 × 3 的张量:
1 2 3 4 5 6 7 8 9 10
| a = torch.Tensor([[1, 2, 3], [4, 5, 6]]) b = torch.ones(2, 3) a
b
|
使用方法一相加:
第二种方法,使用 torch.add()
方法:
另外,如果数学操作函数带下划线 _
,返回值将覆盖对象:
Tensor 每个元素都加上一个标量:
1 2 3 4 5 6 7 8 9 10 11 12 13
| a = torch.rand(3) a
a + 2
torch.add(a, 2)
a.add(2)
|
abs()
方法:返回 Tensor 种每个元素的绝对值:
1 2 3 4
| torch.abs(torch.Tensor([[-5, -4, -3], [-3, -2, -1]]))
|
ceil()
方法:Tensor 每个元素向上取整:
1 2 3
| torch.ceil(torch.Tensor([0.2, 1.5, 3.4]))
|
exp()
方法:返回 Tensor 每个元素以 e 为底的指数:
1 2 3
| torch.exp(torch.Tensor([1, 2, 3]))
|
max()
方法:返回 Tensor 种所有元素的最大值:
1 2 3
| torch.max(torch.Tensor([[1, 2, 3], [4, 5, 6]]))
|
5. 线性代数运算
1 2 3 4 5
| a = torch.Tensor([1, 2, 3]) b = torch.Tensor([2, 3, 4]) torch.dot(a, b)
|
1 2 3 4 5 6 7 8
| a = torch.Tensor([[1, 2, 3], [2, 3, 4], [3, 4, 5]]) a b = torch.Tensor([1, 2, 3]) b torch.mv(a, b)
|
1 2 3 4 5 6 7 8 9 10
| a = torch.Tensor([[1, 2, 3], [2, 3, 4], [3, 4, 5]]) a b = torch.Tensor([[2, 3, 4], [3, 4, 5], [4, 5, 6]]) b torch.mm(a, b)
|
其他的常用线性代数操作:

6. 连接和切片
torch.cat()
可以将多个 Tensor 沿某维度进行连接。cat()
函数的两个参数:①需要进行连接的所有 Tensor 组成的元组;②连接的维度。
如让 a 和 b 在第一个维度进行连接,第二个参数为 0:
1 2 3 4 5 6 7 8 9 10 11
| a = torch.rand(2, 2) a b = torch.rand(2, 2) b torch.cat((a, b), 0)
|
若 a 和 b 在第二个维度相连,第二个参数为 1:
1 2 3 4 5
| torch.cat((a, b), 1)
|
torch.chunk()
可以将 Tensor 沿某维度进行切片,chunk()
函数需要传入的 3 个参数:①被切片的 Tensor 对象;②切分的块数;③切分的维度。
先把张量 c 按第二个维度切分为两块:
1 2 3 4 5 6 7 8 9 10 11 12 13
| c = torch.rand(2, 4) c
torch.chunk(c, 2, 1)
|
torch.t()
函数求转置矩阵,该函数只适用于二维 Tensor,也就是矩阵:
1 2 3 4 5 6 7 8 9 10 11 12
| a = torch.rand(2, 2) a
torch.t(a)
|
其他常见的连接切片操作:

7. 变形
view()
函数可以改变 Tensor 的形状,当想要高维的 Tensor 转化为一维的 Tensor,就是使用 view()
函数。
1 2 3 4 5
| x = torch.rand(2, 3, 4) x.size()
|
使用 view()
函数把该 Tensor 转换为 2 × 12 的 Tensor,总元素数目保持不变:
1 2 3 4 5
| y = x.view(2, 12) y.size()
|
若使用 -1 为 view()
函数的参数,代表该维度数目自动计算。若想要设置第二位为 1,第一维自动计算:
1 2 3 4 5
| z = x.view(-1, 1) z.size()
|
8. CUDA 加速
使用 cuda()
函数可以让接下来的任何运算都调用 GPU 进行加速计算。
Autograd
1. 基本原理
Autograd 就是自动微分,PyTorch 可以帮我们进行自动微分。
Tensor 在自动微分方面有 3 个重要属性:requires_grad
、grad
和 grad_fn
。
required_grad
属性是布尔值,默认为 False。若为 True,表示该 Tensor 需要自动微分。
grad
属性用于存储 Tensor 的微分值。
grad_fn
用于存储 Tensor 的微分函数。
当叶子节点的 requires_grad
为 True 时,信息流经过该节点时,所有中间节点的 requires_grad
属性都会变成 True,只需要在输出节点调用反向传播函数 backward()
,PyTorch 就会自动求出叶子节点的为分支并更新存储在叶子节点的 grad 属性中。只有叶子节点的 grad 属性能被更新。

2. 前向传播
Autograd 技术可以帮助我们从叶子节点开始追踪信息流,记下整个过程使用的函数,直到输出节点,这个过长被称为前向传播。
先初始化叶子节点 x:
1 2 3 4 5
| x = torch.ones(2) x.requires_grad
|
默认 requires_grad 为 False。如果需要让 PyTorch 自动帮我们进行微分计算,需要把 x 的 requires_grad 设置为 True:
1 2 3 4 5
| x.requires_grad = True x
|
设置完成后,x 的 grad 和 grad_fn 属性为空值:
让 x × 4 得到 z:
grad_fn
是微分函数,这里是乘法的反向函数。最后用 norm()
函数求 z 的长度:
y 的 grad_fn 是 norm()
的反向函数。
3. 反向传播
使用 backward()
函数对整个图进行反向传播,求出微分值:
运行完后 x 的 grad 属性更新为 x 的微分值,而 z 和 y 的 grad 值并没有变,因为他们都不是叶子节点。
4. 非标量输出
如果输出节点不是标量,使用 backward()
函数需要增加一个参数 geradient。gradient 的形状应该与输出节点的形状保持一致且元素值均为 1。
1 2 3 4 5 6 7 8 9 10
| z = torch.ones(2, 1) X = torch.Tensor([[2, 3], [1, 2]]) X.requires_grad=True
y = X.mm(z) y
|
若此时调用 y 的 backward()
函数,需传入一个形状与 y 形状一样且元素全为 1 的向量:
1 2 3 4 5 6
| y.backward(torch.ones(2, 1)) X.grad
|