在机器学习中经常都会遇到特征值问题,例如 Laplacian Eigenmaps 或者一大堆的 KernelPCA 派的降维方法,或者谱聚类之类的。通常都是对于一个很大并且比较稀疏的矩阵,求最大或者最小的几个特征值以及对应的特征向量。在 Matlab 里,eig
函数可以用来求得一个矩阵的全部特征值和特征向量,然而,如果我们只需要其中最大或者最小的那几个,用 eig
来求就显得杀鸡用牛刀了,费力还不讨好。而且,eig
还不能处理稀疏矩阵的情况,所以,这个时候通常就需要 eigs
出场了。
eigs
可以只求矩阵的几个最小的或者最大的(或者最接近某一个数值的)特征值和对应的特征向量,并且能够处理稀疏矩阵(如果矩阵规模很大而且稀疏程度有很高的话,使用稀疏矩阵速度会快很多)。当然它使用的算法和 eig
不一样,是迭代的方式(具体的细节我也不是很清楚,记得数值分析课上讲过 power method ,不过也忘得精光了 -.-)。这也造成了一个小缺点,就是当矩阵是 singular 或者 near-singular 的时候,如果求最小的几个特征值,就会有问题。例如下面这个极端的例子,我们造一个 rank 为 1 的矩阵:
Matlab 就会在这里出错。让人很痛苦,因为有时候会在数据中碰到矩阵 near-singular 的情况。一开始我找不到解决办法,因为 eig
是可以处理 singular 矩阵的,所以干脆在遇到 eigs
出错的时候转由eig
来计算,然后手工选出最小的几个特征值和特征向量。
不过这样子显然低效很多,特别是在矩阵维度是几千而需要的特征值特征向量就是几个的时候。当然,这个时候我可以这样子:
不过最后有一天我突然想到了其实这个问题似乎很简单。关于特征值和特征向量,是这个样子的:
如果矩阵 A 是 singular 的话,那么我加上一个单位矩阵 I 好了:
也就是说,加上一个单位阵再求特征值问题的话,得出来的特征向量和原来 A 的特征向量是一样的,对应的特征值也只是多了一个增量 1 而已。另一方面,加上了单位阵之后就不再 singular 了,所以 eigs 也可以用了。
ps: 当然,何时选用 eig
还是 eigs
还是要依赖于计算机性能、经验、心情等一些各种因素的,比如,其实 eig
算
100×100
的矩阵的全部特征值和特征向量还是非常迅速的——几乎是瞬间完成。
reflink:
http://blog.pluskid.org/?p=720