深度学习中需要大量对数据进行操作,本文以Pytorch框架为例,对常用的数据操作进行总结。
基本操作
深度学习中常使用张量(tensor)这一概念,张量最初起源于力学,用于表示弹性介质中各点应力状态,后来发展为力学和物理学的一个数学工具。它可以满足一切物理定于必须与坐标系的选择无关的特性,是矢量概念的推广。在理解时大致上可以直接将其对应为向量。零阶张量对应标量,一阶张量对应向量,二阶张量对应矩阵。
可以使用arrange创建行向量,张量默认存储在内存中,并采用基于CPU的计算。
x = torch.arrange(12)
可以采用shape来输出张量的形状。
1 |
|
调用reshape函数可以改变张量的形状
1 |
|
可以用zeros,ones,randn来初始化创建张量,分别表示张量的元素为全0,全1,随机从标准正态分布中取值。也可以通过python列表来为张量元素赋值。
1 |
|
运算符
张量之间可以进行算术运算,对于任一具有相同形状的张量,可以使用标准算术运算符升级为按元素运算。
1 |
|
还可以将两个或多个张量连结(concatenate)起来个构成一个更大的张量
1 |
|
此外,还可以对张量进行线性代数运算,包括向量点积和矩阵乘法。
点积
1 |
|
向量积与点积类似,区别在于(1)调用mv函数;(2)是矩阵乘向量,点积是向量乘向量。
1 |
|
矩阵乘法调用mm函数
1 |
|
范数
向量范数是将向量映射到标量的函数f,可以简单理解为向量的大小。特殊地,欧氏距离为$L_2$范数。$L_1$范数表示向量各元素的绝对值之和
1 |
|
矩阵范数的计算同理。
广播机制
上节介绍了相同形状的张量如何进行运算,本节介绍形状不同的张量的运算。可以通过广播机制(Broadcasting Mechanism)进行操作,首先通过复制元素使得两个张量具有相同的形状,其次对生成的数组执行按元素操作。
1 |
|
索引与切片
类似于Python语言的特性,张量中的元素可以通过索引访问,也可以通过切片访问,此处略过
节省内存
运行某些操作可能会使得程序在内存中为新结果分配内存。例如,用 Y = X + Y
,将不再引用Y指向的张量,而是引用新分配内存处的张量。当进行大量数据训练时,需要占用大量内存,此时应尽量避免不必要地分配内存,因此,我们希望原地执行这些更新。
为了达到原地操作的目的,可以使用切片表示法将操作的结果分配给先前分配的数组,例如Y[:] = <expression>
1 |
|
此时两次的Z的地址不变,说明为原地操作。如果后续计算中没有重复使用X,也可以使用X[:] = X + Y
或者X += Y
来减少内存操作的开销。
转换为其他Python对象
Pytorch定义的张量可以与numpy定义的张量进行相互转化。
1 |
|
自动微分
深度学习可以通过自动计算导数(自动微分)来加快求导。实际上,根据我们设计的模型,系统会构建一个计算图,来跟踪计算是哪些数据通过哪些操作组合起来产生输出。自动微分使系统能够对吼反向传播梯度。以$y = 2X^TX$关于列向量求导为例
1 |
|
使用自动微分的一个好处是即使计算图需要通过Python控制流,我们仍然可以计算得到的变量的梯度。
分离计算
例如,z是y和x的函数,y是x的函数,如果想计算z关于x的梯度而保持y为常数,可以采用分离y的方法,分离y后,会返回一个新变量,该变量具有与y相同的值,但会丢弃计算图中关于计算y的信息,即梯度不会流经u到x,可以用于计算偏导数。一句话总结即计算偏导数时需要将不求导的变量调用detach函数进行分离。
1 |
|
深度学习框架可以自动计算导数:我们首先将梯度附加到想要对其计算偏导数的变量上。然后我们记录目标值的计算,执行它的反向传播函数,并访问得到的梯度。