预备知识👀
约 1498 个字 79 行代码 预计阅读时间 6 分钟
数据操作👀
- N 维数组 (也称为 张量 | tensor) 是机器学习和神经网络的主要数据结构
- 张量在 PyTorch 中表示为一个由数值组成的数组,这个数组可能有多个维度。 具有一个轴的张量对应数学上的 向量 (vector); 具有两个轴的张量对应数学上的 矩阵 (matrix); 具有两个轴以上的张量没有特殊的数学名称。
Example
入门👀
首先导入 PyTorch。
创建👀
- 可以使用
arange
创建一个行向量x
(只有一维)。 - 张量中的每个值都称为张量的 元素(element)。例如,张量
x
中有 8 个元素。 - 除非额外指定,新的张量将存储在内存中,并基于 CPU 计算。
- 使用全 0 元素创建并初始化矩阵:
Code
- 使用全 1 元素创建并初始化矩阵:
x=torch.ones((2, 3, 4))
- 随机初始化矩阵:
x=torch.randn(3, 4)
(其中每个元素都从均值为0、标准差为1的标准高斯分布(正态分布)中随机采样。) - 还可以通过提供包含数值的Python列表(或嵌套列表),来为所需张量中的每个元素赋予确定值。
torch.tensor([[2, 1, 4, 3], [1, 2, 3, 4], [4, 3, 2, 1]])
- 在这里,最外层的列表对应于轴 0,内层的列表对应于轴 1。
属性👀
- 通过
shape
属性访问张量(沿每个轴的长度)的形状 。
- 通过
numel
函数可以得到张量中元素的总数,即形状的所有元素乘积。
- 要想改变一个张量的形状而不改变元素数量和元素值,可以调用
reshape
函数。 - 例如,可以把张量
x
从形状为(8, )
的行向量转换为形状为(2,4)
的矩阵。 - 这个新的张量包含与转换前相同的值,但是它被看成一个 2 行 4 列的矩阵。
Tip
- 不需要通过手动指定每个维度来改变形状。
- 即,如果我们的目标形状是(高度,宽度), 那么在知道宽度后,高度会被自动计算得出。
- 实践中可以通过
-1
来调用此自动计算出维度的功能。 即我们可以用x.reshape(-1,4)
或x.reshape(2,-1)
来取代x.reshape(2,4)
。
运算符👀
对于任意具有相同形状的张量,常见的标准算术运算符(+
、-
、*
、/
和 **
)都可以被升级为按元素运算。
Code
code
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 # **运算符是求幂运算
除了按元素计算,也可以执行线性代数运算,包括向量点积和矩阵乘法。
- 通过
cat
函数来连接张量,把它们端对端地叠起来形成一个更大的张量。 - 我们只需要提供张量列表,并给出沿哪个轴连结。
Code
code
X = torch.arange(12, dtype=torch.float32).reshape((3,4))
Y = torch.tensor([[2.0, 1, 4, 3], [1, 2, 3, 4], [4, 3, 2, 1]])
torch.cat((X, Y), dim=0), torch.cat((X, Y), dim=1)
- 也可以通过 逻辑运算符 构建新的二元张量。如
X == Y
,会创建大小相同的新张量,其中的每个元素都是 0(如果两个张量在相应位置相等)或 1(如果不等)。
Code
- 可以对张量中的所有元素进行求和,得到只有一个元素的张量。
广播机制👀
在某些情况下,即使形状不同,我们仍然可以通过调用 广播机制(broadcasting mechanism)来执行按元素操作。这种机制的工作方式如下:
- 通过适当复制元素来扩展一个或两个数组,以便在转换之后,两个张量具有相同的形状;
- 对生成的数组执行按元素操作。
在大多数情况下,我们将沿着数组中长度为1的轴进行广播,如下例子:
Code
a
和b
分别是 \(3\times 1\) 和 \(1\times 2\) 矩阵,如果让它们相加,它们的形状不匹配。- 我们将两个矩阵 广播 为一个更大的 \(3\times 2\) 矩阵,如上所示:矩阵
a
将复制列,矩阵b
将复制行,然后再按元素相加。
索引和切片👀
- 张量中的元素可以通过索引访问。
- 与任何 Python 数组一样:第一个元素的索引是 0,最后一个元素索引是 -1;
- 也可以指定范围 (前闭后开), 例如
[1:3]
表示第二和第三个元素 (从 0 开始)。
除了索引读取操作外,也可以通过指定索引来将元素写入矩阵。
- 如果我们想为多个元素赋值相同的值,我们只需要索引所有元素,然后为它们赋值。例如,
X[0:2, :] = 12
将为矩阵X
的前两行的所有列赋值为 12。
Code
节省内存👀
- 运算符和索引的结果都会分配新的内存来存储结果。
- 例如,如果我们写
Y = X + Y
,我们会将Y
指向新分配的内存。
- 并且在机器学习中,可能有数百兆的参数,并且在一秒内多次更新所有参数。通常情况下,我们希望原地执行这些更新。
- 而且如果不原地更新,其他引用仍然会指向旧的内存位置,这样我们的某些代码可能会无意中引用旧的参数;
id()
id()
函数返回对象的唯一标识符,给我们提供了内存中引用对象的确切地址
原地更新👀
可以使用切片表示法将操作的结果分配给先前分配的数组,例如 Y[:] = <expression>
。
数据预处理👀
线性代数👀
微积分👀
自动微分👀
概率👀
本文总阅读量:
次