D2DL笔记_3
线性代数部分:
因为张量是机器学习中最基本的计算单元,所以对于张量的计算是学习机器学习中不可或缺的。而张量是另一种意义上的矩阵,张量的计算理所当然地遵循线性代数的很多规范,所以线性代数的知识也尤为重要。
先从最基本的标量开始,给单个元素就是标量(与前面张量运算的部分一样):
可以通过torch.arange()生成一个数列,也可以叫列表list,可以通过索引来访问任一元素:
通过len()可以访问张量的长度:
可以shape看一下:
可见4是张量的长度,该张量只有一个轴,或是说只有一个维度。
通过指定行m和列n两个分量,可以创建一个形状为m x n的矩阵:
矩阵的转置(行变成列,列变成行):
可以通过A == A.T的输出判断矩阵A是否为对称矩阵(symmetric matrix):
相同形状的张量,任何按元素二元运算的结果,都必然是相同形状的张量:
补充:.clone()是深拷贝,这样A和B除了值相同之外没有任何关系,如果直接A = B,那么A和B其实只是指向同一内存空间的两个名称不同的变量罢了:
两个矩阵直接*,也就是按元素做乘法,称为哈达玛积(数学里面矩阵之间常做内积而不是元素按位积):
如果是标量和多维张量之间做二元运算,其实是把标量与张量中的每一个元素做相同的二元运算,这里其实是广播机制在作用,标量被视作单行单列的矩阵和张量作运算:
对张量中的所有元素进行求和:
如果是第一个轴长为2(除去行和列的第三维)的张量做sum:
A.sum(axis=0),在第0轴层面上求和:
也就是说,在第0轴上以加和的方式合并张量中的各个部分,可见A.sum(axis=0)的操作把张量进深这个维度合并掉了,而保留了行和列这两个轴,与之前的dim不一样。
分别对axis1和axis2进行尝试可以发现:
Axis1:保留了进深2,和列4,对每个矩阵的行分别进行了加和合并(所有行合成一行);
Axis2:保留了进深2和行3,对每一列分别进行了合并,也可以理解为压缩或是拍扁。
由于合并了size(2, 3, 4)中的4,size变成了(2, 3),所以最后的tensor看起来是一个二行三列的矩阵,但它其实是一个由两个三行一列的矩阵构成的张量。
也就是说,和dim的0,1,2分别对应行,列,进深不同,轴axis的0,1,2分别对应进深,行,列。另一个方面是,在axis上运算是会丢掉当前维度的,甚至将不同行的元素放在了同一行的各个列上,被丢掉的列得到了保持,而行这个维度却没了,后面会说不丢维度进行合并的方法。
所以,axis可以理解为是张量shape的索引。
也可以让张量在多个维度同时进行合并:
A.mean()可以求张量元素的平均值,和A.sum() / A.numel()等价:
(需要说明的是,mean函数不能求整形数据,需要把数据类型转换成浮点数再算均值)
当然也可以对轴求均值:
这俩表示形式也是等价的:
在axis上合并运算时,保持维度(轴数)不变的办法:
可以很明显地看到原本导致维度出现错误的问题由于keepdims=True得到了解决。其实本身在axis上操作的话,会把给定的axis从shape中去掉,而keepdims=True保证了给定的axis不被去掉,而是把shape的那个维度固定为1。
这么做的目的是为了利用广播机制进行进一步操作,因为keepdims可以通过将shape的维度固定为1从而保证出现单列矩阵:
A.cumsum(axis=*):计算第*个轴的累加和:
说完了tensor的哈达玛积,来看看矩阵之间的乘法本该是啥样的:
向量的点积:可以通过torch.dot(a, b)来实现:
由于torch.dot()只能算一维张量(向量)的点积,所以它和先做元素乘法再求和的办法等价:
矩阵向量积:通过mv计算,也就是matrix-vector multiplication:
矩阵内积:通过mm计算,也就是matrix-matrix multiplication:
在张量计算中,除了哈达玛积之外,还有一种乘法也是数学上很少用的,叫做克罗内克积,它在多模态融合和自动控制的相关算法中比较常用,可以通过调用特定的包来实现。
机器学习中,张量计算常用于特征的提取和融合,另一个用途就是计算损失函数,最基础的损失函数通常都包含范数(norm),以下是简要的范数相关内容。
范数(norm):
向量中一般用L_2(2是下标)范数,是向量元素平方和的平方根:
L_1范数:是向量元素的绝对值之和:
矩阵范数,最常用F范数(Frobenius norm):是矩阵元素平方和的平方根: