我正在阅读一本书,书名为“与Scikit一起动手机器学习-学习,Keras和Tensorflow”,作者解释了矩阵的伪逆(Moore-Penrose逆)是如何在线性回归的背景下计算的。我在这里逐字引用:
伪逆本身是用一种标准的矩阵分解技术(奇异值分解)来计算的,它可以将训练集矩阵X分解成三个矩阵U Σ VT的矩阵乘法(见numpy.linalg.svd())。伪逆计算为:X+ = V * Σ+ * UT.计算矩阵Σ
E 218
+,该算法取E 119
Σ<代码>E 220,将小于一个小阈值的所有值设置为零,然后用它们的逆替换所有非零值,最后将生成的矩阵转移到零。这种方法比计算正规方程更有效。
我已经了解了伪逆和奇异值是如何从这贴子上联系起来的.但我无法理解将所有值设置为零的理由。对角线矩阵的逆是通过取对角元的倒数得到的。然后在逆矩阵中将小值转换为大值,对吗?那么,我们为什么要删除大值呢?
我查看了numpy代码,它如下所示,仅供参考:
@array_function_dispatch(_pinv_dispatcher)
def pinv(a, rcond=1e-15, hermitian=False):
a, wrap = _makearray(a)
rcond = asarray(rcond)
if _is_empty_2d(a):
m, n = a.shape[-2:]
res = empty(a.shape[:-2] + (n, m), dtype=a.dtype)
return wrap(res)
a = a.conjugate()
u, s, vt = svd(a, full_matrices=False, hermitian=hermitian)
# discard small singular values
cutoff = rcond[..., newaxis] * amax(s, axis=-1, keepdims=True)
large = s > cutoff
s = divide(1, s, where=large, out=s)
s[~large] = 0
res = matmul(transpose(vt), multiply(s[..., newaxis], transpose(u)))
return wrap(res)
发布于 2020-02-01 13:53:05
这几乎可以肯定是对数值误差的调整。为了了解为什么这可能是必要的,看看当你取一个2x2矩阵的秩的svd
时会发生什么。我们可以通过取如下向量的外积来创建秩一矩阵:
>>> a = numpy.arange(2) + 1
>>> A = a[:, None] * a[None, :]
>>> A
array([[1, 2],
[2, 4]])
虽然这是一个2x2矩阵,但它只有一个线性无关的列,因此它的排名是1而不是2。所以当我们把它传递给svd
时,其中一个奇异值将为零。但是看看发生了什么:
>>> U, s, V = numpy.linalg.svd(A)
>>> s
array([5.00000000e+00, 1.98602732e-16])
我们得到的是一个不完全为零的奇异值。这一结果在许多情况下是不可避免的,因为我们使用的是有限精度浮点数。所以,尽管你已经确定的问题是真实的,但我们在实践中将无法区分一个真正具有非常小的奇异值的矩阵与一个应该具有零奇异值但不具有奇异值的矩阵之间的区别。将小值设置为零是处理这个问题的最安全的实用方法。
https://stackoverflow.com/questions/60019708
复制