为什么不能通过XX'和X'X的特征值分解来获得X的有效SVD?


9

我正在尝试手工制作SVD:

m<-matrix(c(1,0,1,2,1,1,1,0,0),byrow=TRUE,nrow=3)

U=eigen(m%*%t(m))$vector
V=eigen(t(m)%*%m)$vector
D=sqrt(diag(eigen(m%*%t(m))$values))

U1=svd(m)$u
V1=svd(m)$v
D1=diag(svd(m)$d)

U1%*%D1%*%t(V1)
U%*%D%*%t(V)

但是最后一行不会返回m。为什么?似乎与这些特征向量的迹象有关...还是我误解了该过程?



我一再被告知,在SVD中信号并不重要...就像这样
失败的统计师,

@Amoeba谢谢您的澄清。我专注于英语问题而不是代码。Failedstatistician:查看D=diag(c(-1,1,1)*sqrt(eigen(m%*%t(m))$values))操作并记住平方根(以及任何归一化的特征向量)仅定义为正负号。要获取更多信息,请更改m为,m <- matrix(-2,1,1),1,1)在每次致电末尾添加diag。这是一个示例,它会产生相同的问题-但如此简单,问题的本质将变得十分明显。1×1
ub

1
得到它了。谢谢!您是否有确定向量c(-1,1,1)的一般规则?还是应该将两个分解的符号联系起来?
失败的统计师,2017年

1
请注意,@ whuber的把戏c(-1,1,1)确实可以使用,但是这样D定义并不能给您单值。根据定义,奇异值必须全部为正。如何联系起来的迹象问题UV好,我没有答案。您为什么不只做SVD?:-)
amoeba '02

Answers:


13

问题分析

矩阵的SVD永远都不是唯一的。设矩阵维数为,其SVD为n × kAn×k

A=UDV

对于具有正交列的矩阵,具有非负项的对角矩阵和具有正交列的矩阵U p × p D k × p Vn×pUp×pDk×pV

现在,任意选择对角线上有 s的任何对角线矩阵,使得是身份。然后S ± 1 S 2 = I p × p I pp×pS±1S2=Ip×p一世p

一个=üdV=ü一世d一世V=ü小号2d小号2V=ü小号小号d小号V小号

也是一个的SVD因为演示具有正交列相似的计算表明具有正交列。此外,由于和是对角线,所以它们通勤,因此表示仍然具有非负项。û 小号'Ù 小号= 小号' ü ' Ù 小号= 小号' p小号= 小号'小号= 小号2 = p Ü 小号V 小号小号d 小号d 小号= d 小号2 = d d一个

ü小号ü小号=小号üü小号=小号一世p小号=小号小号=小号2=一世p
ü小号V小号小号d
小号d小号=d小号2=d
d

在代码中找到SVD的方法将找到一个对角化A的,类似地,对角化的 它前进到计算中的特征值方面中发现。 问题在于,这不能确保的列与的列始终匹配' = û d V 'Û d V ' ' = Ü d V ' V d ' Ù ' = û d 2 ü V '= V d 2 V 'D D 2 U Vü

一个一个=üdVüdV=üdVVdü=üd2ü
V
一个一个=Vd2V
dd2üV

一个解法

相反,找到这样的和这样的,用它们来计算VüV

ü一个V=üüdVV=üüdVV=d

直接有效地。 该的对角线值不一定为正。d (这是因为对角化或的过程没有什么可以保证的,因为这两个过程是分别进行的。)通过选择对角线中的项使它们为正等于项的符号,因此具有所有正值。弥补这种由右乘用:'小号d 小号d ù 小号一个一个一个一个小号d小号dü小号

一个=üdV=ü小号小号dV

是一个SVD。

令且。SVD是ñ=p=ķ=1个一个=-2

-2=1个2-1个

其中,和。ü=1个d=2V=-1个

如果对角化您自然会选择和。同样,如果将A对角化,则可以选择。不幸的是,相反,计算 因为这是负数,所以设置。这将调整为,将为。您已经获得了它是两个可能的SVD之一(但与原始的不一样!)。一个一个=4ü=1个d=4=2一个一个=4V=1个

üdV=1个21个=2一个
d=ü一个V=1个-21个=-2
小号=-1个üü小号=1个-1个=-1个d小号d=-1个-2=2
一个=-1个21个

这是修改后的代码。其输出确认

  1. 该方法m正确地重新创建。
  2. ü和实际上仍然是正交的。V
  3. 但是结果与所返回的SVD不同svd。(两者同等有效。)
m <- matrix(c(1,0,1,2,1,1,1,0,0),byrow=TRUE,nrow=3)

U <- eigen(tcrossprod(m))$vector
V <- eigen(crossprod(m))$vector
D <- diag(zapsmall(diag(t(U) %*% m %*% V)))
s <- diag(sign(diag(D)))  # Find the signs of the eigenvalues
U <- U %*% s              # Adjust the columns of U
D <- s %*% D              # Fix up D.  (D <- abs(D) would be more efficient.)

U1=svd(m)$u
V1=svd(m)$v
D1=diag(svd(m)$d,n,n)

zapsmall(U1 %*% D1 %*% t(V1)) # SVD
zapsmall(U %*% D %*% t(V))    # Hand-rolled SVD
zapsmall(crossprod(U))        # Check that U is orthonormal
zapsmall(tcrossprod(V))       # Check that V' is orthonormal

1
+1。这很清楚。我只会在实践中添加一个,即足以计算UV,然后通过与相乘获得另一个矩阵A。这样,一个人仅执行一个(而不是两个)本征分解,并且信号会正确显示。
amoeba'2

2
@Amoeba是的:按照手工计算SVD的精神,这显然是一种教育活动,在这里没有关注效率。
胡伯

2
谢谢你的热心帮助!我想我(最终)理解了这个问题。
失败的统计师,

3
@Federico谢谢您的提醒。您是完全正确的-我隐式地假设所有特征值都是不同的,因为实际上在统计应用中几乎肯定会是这种情况,并且摆脱了考虑“退化”特征空间的歧义的习惯。
ub

3
您是正确的,这只是一个极端情况,确实是一个棘手的情况。从某种意义上讲,这是您在答案中概述的同一问题的另一种体现,即该方法不能确保和列之间的“匹配” 。从特征分解开始计算SVD仍然是一个很好的学习示例。üV
Federico Poloni'2

5

正如我在@whuber答案的评论中所概述的那样,这种计算SVD的方法不适用于每个矩阵。问题不仅限于迹象。

问题在于可能存在重复的特征值,在这种情况下,和A的特征不是唯一的,并且并非所有的和选择都可用于检索SVD的对角因子。例如,如果您采用任何非对角正交矩阵(例如),则。在特征向量矩阵所有可能选择中,将返回,因此在这种情况下,不是对角线。一个一个一个一个üV一个=[3/54/5-4/53/5]一个一个=一个一个=一世一世eigenü=V=一世ü一个V=一个

直观上,这是@whuber概述的同一问题的另一种体现,即和的列之间必须存在“匹配” ,并且单独计算两个本征分解不能确保这一点。üV

一个一个一个一个一个一个2üü2×10-1610-8

从两个特征分解中计算SVD是一个很好的学习示例,但是在现实生活中,应用程序始终使用R svd函数来计算奇异值分解。


1
此评论是很好的建议。但是请注意,该线程并不关心计算SVD的正确方法(我相信没有人会反对您的建议)。OP隐式接受该svd工作。的确,他们将其用作比较手算的标准,目的是检查理解,而不svd是以任何方式代替。
ub

@whuber正确观察;我改写了最后一段。
Federico Poloni'2
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.