/ edit: Tindak lanjut lebih lanjut sekarang Anda dapat menggunakan irlba :: prcomp_irlba
/ edit: menindaklanjuti posting saya sendiri. irlba
sekarang memiliki argumen "pusat" dan "skala", yang memungkinkan Anda menggunakannya untuk menghitung komponen prinsip, misalnya:
pc <- M %*% irlba(M, nv=5, nu=0, center=colMeans(M), right_only=TRUE)$v
Saya memiliki banyak Matrix
fitur yang ingin saya gunakan dalam algoritma pembelajaran mesin:
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)
Karena matriks ini memiliki banyak kolom, saya ingin mengurangi dimensinya menjadi sesuatu yang lebih mudah dikelola. Saya dapat menggunakan paket irlba yang sangat baik untuk melakukan SVD dan mengembalikan komponen utama n pertama (5 ditampilkan di sini; Saya mungkin akan menggunakan 100 atau 500 pada dataset aktual saya):
library(irlba)
pc <- irlba(M, nu=5)$u
Namun, saya telah membaca bahwa sebelum melakukan PCA, orang harus memusatkan matriks (kurangi rata-rata kolom dari setiap kolom). Ini sangat sulit dilakukan pada dataset saya, dan selanjutnya akan menghancurkan sparsity dari matriks.
Seberapa "buruk" untuk melakukan SVD pada data yang tidak diskalakan, dan memasukkannya langsung ke algoritma pembelajaran mesin? Adakah cara efisien yang bisa saya lakukan untuk menskala data ini, sambil menjaga sparsity dari matriks?
/ edit: A dibawa ke perhatian saya oleh B_miner, "PC" harus benar-benar:
pc <- M %*% irlba(M, nv=5, nu=0)$v
Juga, saya pikir jawaban whuber seharusnya cukup mudah diimplementasikan, melalui crossprod
fungsi, yang sangat cepat pada matriks jarang:
system.time(M_Mt <- crossprod(M)) # 0.463 seconds
system.time(means <- colMeans(M)) #0.003 seconds
Sekarang saya tidak yakin apa yang harus dilakukan terhadap means
vektor sebelum dikurangi M_Mt
, tetapi akan dikirim segera setelah saya mengetahuinya.
/ edit3: Berikut ini adalah versi modifikasi dari kode whuber, menggunakan operasi matriks jarang untuk setiap langkah proses. Jika Anda dapat menyimpan seluruh matriks jarang dalam memori, ia bekerja sangat cepat:
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))
Jika Anda mengatur jumlah kolom menjadi 10.000 dan jumlah komponen utama menjadi 25, irlba
PCA berbasiskan membutuhkan waktu sekitar 17 menit untuk menghitung 50 perkiraan komponen utama dan mengkonsumsi sekitar 6GB RAM, yang tidak terlalu buruk.
X %*% v %*% diag(d, ncol=length(d))
. Matriks v dalam svd setara dengan elemen "rotasi" dari suatu prcomp
objek, dan X %*% v
atau X %*% v %*% diag(d, ncol=length(d))
mewakili x
elemen dari suatu prcomp
objek. Lihatlah stats:::prcomp.default
.