/ 편집 : 추가 후속 조치 irlba :: prcomp_irlba를 사용할 수 있습니다
/ 편집 : 내 자신의 게시물에 후속. irlba
이제 "center"및 "scale"인수를 사용하여이를 사용하여 기본 구성 요소를 계산할 수 있습니다. 예 :
pc <- M %*% irlba(M, nv=5, nu=0, center=colMeans(M), right_only=TRUE)$v
Matrix
기계 학습 알고리즘에 사용하려는 크고 작은 기능이 있습니다.
library(Matrix)
set.seed(42)
rows <- 500000
cols <- 10000
i <- unlist(lapply(1:rows, function(i) rep(i, sample(1:5,1))))
j <- sample(1:cols, length(i), replace=TRUE)
M <- sparseMatrix(i, j)
이 행렬에는 많은 열이 있으므로 차원을 관리하기 쉬운 것으로 줄이려고합니다. 우수한 irlba 패키지 를 사용하여 SVD를 수행하고 첫 번째 n 주요 구성 요소를 반환 할 수 있습니다 (여기서는 5, 실제 데이터 세트에는 100 또는 500을 사용할 것입니다).
library(irlba)
pc <- irlba(M, nu=5)$u
그러나 PCA를 수행하기 전에 행렬을 중앙에 배치해야한다는 것을 읽었습니다 (각 열에서 열 평균을 뺍니다). 이것은 내 데이터 세트에서 수행하기가 매우 어렵고 행렬의 희소성을 파괴합니다.
스케일링되지 않은 데이터에 대해 SVD를 수행하고 머신 러닝 알고리즘에 직접 공급하는 것이 얼마나 "나쁜"가? 행렬의 희소성을 유지 하면서이 데이터를 확장 할 수있는 효율적인 방법이 있습니까?
/ edit : B_miner가 A에게 주목 한 "PC"는 다음과 같아야합니다.
pc <- M %*% irlba(M, nv=5, nu=0)$v
또한 whuber의 답변은 crossprod
희소 행렬에서 매우 빠른 함수 를 통해 구현하기가 매우 쉽다고 생각합니다 .
system.time(M_Mt <- crossprod(M)) # 0.463 seconds
system.time(means <- colMeans(M)) #0.003 seconds
이제 means
에서 빼기 전에 벡터에 대해 무엇을 해야할지 잘 모르겠지만 알아 M_Mt
낸 즉시 게시합니다.
/ edit3 : 프로세스의 각 단계마다 희소 행렬 연산을 사용하여 수정 된 버전의 whuber 코드가 있습니다. 전체 희소 행렬을 메모리에 저장할 수 있으면 매우 빠르게 작동합니다.
library('Matrix')
library('irlba')
set.seed(42)
m <- 500000
n <- 100
i <- unlist(lapply(1:m, function(i) rep(i, sample(25:50,1))))
j <- sample(1:n, length(i), replace=TRUE)
x <- sparseMatrix(i, j, x=runif(length(i)))
n_comp <- 50
system.time({
xt.x <- crossprod(x)
x.means <- colMeans(x)
xt.x <- (xt.x - m * tcrossprod(x.means)) / (m-1)
svd.0 <- irlba(xt.x, nu=0, nv=n_comp, tol=1e-10)
})
#user system elapsed
#0.148 0.030 2.923
system.time(pca <- prcomp(x, center=TRUE))
#user system elapsed
#32.178 2.702 12.322
max(abs(pca$center - x.means))
max(abs(xt.x - cov(as.matrix(x))))
max(abs(abs(svd.0$v / pca$rotation[,1:n_comp]) - 1))
열 수를 10,000으로 설정하고 주요 구성 요소 수를 25로 설정하면, irlba
기반 PCA는 대략적인 주요 구성 요소 50 개를 계산하는 데 약 17 분이 걸리고 약 6GB의 RAM을 소비하므로 이는 나쁘지 않습니다.
X %*% v %*% diag(d, ncol=length(d))
합니다. svd의 v 행렬은 prcomp
객체 의 "rotation"요소 와 동일 X %*% v
하거나 객체 X %*% v %*% diag(d, ncol=length(d))
의 x
요소를 나타냅니다 prcomp
. 보세요 stats:::prcomp.default
.