我一直在使用英特尔MKL的SVD(dgesvd
通过SciPy的),并注意到,当我改变之间的精确结果是显著不同float32
而float64
当我的基质被严重空调/没有满秩。我应该添加一些关于最小化正则化的指南,以使结果对float32
-> float64
变化不敏感吗?
特别是 , 我看到 规范 当我在float32
和之间更改精度时,会移动约1 float64
。 规范 是 在784个总数中,约有200个零特征值。
在做SVD 与 使差异消失了。
我一直在使用英特尔MKL的SVD(dgesvd
通过SciPy的),并注意到,当我改变之间的精确结果是显著不同float32
而float64
当我的基质被严重空调/没有满秩。我应该添加一些关于最小化正则化的指南,以使结果对float32
-> float64
变化不敏感吗?
特别是 , 我看到 规范 当我在float32
和之间更改精度时,会移动约1 float64
。 规范 是 在784个总数中,约有200个零特征值。
在做SVD 与 使差异消失了。
Answers:
尽管这个问题有很好的答案,但是对于小奇异值(带有图解),这是一条经验法则。
如果奇异值非零但非常小,则应将其倒数定义为零,因为其表观值可能是舍入误差的产物,而不是有意义的数字。一个合理的答案是“小有多小?” 是以这种方式编辑所有与最大比率小于的奇异值 乘以机器精度 。
补充:以下几行计算了此经验法则。
#!/usr/bin/env python2
from __future__ import division
import numpy as np
from scipy.sparse.linalg import svds # sparse, dense or LinOp
#...............................................................................
def howsmall( A, singmax=None ):
""" singular values < N float_eps sing_max may be iffy, questionable
"How small is small ?"
[Numerical Recipes p. 795](http://apps.nrbook.com/empanel/index.html?pg=795)
"""
# print "%d singular values are small, iffy" % (sing < howsmall(A)).sum()
# small |eigenvalues| too ?
if singmax is None:
singmax = svds( A, 1, return_singular_vectors=False )[0] # v0=random
return max( A.shape ) * np.finfo( A.dtype ).eps * singmax
在这里,希尔伯特矩阵的尾数中的低位被置零
A.astype(np.float__).astype(np.float64)
,然后np.linalg.svd
在中运行float64
。(svd
所有结果float32
大致相同。)
简单地将其截断float32
甚至可能对去噪高维数据(例如,训练/测试分类)有用。
真正的测试用例将是受欢迎的。
对称矩阵的奇异值分解 是一个且与其规范本征分解相同(即具有正交特征向量矩阵),而对于非对称矩阵则是相同的 只是对称矩阵的规范特征值分解
答案是令人惊讶的。让 很小,并考虑两个矩阵
现在,将这种见解以有限的精度应用于SVD,让我们写 作为您的float64
精度矩阵,并且
与相同矩阵的float32
精度相同。如果我们假设SVD本身是精确的,则奇异值
必须相差不超过一个小的常数因子 ,但奇异向量 和
可以相差很大。因此,如图所示,在奇异矢量的意义上,没有办法使SVD“稳定”。