psl*_*ice 7 math performance r matrix
随机SVD通过使用k + p个随机投影提取前k个奇异值/向量来分解矩阵.这对于大型矩阵来说效果非常好.
我的问题涉及从算法输出的奇异值.如果你做完整的SVD,为什么这些值不等于第一个k-奇异值?
下面我在R中有一个简单的实现.任何有关改善性能的建议都将受到赞赏.
rsvd = function(A, k=10, p=5) {
n = nrow(A)
y = A %*% matrix(rnorm(n * (k+p)), nrow=n)
q = qr.Q(qr(y))
b = t(q) %*% A
svd = svd(b)
list(u=q %*% svd$u, d=svd$d, v=svd$v)
}
> set.seed(10)
> A <- matrix(rnorm(500*500),500,500)
> svd(A)$d[1:15]
[1] 44.94307 44.48235 43.78984 43.44626 43.27146 43.15066 42.79720 42.54440 42.27439 42.21873 41.79763 41.51349 41.48338 41.35024 41.18068
> rsvd.o(A,10,5)$d
[1] 34.83741 33.83411 33.09522 32.65761 32.34326 31.80868 31.38253 30.96395 30.79063 30.34387 30.04538 29.56061 29.24128 29.12612 27.61804
Run Code Online (Sandbox Code Playgroud)
我认为你的算法是Martinsson 等人算法的修改。。如果我理解正确的话,这尤其适用于低秩矩阵的近似。但我可能是错的。
这种差异很容易解释为 A (500) 的实际排名与 k (10) 和 p (5) 的值之间的巨大差异。另外,Martinsson 等人提到 p 的值实际上应该大于 k 的选定值。
因此,如果我们应用您的解决方案并考虑到他们的考虑,请使用:
set.seed(10)
A <- matrix(rnorm(500*500),500,500) # rank 500
B <- matrix(rnorm(500*50),500,500) # rank 50
Run Code Online (Sandbox Code Playgroud)
我们发现,与原始 svd 算法相比,使用较大的 p 值仍然会带来巨大的加速。
> system.time(t1 <- svd(A)$d[1:5])
user system elapsed
0.8 0.0 0.8
> system.time(t2 <- rsvd(A,10,5)$d[1:5])
user system elapsed
0.01 0.00 0.02
> system.time(t3 <- rsvd(A,10,30)$d[1:5])
user system elapsed
0.04 0.00 0.03
> system.time(t4 <- svd(B)$d[1:5] )
user system elapsed
0.55 0.00 0.55
> system.time(t5 <-rsvd(B,10,5)$d[1:5] )
user system elapsed
0.02 0.00 0.02
> system.time(t6 <-rsvd(B,10,30)$d[1:5] )
user system elapsed
0.05 0.00 0.05
> system.time(t7 <-rsvd(B,25,30)$d[1:5] )
user system elapsed
0.06 0.00 0.06
Run Code Online (Sandbox Code Playgroud)
但我们看到,对较低秩矩阵使用较高的 p 确实可以提供更好的近似值。如果我们让 k 也更接近秩,则真实解和近似值之间的差异将变为 appx。0,而速度增益仍然很大。
> round(mean(t2/t1),2)
[1] 0.77
> round(mean(t3/t1),2)
[1] 0.82
> round(mean(t5/t4),2)
[1] 0.92
> round(mean(t6/t4),2)
[1] 0.97
> round(mean(t7/t4),2)
[1] 1
Run Code Online (Sandbox Code Playgroud)
所以总的来说,我相信人们可以得出这样的结论:
l如果我是对的,马丁森称之为它)就我而言,这是一种巧妙的方法。实际上我真的找不到更优化的方法。我唯一能说的是,t(q) %*% A不建议这种构造。人们应该使用crossprod(q,A)它,这应该会快一点。但在你的例子中,差异是不存在的。