numpy 为什么SciPy的`linalg.svd`和`linalg.lstsq`的奇异值不匹配?

pnwntuvh  于 11个月前  发布在  其他
关注(0)|答案(1)|浏览(83)

SciPy's documentation表示lstsq返回观察矩阵的奇异值。但是当我直接使用singular value decomposition(来自SciPy的相同实现scipy.linalg.svd)计算它们时,我得到了一组不同的值。
两者的趋势肯定是一样的,但是它们的最小值和最大值似乎是不同的,这一点特别重要,因为它改变了条件数的估计,为什么它们不同呢?
下面的代码可以复制这个:

import numpy as np
from scipy.linalg import svd, lstsq
import matplotlib.pyplot as plt

# Let's generate some interesting X
X = np.arange(100*50, dtype=float).reshape(100,50)
X = np.sin(X) + np.tan(X) + np.cos(X)
X += np.random.normal(0,3, size=(100,50))

# And some function which we want to fit
# (for now it does't matter)
Y = np.sin(X)

# Let's compute the signular values of the observation matrix X
W, res, rank, s = lstsq(X, Y, cond=0) # cond=0 to deactivate sing-val truncation
_, S, _ = svd(X.T @ X)

# They should match exactly
plt.semilogy(S, label='from svd')
plt.semilogy(s, label='from lstsq')
plt.legend()

字符串


的数据

iyfjxgzm

iyfjxgzm1#

你在计算,一方面,X的奇异值,另一方面,X的奇异值,所以,不是相同的结果。
为了更准确,第二个结果是第一个的平方。因此,对数尺度上的乘法因子。
如果你想确信这一点,只要画出svd的平方根

_, S, _ = svd(X.T@X)
plt.semilogy(np.sqrt(S), label='from svd')
plt.semilogy(s, label='from lstsq')

字符串

或者,与正确的计算相比

_, S, _ = svd(X)
plt.semilogy(S, label='from svd')
plt.semilogy(s, label='from lstsq')


(same结果)
在你的代码中,sX的奇异值,SX.T@X的奇异值。这是不同的东西。但是为什么一个是另一个的平方是因为奇异值的定义:奇异值是X*X的特征值的平方根(这里= XᵀX,因为这些都是实值)。因此,XᵀX部分已经由svd完成。
设λ是XᵀX的特征值,即如果λ u <$0,X <$Xu = λu,则(X <$X)<$(X <$X)=(X <$X)(X <$X)u = X <$X λu = λ²u,所以λ²是(X <$X)<$(X <$X)的特征值。
因此,如果s是X的奇异值,也就是说如果s²是X <$X的特征值,那么s <$是(X <$X)<$(X <$X)的特征值,那么s²是X <$X的奇异值。
所以,这里没什么奇怪的,奇异值是奇异值的平方,这和你的图显示的一样。

相关问题