深度学习基础框架 张量 Tensor
- 张量
- 数据操作
- 导入
- 创建张量
- 获取张量信息
- 改变张量
- 张量运算
- 张量与内存
张量
Pytorch 是一个深度学习框架,用于开发和训练神经网络模型。
而其核心数据结构,则是张量 Tensor,类似于 Numpy 数组,但是可以支持在 GPU 上加速运算,显著加速模型训练过程,更适用于深度学习和神经网络模型的构建和学习。
张量是多维数组的泛化,可以是:
- 标量(零维张量)
- 向量(一维张量)
- 矩阵(二维张量)
- 或更高维度的数组;
- e . g . e.g. e.g. RGB 图像可以表示为三维张量,其中一个维度表示高度,另一个维度表示宽度,最后一个维度表示颜色通道:
[[[255, 0, 0], [0, 255, 0], [0, 0, 255]],
[[0, 255, 255], [255, 255, 0], [255, 0, 255]]]
此外,后期读者会接触到梯度下降与反向传播,而张量非常重要一点,即可以自动求导,方便计算梯度并更新模型参数。
数据操作
导入
首先,导入 torch,需要注意的是,虽然称为 Pytorch,但是我们应该导入 torch 而不是 Pytorch;
import torch
创建张量
张量 tensor 表示一个数值组成的数组,
x = torch.arange(12)
print(x)
# >>> 表示结果输出
>>> tensor([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])
通过 zeros
函数与 ones
函数创建全0、全1元素,
torch.zeros((2, 3, 4))>>> tensor([[[0., 0., 0., 0.],[0., 0., 0., 0.],[0., 0., 0., 0.]],[[0., 0., 0., 0.],[0., 0., 0., 0.],[0., 0., 0., 0.]]])
张量同样支持逻辑运算符构建,
x = torch.tensor([[1, 2, 4, 8], [1, 3, 9, 27]])
y = torch.tensor([[2, 2, 2, 2], [3, 3, 3, 3]])
x == y>>> tensor([[False, True, False, False],[False, True, False, False]])
获取张量信息
通过 shape
属性来访问张量的形状和张量中元素的总数,
# 张量的形状
x.shape>>> torch.Size([12])
# 张量中元素的总数
x.numel()>>> 12
对张量中所有元素进行求和会产生一个只有一个元素的张量,
x = torch.tensor([[1, 2, 4, 8], [1, 3, 9, 27]])
x.sum()>>> tensor(55)
通过用切片方法访问张量内指定位置元素,
x = torch.tensor([[1, 2, 4, 8], [1, 3, 9, 27]])
x[-1], x[1][1:3]>>> (tensor([1, 3, 9, 27]), tensor([3, 9]))
改变张量
通过 reshape
函数改变一个张量的形状而不改变元素数量和元素值,
x.reshape(3, 4)>>> tensor([[ 0, 1, 2, 3],[ 4, 5, 6, 7],[ 8, 9, 10, 11]])
通过 cat
函数把多个张量连结在一起,支持按指定维度 dim
拼接,
x = torch.tensor([[1, 2, 4, 8], [1, 3, 9, 27]])
y = torch.tensor([[2, 2, 2, 2], [3, 3, 3, 3]])
torch.cat((x, y), dim=0), torch.cat((x, y), dim=1)>>> (tensor([[ 1, 2, 4, 8],[ 1, 3, 9, 27],[ 2, 2, 2, 2],[ 3, 3, 3, 3]]),tensor([[ 1, 2, 4, 8, 2, 2, 2, 2],[ 1, 3, 9, 27, 3, 3, 3, 3]]))
通过指定索引将元素写入张量,
x = torch.tensor([[1, 2, 4, 8], [1, 3, 9, 27]])
x[1, 2] = 1111>>> tensor([[1, 2, 4, 8],[1, 3, 1111, 27]])
x = torch.tensor([[1, 2, 4, 8], [1, 3, 9, 27]])
x[1, :] = 12>>> tensor([[ 1, 2, 4, 8],[12, 12, 12, 12]])
张量运算
张量支持按元素运算,
x = torch.tensor([1.0, 2, 4, 8])
y = torch.tensor([2, 2, 2, 2])
x + y, x - y, x * y, x / y, x ** y>>> (tensor([ 3., 4., 6., 10.]),tensor([-1., 0., 2., 6.]),tensor([ 2., 4., 8., 16.]),tensor([0.5000, 1.0000, 2.0000, 4.0000]),tensor([ 1., 4., 16., 64.]))
张量加法中,即使形状不同,我们仍然可以通过调用广播机制来执行张量加法,
a = torch.arange(3).reshape((3, 1))
b = torch.arange(2).reshape((1, 2))
a + b>>> tensor([[0, 1],[1, 2],[2, 3]])
张量与内存
虽然 Python 中很少涉及到内存处理,但是如果矩阵很大,就需要考虑到内存方面。
在运行一些操作时,可能会导致为新结果分配内存,
before = id(Y)
Y = Y + X
id(Y) == before>>> False # 说明新内存地址不等同于原内存地址
如果我们的矩阵 Y 非常大,为了效率考虑,不更换内存地址,减少操作的内存开销,怎么做?
before = id(Y)
Y += X
id(Y) == before>>> True # 说明没有新分配内存空间
Numpy 是 Python 里最基础的多元数组运算框架,所以也要多关注 Numpy 与 Tensor 之间的转化。