Press "Enter" to skip to content

线性代数及其应用——嵌入向量

走过路过不要错过:

 

在深度学习广泛应用于自然语言处理和推荐系统的今天,各位会经常听说“嵌入向量”(Embedding Vector)。对于每一个实体(Item)—— 物品、人、词等等,给它分配一个相对低维的向量(几十或几百维),这个向量叫做嵌入向量,为什幺叫“嵌入”,后文会明了。嵌入向量是物品的一种表示(Representation),或者也可以看作是从物品中提取出来的一套特征。自然语言问题的样本(句子,文章)是一堆词(或者 n-gram 之类 Token),推荐系统的样本往往包含“人+物品”。样本中的词、人、物等实体都先被转化成嵌入向量,再送交给网络的后续部分。

 

在处理这类问题的深度神经网络中,在网络的前部会先有一个“嵌入层”。最表面化地看待嵌入层:它根据实体的 id 在一个大的嵌入向量表中检索出该实体的嵌入向量,输出给后续网络。训练时,嵌入向量表中的全体嵌入向量一并在反向传播+梯度下降过程中受到调整。训练完成后,所有物品的嵌入向量和整个网络的其他参数一样都固定下来。

 

嵌入向量只是网络参数的一部分,训练完成后它们和网络其他参数一起构成了整个网络的“血肉”。当然,网络是针对某一个具体问题而训练的,比如分类,比如“人”喜不喜欢这个“物”,这其实是一个二分类问题。序列生成(比如翻译、自动回答)其实是一连串分类问题,也就是语言模型——选择下一个词。

 

针对不同的问题,嵌入层后连接不同结构的网络,计算并优化不同的损失(Loss)。那幺嵌入向量当然也是朝着有利于这个具体问题的方向而被训练的。但是如果网络比较庞大,比较深,嵌入层就只是位于大网络的初始部分。可以认为网络的后部更多地承担了应对具体问题的责任,而嵌入层(嵌入向量)与为之训练的具体问题还隔得较远,更多地承担了比较通用的实体表示,特征提取的功能。特别是如果使用非监督式学习,网络学习的不是某个具体的分类/回归任务,而是样本实体本身之间的关系(比如词与词之间的关系)。那幺学得的嵌入向量就更加与具体问题无关只关乎于现实中这些实体本身的某种性质和关系。

 

这样训练而得的实体嵌入向量,可以保存下来服务于其他任务。比如面对某个具体分类问题时,可以把之前非监督地,或者对某个大的通用问题训练得到的嵌入向量直接拿来作为实体的表示输入给(传统)模型或网络。如果把嵌入层视作网络的前部,这其实就是迁移学习。

 

这种实体的表示向量为什幺叫“嵌入”?这种方法为什幺 work ?嵌入向量具体如何训练,也就是如何计算损失对嵌入向量的梯度,这就是本文要从数学角度说明的问题。

 

我们先从向量说起。最浅显来讲,向量是有顺序的一组数,写成这样的形式:

 

这组数中的每一个称作该项量的分量, 是 的第一分量, 是 的第一分量 …… 有 个分量, 就是 维向量。但是这“一列数”并不是向量的本质。它也只是这个向量的一个表示。向量(Vector)本是一个抽象概念,它存在与同样抽象的向量空间(Vector Space)中。向量空间是向量的集合(可以有穷,可以无穷,甚至不不可列)记做: ,我们用小写粗体字母表示向量,用花体字母表示向量空间。顺便提一嘴,我们用小写斜体字母表示标量(数),用大写粗体字母表示矩阵。

 

向量空间中的两个向量之间可以进行加法。我们用 表示这种向量加法。加法必须满足下面几条性质:

 

 

    1. 交换律: ;

 

    1. 结合律: ;

 

    1. 存在“零向量” ,满足: ;

 

    1. 对于每个向量 存在“反向量” ,满足: 。

 

 

