СВД очень большой матрицы в R

Я хочу сгенерировать матрицу 30000 x 30000 в r, умножив вектор из 30000 элементов на его транспонирование, а затем получить SVD этой матрицы, но программа говорит мне, что r не может найти вектор размером 900000000. Помогите мне, что я могу сделать?

y <- read.csv("C:\\Users\\jmarescr\\Desktop\\BigLetra50.csv",header=TRUE)

x <- matrix(y[1:30000,1],30000,1)
tx <- as.matrix(t(x))

mat <- x %*% tx

Error: can not allocate vector of length 900000000

s <- svd(mat)

Error in svd (x): object 'mat' not found

person user2358634    schedule 29.05.2013    source источник


Ответы (1)


Часть красоты SVD заключается в том, что вам не нужно брать перекрестное произведение x, чтобы получить SVD перекрестного произведения.

Вместо этого вы можете получить СВД x%*%t(x) (он же tcrossprod(x)) непосредственно из элементов СВД x. В частности (и с точностью до знака столбцов U) SVD(x %*% t(x)) = U D^2 t(U), ​​где U и D взяты из SVD x. (Для справки см. здесь.)

Чтобы увидеть это в действии, попробуйте небольшой пример:

set.seed(1)
x <- matrix(rnorm(15), ncol=5)


svd(x)$d
# [1] 3.046842 1.837539 1.411585
sqrt(svd(tcrossprod(x))$d)
# [1] 3.046842 1.837539 1.411585

svd(x)$u
#            [,1]       [,2]      [,3]
# [1,] -0.3424029  0.7635281 0.5475264
# [2,] -0.8746155 -0.4719093 0.1111273
# [3,]  0.3432316 -0.4408248 0.8293766
svd(tcrossprod(x))$u
#            [,1]       [,2]      [,3]
# [1,] -0.3424029  0.7635281 0.5475264
# [2,] -0.8746155 -0.4719093 0.1111273
# [3,]  0.3432316 -0.4408248 0.8293766
svd(tcrossprod(x))$v
#            [,1]       [,2]      [,3]
# [1,] -0.3424029  0.7635281 0.5475264
# [2,] -0.8746155 -0.4719093 0.1111273
# [3,]  0.3432316 -0.4408248 0.8293766

Другой способ увидеть это:

sss <- svd(x)

with(sss, u %*% diag(d)^2 %*% t(u))
#           [,1]      [,2]      [,3]
# [1,]  3.654154  1.684675 -1.322649
# [2,]  1.684675  7.877802 -1.900721
# [3,] -1.322649 -1.900721  3.120415

tcrossprod(x)
#           [,1]      [,2]      [,3]
# [1,]  3.654154  1.684675 -1.322649
# [2,]  1.684675  7.877802 -1.900721
# [3,] -1.322649 -1.900721  3.120415
person Josh O'Brien    schedule 29.05.2013
comment
Кроме того, обратите внимание, что (в зависимости от вашего приложения) вы можете ускорить работу, вычислив меньше, чем полный набор левых сингулярных векторов. См. раздел «Подробности» в ?svd, чтобы узнать, как/почему вы можете захотеть вручную установить nu меньше, чем min(nrow(x), ncol(x)). - person Josh O'Brien; 29.05.2013