/ chỉnh sửa: Theo dõi thêm bây giờ bạn có thể sử dụng irlba :: prcomp_irlba
/ chỉnh sửa: theo dõi trên bài viết của riêng tôi. irlba
bây giờ có các đối số "trung tâm" và "tỷ lệ", cho phép bạn sử dụng nó để tính toán các thành phần nguyên tắc, ví dụ:
pc <- M %*% irlba(M, nv=5, nu=0, center=colMeans(M), right_only=TRUE)$v
Tôi có một số lượng lớn Matrix
các tính năng mà tôi muốn sử dụng trong thuật toán học máy:
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)
Bởi vì ma trận này có nhiều cột, tôi muốn giảm kích thước của nó xuống một cái gì đó dễ quản lý hơn. Tôi có thể sử dụng gói irlba tuyệt vời để thực hiện SVD và trả về n thành phần chính đầu tiên (5 được hiển thị ở đây; tôi có thể sẽ sử dụng 100 hoặc 500 trên tập dữ liệu thực tế của mình):
library(irlba)
pc <- irlba(M, nu=5)$u
Tuy nhiên, tôi đã đọc rằng trước khi thực hiện PCA, người ta phải căn giữa ma trận (trừ trung bình cột từ mỗi cột). Điều này rất khó thực hiện trên tập dữ liệu của tôi và hơn nữa sẽ phá hủy sự thưa thớt của ma trận.
Làm thế nào "xấu" là nó thực hiện SVD trên dữ liệu không có tỷ lệ và đưa nó thẳng vào một thuật toán học máy? Có cách nào hiệu quả để tôi có thể mở rộng dữ liệu này, trong khi vẫn giữ được độ thưa của ma trận không?
/ chỉnh sửa: A mang đến sự chú ý của tôi bởi B_miner, "PC" thực sự phải là:
pc <- M %*% irlba(M, nv=5, nu=0)$v
Ngoài ra, tôi nghĩ rằng câu trả lời của người làm nên khá dễ thực hiện, thông qua crossprod
chức năng, cực kỳ nhanh trên các ma trận thưa thớt:
system.time(M_Mt <- crossprod(M)) # 0.463 seconds
system.time(means <- colMeans(M)) #0.003 seconds
Bây giờ tôi không chắc chắn phải làm gì với means
vectơ trước khi trừ đi M_Mt
, nhưng sẽ đăng ngay khi tôi tìm ra nó.
/ edit3: Đây là phiên bản sửa đổi của mã trình duyệt, sử dụng các hoạt động ma trận thưa thớt cho từng bước của quy trình. Nếu bạn có thể lưu trữ toàn bộ ma trận thưa thớt trong bộ nhớ, nó sẽ hoạt động rất nhanh:
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))
Nếu bạn đặt số lượng cột là 10.000 và số thành phần chính là 25, irlba
PCA dựa trên cơ sở sẽ mất khoảng 17 phút để tính 50 thành phần chính gần đúng và tiêu tốn khoảng 6GB RAM, điều này không quá tệ.
X %*% v %*% diag(d, ncol=length(d))
. Ma trận v trong svd tương đương với phần tử "xoay" của một prcomp
đối tượng và X %*% v
hoặc X %*% v %*% diag(d, ncol=length(d))
đại diện cho x
phần tử của một prcomp
đối tượng. Hãy xem a stats:::prcomp.default
.