仅根据这几条性质,容易证明零向量以及每个向量的反响量都是唯一的。 可以简单记为 。向量“减法”就是加上反向量。数和向量之间可以进行乘法(数乘)。数乘必须满足:

 

 

    1. 结合律: ;

 

    1. 数乘对向量加法的分配率: ;

 

    1. 数乘对数加法的分配率: ;

 

    1. 数 乘任何向量都等于该项量本身: 。

 

 

用这几条性质可以证明数 0 乘任何向量都等于零向量 (粗体,表示向量)。因为: ,等号两边都加上 的反向量,就得到: 。定义了满足上述八条要求的加法和数乘的向量集合就是向量空间。如果一个向量 满足:

 

 

则称向量 可以被这组向量 线性表出。注意我们把系数的序号放在下标而不是上标,这在今后学习张量时有它的意义。现在可以不管,不论上标下标,就看做是序号即可。如果一组向量可以线性表出零向量:

 

 

如果满足上式的一组系数 就只能全都为 0 ,非如此就不可能用这组向量线性表出零向量,则称这组向量是线性独立的(Linear Independent)。否则,即如果可以找到一组非零的系数,用这组向量线性表出零向量,则称这组向量是线性相关的(Linear Dependent)。

 

如果一组线性独立的向量 能够线性表出向量空间中的所有向量,则称这组向量为该向量空间的一组基(Basis),基中的向量成为基向量(Basis Vector)。这组向量的个数 称作该向量空间的维数。这时候我们要问,如果有另一组能够线性表出所有向量且线性独立的向量,但是这另一组向量的向量个数是 ,那幺向量空间的维数就不是良好定义的了,是 还是 还是又一组满足基的条件的向量组的个数?这个结论我们不在此证明,只陈述出来:所有线性独立且能线性表出向量空间中所有向量的向量组(基),其向量个数都是一致的,都是该空间的维数。

 

选定一组基 。任意向量 被这组基线性表出时候的系数 是唯一的。因为假如存在另一组系数 ,则有:

 

 

因为基 是线性独立的,现在它们线性表出了零向量,那只可能那些系数都是 0 ,即 。所以,任意向量被特定一组基线性表出时候的一组系数是唯一的。这组洗漱成为这个向量在这组基上的坐标(Coordinate)。在 维向量空间中,我们可以用坐标表示一个向量。坐标就是一组 个数,而且有顺序,因为它们是向量在每个基向量身上的系数。一组基中基向量的顺序就决定坐标这组数的顺序。比如:

 

 

这就是本文一开始的那个:“向量是一组有序数”的含义。但是向量 并不“固”在这一组坐标上。选择另外一组基, 的坐标就变了。 是固定的,它的坐标随基不同而变。

 

现在我们来谈线性变换(Linear Transform)。有两个向量空间 和 ,维数分别是 和 。一个线性变换 将 中的向量映射到 中的向量,比如: ,而且要满足:

 

 

这就是对线性变换的“线性”性要求。形象来说就是变换 可以“刺穿”数乘与加法。线性变化从一个向量空间到另一个向量空间的映射,看上去好像很自由。但是“线性”性让它没那幺自由了。选定一组基 ,线性变换 在这组基上的表现就决定了它在所有向量上的表现。因为对于任意向量 ,有:

 

 

将每一个基向量 映射成什幺,就决定了它将任意向量 映射成什幺。 是 维(目标)向量空间 中的向量。给 选定一组基 ,我们问 在这组基上的坐标是什幺呢?我们先看对于 的每一个基向量 , 也都是 中的向量。它们在选定的那组 的基上的坐标如果是:

 

 

我们用 表示这个坐标。因为是 的坐标,下标先加一个 ,又因为是在第 个基向量上的系数,下标再加一个 ,所以 就有了双重下标 。现在看:

 

 

上式表明, 在 空间的基 上的坐标是 。这告诉了我们如何用 的坐标计算它在线性变换 下的“像” 的坐标(前提是在两个向量空间中选定各自的基)。现在我们把 列成一个“阵列”:

 

 

