3.7 插曲:一点点线性代数的知识
如果你对数学感到头疼,请略过这个插曲。但是,将来你会发现,深度学习高度依赖于这种数学。对这种数学的理解越深刻,你越能理解深度学习的本质。在下面的表述中,我会用相当精确严肃的数学语言来介绍。因为数学本身的定义是严谨的,不能随便引申其内涵或者联想。所以我在本课程中凡是涉及数学的部分,都力求严谨。
到现在为止,我们用到了一个很有用的数学知识:向量的点积。在之前的表达中,我们在代码中用了Python中的 list 来表示向量,实际上应该是纯粹数字的 list 才具有向量的含义。那么什么是向量呢?
向量是线性空间中的一个点。
什么是线性空间?
线性空间是由一组互相正交归一的基展开的空间。
3.7.1 代数表示
这是一个很抽象的概念。我们来举个例子来说明一下线性空间的概念。实际上,这个概念很简单。考虑在我们熟悉的三维空间,我们用x,y,z三个互相垂直的轴来表示这样的三维空间,实际上,这三个轴还标记了方向和原点。我们用三个有方向的单位长度的线段来表示这三个轴,我们可以标记为:。这样,在这个三维空间中的任何一个点p,我们都可以表示为:
其中 为p这个点在x轴,y轴,z轴上的投影(作垂线得到的垂足的刻度值)。正是因为三维空间中的任意一个点都可以这么表示出来,所以我们说 就是三维空间(欧几里得空间)的基准矢量,简称基矢。这个三维空间就是一个线性空间,因为三个基矢 两两之间互相垂直,且长度为1。
这是我们通常用的表示三维线性空间的方法,这实际上是向量的一种表示。但是,上面的表示虽然人类比较容易理解,但计算机无法理解,这是一种符号标记系统,而不是数值表示。为了使用数值表示,我们需要引入新的标记方法:矩阵表示。
3.7.2 矩阵表示
一个 矩阵的定义是m行n列的数值的矩形阵列,实际上,这也是矩阵这个词的由来。比如,一个()的矩阵可能看起来像这样
各种各样的矩阵中,有三种矩阵是比较特殊的,即行(hang)向量,列向量和方矩阵。行向量就是只有一行的矩阵,列向量是只有一列的矩阵,方矩阵则是具有相同的行数和列数的矩阵。
3.7.3 对偶表示
矩阵实际上是推广了的数,我们知道实数是用来标记实数轴上的点的。而行向量和列向量实际上就是标记线性空间中的点的。那么线性空间中的同一个点,就有两种矩阵表示,一种是行向量表示,一种是列向量表示。
比如,一个长为3,宽为2,高为4的长方体的一个顶角放在坐标轴原点,那么其对顶角究竟应该表达为行矩阵 还是应该表示为
呢?
实际上,这两种表示都是正确的。这取决于你怎么选择你的基矢,如果你选择基矢就是行向量,即定义:
那么在这个三维空间中的任何点,其表示都应该按照行向量表示。
如果我们选择基矢为列向量,即定义:
那么在这个三维空间中的任何点,其表示都应该按照列向量来表示。
这样原本我们只有一个三维空间,从矩阵定义上来看,我们就分成两个互为对偶的空间。关于“对偶”这个词,暂时可以不去理会。只需要知道它们其实描述的是同一个线性空间,但是用的分别是行和列向量表示。
实际上,这种对偶实际上是实数中互为倒数的一种推广。为了理解这一点,我们需要引入矩阵的乘法。
3.7.4 矩阵的乘法
为此,第一步我们需要引入()行矩阵A和()列矩阵B的乘法。
假定, , 注意这个列向量B的写法也是横着写,但是不同的是,在方括号上多了一个指标(T)。这个指标表示B实际上是个列矩阵,只不过列矩阵写在文字中间比较难看,我们用了这么一个标记符号来表示。它的英文是transpose,翻译成中文是转换位置,简称为 "转置"。
如果 , A 和 B 是无法相乘的。 也许你会想,我们只需要填上几个零,就可以让 A 和 B 的长度相同,不是可以同样做乘法了吗?但问题是,你不知道这些零应该填在什么地方,不同的地方填0得到的结果是不一样的,因而也就不是一个好的乘法规则。
考虑 的情形,此时矩阵的乘法定义如下:
这个乘法将行向量和列向量一起映射成了一个数。
举例: 给定, 求 AB 的值。
解:
现在将这个乘法推广到更一般的矩阵的情形。刚刚是把行向量和列向量映射到数的一个乘法,而现在则是考虑把两个矩阵映射到一个结果矩阵的乘法。
一般矩阵的乘法规则是:左边矩阵的第 行和右边矩阵的第 列 进行行列乘法,得到的结果矩阵的第 行,第 列的元素.
我们还是用例子来说明。
假如 A 是一个 (m,n) 矩阵,
而 B 是一个 (n,k) 矩阵
那么 是一个(m,k) 矩阵
C的元素 应该如下表示:
当然,矩阵还有别的更复杂的乘法,但我暂时不涉及到这些内容。
请思考一个问题:列向量A和行向量B相乘的结果是什么?这时需要A和B的元素个数是一样多的嘛?
3.7.5 插曲的尾声
矩阵的乘法是数的乘法的严格的推广,为什么我要强调矩阵的乘法呢?
在Python的数据处理技术中,很多人为了数据处理的方便,将数据随意地改变长度,添加0值,甚至Numpy包中就预留了一个叫作broadcast的操作,它可以隐式地自动改变长度和添加0值,这种做法是非常非常危险的,它可能会导致算法中的错误极难被发现。我对于这样的做法是极其反对的。因为一旦脱离了数学的严谨性,算法本身的牢固性就得不到保证了。请不要使用broadcast操作,即便它很方便。一切应回到矩阵本身允许的乘法来做。
网友评论