在研究NLP的过程中,遇到了word embedding, 经过一系列学习,发现它最初的原理之一来自奇异值分解。于是对奇异值分解做一个简单的记录。
资料中比较好的资料:
https://www.cnblogs.com/endlesscoding/p/10033527.html 原理讲解简单,demo做的十分好!
https://www.cnblogs.com/litaotao-doctor/p/5320521.html 这篇把特征值和奇异值放在一起讲,十分到位。
看完上面的资料后,我觉得自己没必要记录公式原理了,自惭形秽。好,下面开始:
SVD: Sigular Value Decomposition
个人认为奇异值和特征值应该可以有相同的理解,这里我们先谈特征值:
特征值的定义为对矩阵A存在特征值 λ,特征向量x,使下式成立:
而对A的所有特征值,我们称为A的谱,记为λ(A)。
那么我们该如何理解这个式子?
有几个相关的关系可以给我们参考:矩阵A的秩不小于A的非零特征值数;如果矩阵A不满秩,则一定存在0特征值;若矩阵A可对角化,则rankA = A的非零特征值数。
也就是说 矩阵的特征值与矩阵的线性相关性是有关系的。
则我们对特征值的理解可以为:
任意矩阵A对向量x的矩阵乘法,可以理解为对x向量的表换(旋转、平移、缩放),那么Ax可以理解为一次表换,而特征值λ与x的相乘,表示了拉伸操作。也就是说:
对矩阵A的表换操作,存在一个向量在表换后向量的方向不变。
而从特征值分解的角度上看,所有可对角化矩阵都可以被其特征值及特征向量所表征。因为我们知道,可对角化矩阵存在:
的关系,所以我们可以通过对角化矩阵(特征值构成的对角矩阵)表征A,这个性质的证明可以考虑:
对两边做矩阵乘法会发现是相等的,必要性证明可以去百科看。
那么我们对特征值的理解又可以表示成:
可对角化矩阵可由其特征向量及特征值表征。
而表征的过程中,我们可以将特征值向量理解为一个线性子空间,其中特征值标记了每个特征向量的重要程度。
这样一来,我们可以将特征向量想象成一堆基向量,而矩阵恰好可以通过基向量进行表征;而对于对称矩阵,这些基向量为正交基向量。
所以特征值是一种可以让我们对方阵拆分表征的工具。
一旦清晰了这个概念,我们来看SVD的表达式,结合实际中情况,就能轻松看出门道。
对于现实中的情况,我们往往遇不到方针,所以对MxN的矩阵M来说,奇异值分解为,一定能找到左奇异方阵U和右奇异方阵V,使下式成立:
其中
为MxN的半正定对角矩阵。且U和V必须为酉矩阵,即幺正矩阵,厄米共轭矩阵,其实就是复数域上的正交矩阵;
即对U、V存在
而在实数域上,这样的矩阵我们成为正交矩阵,即矩阵由n个正交基组成,在行列上都为n个正交的矩阵。
酉矩阵把这个概念扩展到了复数域。则我们在复数域上拿到了两组正交基。
那同特征值表示矩阵一样,奇异值分解也是通过不同内积空间的变换表征了任意矩阵M。
到此,奇异值的分解原理可以解释了,但可能会有些问题,比如
是不是有点太狠了,如果它是阶对角矩阵,就说明U上的正交基中某些维度的值在计算过程中变为0被舍弃了。其实不然,我们要关心的是矩阵M的秩,因为rankM <= min(M, N),所以奇异值分解能最大的保留M的特征。
而我们最理想的情况,就是使用k<=rankM个非零奇异值,完全表征矩阵M。
Word embedding 中的SVD
这也引入了我们在使用奇异值分解时的思路:
这是原来的奇异值分解的各个矩阵,
这是实际使用时的矩阵,可以看到,实际使用时,我们并没有保证U和V矩阵的维度大于等于A的秩,这是因为,往往M和N都是非常大的值,如在word embedding中,我们一开始对每个词进行特征表征会先统计一个co-occurance矩阵,标记了n-gram设定中,任意两个词同时出现的次数,即一个VxV的方阵,其中V表示词典大小:
而因为V常常是百万级以上的大小,就会导致这个表格我们无法在计算中使用,所以将这个VxV的矩阵,定义为奇异值分解中的U矩阵,而定义embedding维数为k,即每个词用k维的vector表示,利用一个mini版的奇异值分解模型,我们可以得到一个Vxk维的矩阵,我们称之为词嵌入矩阵,在运算的过程中,每个token就会经过这个矩阵转置为一个向量表示,大大减少了所需要的运算空间。
当然,如果k越大,或者说越接近于真实Vxk维矩阵的非零奇异值数,我们得到的词嵌入就越好,表现能力也越强,当然往往我们做不到,所以我们只需要保证,较大的奇异值被我们留下来就能很好的表征词嵌入了。
这就是SVD在词嵌入中的应用,当然,随着后来技术的发展,有了skip-gram,glove,output embedding等模型对词嵌入有了更好的提升;我个人认为这些提升都在于找到更好的奇异值进行表征(但描述的问题变了,比如引进了context的模型进行表征)。为什么这么说的呢,因为在Breaking the softmax bottleneck: A high-rank RNN language model中提到了一个问题,就是使用softmax函数做最后结果的输出,迫使词嵌入维度要大于其构建的一个context矩阵的秩;所以从这点可以看到这些问题都有着十分紧密的相似性!
来源:CSDN
作者:SaoYear
链接:https://blog.csdn.net/qq_35509823/article/details/104577734