这是一个 行 列的矩阵(Matrix)。它的第 行第 列元素是元空间 的第 个基向量 的像 在目标空间 的第 个基向量 上的坐标 。线性变换 的所有行为都蕴含在矩阵 中。矩阵 是线性变换 在这两组基下的“表示”,正如“一列有序数”是向量在一组基下的表示一样。

 

于是我们可以定义矩阵与向量的乘法。我们令表示线性变换的矩阵乘以某向量(的表示)等于该项量在目标空间上的“像”(的表示):

 

 

结论:(一列有序数的)向量是向量在一组特定基上的坐标(表示),矩阵是一个线性变换在两组特定基上的表示。我们回顾了基础线性代数知识,现在让我们回到嵌入向量的话题上来。

 

一下我们不再区分抽象的向量和“一列有序数”的向量,统称为向量。在你的问题中,有许多实体(词、人、物/商品),比如 10000 个。有什幺好办法把它们表示为向量幺?最开始你能找到的最好的办法就是 One-Hot 编码。将 10000 个实体排个序,然后用 10000 维向量表示每一个实体。比如第 号实体,表示它的向量只有第 个分量是 1 ,其余分量都是 0 :

 

 

只有一个分量“热”,其余分量都“凉”,这就是“独热”—— One-Hot 。因为我们最开始时不想假设物品与物品之间有任何关系。对,你知道“国王-女王与男-女”,但是你不可能手工(Handcraft)给 10000 种实体都人肉分配相互之间距离和角度都合适的向量。一开始,我们要求表示 10000 个实体的向量中两两之间一律有同样的距离和角度关系,那幺只有在 10000 维空间中,为每一个物品分配一个坐标轴上的单位向量,这正是 One-Hot 编码。

 

用 One-Hot 编码了向量,接下来就要把它送给模型了。我们头一件需要做的事就是降低维度,10000 维太高了。最简单的降低维度的方法就是用一个线性变换,将 10000 维的 One-Hot 向量映射到一个低维空间,比如100 维。把这个线性映射当做我们的网络的最头部的部分,接着再把得到的低维(100 维)向量输入给后面的其他组件。这样的线性变换就是:

 

 

就是表示这个线性变换的矩阵,它的形状是 。 是 10000 维 One-Hot 向量,表示一个实体。 是变换得到的 100 维向量,是网络后续部分的输入。以下我们省略形状下标。根据矩阵与向量的乘法, 的第 分量是:

 

 

是 的第 行第 列元素。 是 的第 分量。而 是 One-Hot 向量,对于第 号实体来说,只有 是 1 ,其余分量都是 0 ,于是:

 

 

这说明 是 的第 个 列 。也就是说,对第 号物品(的 One-Hot 向量)做线性变换,等价于取出该线性变换的矩阵的第 个列。而这个列就是第 号实体的“嵌入向量”(Embedding Vector),因为它把物品的高维表示(One-Hot)嵌入到了低维空间。这个线性变换就是“嵌入层”,它本质上就是线性变换层。这个线性变换的表示矩阵称作嵌入矩阵。它的所有元素也属于模型参数,在反向传播+梯度下降过程中一并训练。训练完成后,我们就得到了所有实体的嵌入向量(线性变换矩阵的所有列)。

 

回顾那个 从 1 加到 10000 的加式,那其中大部分是“乘 0 再累加”,加了个寂寞。但是 CPU/GPU 不管你乘的是零还是不是零,碳排放是一样的。于是,当输入向量是 One-Hot 时,可以这样实现嵌入层,就用物品的编号取索引矩阵的对应列就可以了。如果嵌入矩阵在存储中是按列存的,那幺一个寻址就过去了。而损失函数对嵌入矩阵各分量的偏导数的计算,本质上与损失函数对线性变换的矩阵的元素的计算一样。

Be First to Comment

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注