定义
设有
m×n
m
×
n
的矩阵
A
A
,那么SVD就是要将
A
A
分解为3个矩阵的乘积:
其中, U U 和 V V 都是正交矩阵,在复数域的话就是酉矩阵,即
Σ Σ 是非负实对角矩阵。
求解
U U 和 V V 的列分别叫做 A A 的左奇异向量(left-singular vectors)和 右奇异向量(right-singular vectors), Σ Σ 的对角线上的值叫做 A A 的奇异值(singular values)。
其实整个求解SVD的过程就是求解这3个矩阵的过程,而求解这3个矩阵的过程就是求解特征值和特征向量的过程,问题就在于求谁的特征值和特征向量。
- U U 的列由 AAT A A T 的单位化过的特征向量构成
- V V 的列由 ATA A T A 的单位化过的特征向量构成
- Σ Σ 的对角元素来源于 AAT A A T 或 ATA A T A 的特征值的平方根,并且是按从大到小的顺序排列的
知道了这些,那么求解 SVD 的步骤就显而易见了:
- 求 AAT A A T 的特征值和特征向量,用单位化的特征向量构成 U U
- 求 ATA A T A 的特征值和特征向量,用单位化的特征向量构成 V V
- 将 AAT A A T 或者 ATA A T A 的特征值求平方根,然后构成 Σ Σ
Python 中可以使用 numpy 包的 linalg.svd() 来求解 SVD。
部分奇异值分解
奇异值在矩阵
Σ
Σ
中也是从大到小排列,而且减少特别的快,在很多情况下,前
10%
10
%
甚至
1%
1
%
的奇异值的和就占了全部的奇异值之和的
99%
99
%
以上了。也就是说,我们也可以用前
r
r
大的奇异值来近似描述矩阵:
其中 r≪m,r≪n r ≪ m , r ≪ n
潜在语义索引(Latent Semantic Indexing)
之前吴军老师在矩阵计算与文本处理中的分类问题中谈到:
“三个矩阵有非常清楚的物理含义。第一个矩阵X中的每一行表示意思相关的一类词,其中的每个非零元素表示这类词中每个词的重要性(或者说相关性),数值越大越相关。最后一个矩阵Y中的每一列表示同一主题一类文章,其中每个元素表示这类文章中每篇文章的相关性。中间的矩阵则表示类词和文章雷之间的相关性。因此,我们只要对关联矩阵A进行一次奇异值分解,w 我们就可以同时完成了近义词分类和文章的分类。(同时得到每类文章和每类词的相关性)。”
上面这段话可能不太容易理解,不过这就是LSI的精髓内容。下面的例子来自LSA tutorial:
这就是一个矩阵,不过不太一样的是,这里的一行表示一个词在哪些title中出现了(一行就是之前说的一维feature),一列表示一个title中有哪些词,(这个矩阵其实是我们之前说的那种一行是一个sample的形式的一种转置,这个会使得我们的左右奇异向量的意义产生变化,但是不会影响我们计算的过程)。比如说T1这个title中就有guide、investing、market、stock四个词,各出现了一次,我们将这个矩阵进行SVD,得到下面的矩阵:
左奇异向量表示词的一些特性,右奇异向量表示文档的一些特性,中间的奇异值矩阵表示左奇异向量的一行与右奇异向量的一列的重要程序,数字越大越重要。
继续看这个矩阵还可以发现一些有意思的东西,首先,左奇异向量的第一列表示每一个词的出现频繁程度,虽然不是线性的,但是可以认为是一个大概的描述,比如book是0.15对应文档中出现的2次,investing是0.74对应了文档中出现了9次,rich是0.36对应文档中出现了3次;
其次,右奇异向量中一的第一行表示每一篇文档中的出现词的个数的近似,比如说,T6是0.49,出现了5个词,T2是0.22,出现了2个词。
然后我们反过头来看,我们可以将左奇异向量和右奇异向量都取后2维(之前是3维的矩阵),投影到一个平面上,可以得到:
在图上,每一个红色的点,都表示一个词,每一个蓝色的点,都表示一篇文档,这样我们可以对这些词和文档进行聚类,比如说stock 和 market可以放在一类,因为他们老是出现在一起,real和estate可以放在一类,dads,guide这种词就看起来有点孤立了,我们就不对他们进行合并了。按这样聚类出现的效果,可以提取文档集合中的近义词,这样当用户检索文档的时候,是用语义级别(近义词集合)去检索了,而不是之前的词的级别。这样一减少我们的检索、存储量,因为这样压缩的文档集合和PCA是异曲同工的,二可以提高我们的用户体验,用户输入一个词,我们可以在这个词的近义词的集合中去找,这是传统的索引无法做到的。