Расчет
Я считаю, что ваш алгоритм является модификацией алгоритма Martinsson et al. .Если я правильно понял, это особенно важно для приближений для матриц низкого ранга.Я могу ошибаться, хотя.
Разницу легко объяснить огромной разницей между фактическим рангом A (500) и значениями k (10) и p (5).Кроме того, Мартинссон и др. Отмечают, что значение для p на самом деле должно быть больше, чем выбранное значение для k.
Поэтому, если мы применим ваше решение с учетом их соображений, используя:
set.seed(10)
A <- matrix(rnorm(500*500),500,500) # rank 500
B <- matrix(rnorm(500*50),500,500) # rank 50
Мы считаем, что использование большего значения p по-прежнему приводит к огромному ускорению по сравнению с исходным алгоритмом SVD.
> 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
Но мы видим, что использование более высокого p для более низкого рангаматрица действительно дает лучшее приближение.Если мы позволим k также приблизиться к рангу немного ближе, разница между реальным решением и приближением станет ок.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
Итак, в общем, я считаю, что можно сделать вывод, что:
- p следует выбирать так, чтобы p> k (Мартинссон вызываетэто
l
если я прав) - k не должно сильно отличаться от ранга (A)
- Для матриц низкого ранга результат обычно лучше.
Оптимизация:
Насколько я понимаю, это отличный способ сделать это.Я действительно не мог найти более оптимальный путь.Единственное, что я могу сказать, это то, что конструкция t(q) %*% A
не рекомендуется.Для этого нужно использовать crossprod(q,A)
, что должно быть немного быстрее.Но в вашем примере разницы не было.