/ 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 suatuprcomp
objek, danX %*% v
atauX %*% v %*% diag(d, ncol=length(d))
mewakilix
elemen dari suatuprcomp
objek. Lihatlahstats:::prcomp.default
.Jawaban:
Pertama-tama, Anda benar-benar ingin memusatkan data . Jika tidak, interpretasi geometris PCA menunjukkan bahwa komponen utama pertama akan dekat dengan vektor rata-rata dan semua PC berikutnya akan ortogonal, yang akan mencegah mereka mendekati PC mana pun yang dekat dengan vektor pertama tersebut. Kita dapat berharap bahwa sebagian besar PC yang akan datang kira-kira benar, tetapi nilai yang dipertanyakan ketika kemungkinan beberapa PC pertama - yang paling penting - akan sangat salah.
Jadi, apa yang harus dilakukan? PCA hasil dengan cara dekomposisi nilai singular dari matriks . Informasi penting akan terkandung dalam X X ' , yang dalam hal ini adalah 10000 dengan 10000 matriks: yang mungkin dikelola. Perhitungannya melibatkan sekitar 50 juta perhitungan produk titik dari satu kolom dengan yang berikutnya.X XX′ 10000 10000
Pertimbangkan dua kolom, lalu, dan Z (masing-masingnya adalah vektor 500000 ; biarkan dimensi ini n ). Biarkan sarana mereka menjadi m Y dan m Z , masing-masing. Yang ingin Anda hitung adalah, menulis 1 untuk n- vektor 1 's,Y Z 500000 n mY mZ 1 n 1
karena dan m Z = 1 ⋅ Z / n .mY=1⋅Y/n mZ=1⋅Z/n
Hal ini memungkinkan Anda untuk menggunakan teknik matriks jarang untuk menghitung , yang entri memberikan nilai-nilai Y ⋅ Z , dan kemudian menyesuaikan koefisien yang didasarkan pada 10000 sarana kolom. Penyesuaian seharusnya tidak sakit, karena sepertinya tidak mungkin X X ′ akan sangat jarang.XX′ Y⋅Z 10000 XX′
Contoh
R
Kode berikut menunjukkan pendekatan ini. Ini menggunakan rintisan,,get.col
yang dalam praktiknya mungkin membaca satu kolom pada suatu waktu dari sumber data eksternal, sehingga mengurangi jumlah RAM yang diperlukan (tentu saja dengan biaya dalam kecepatan komputasi, tentu saja). Ini menghitung PCA dalam dua cara: melalui SVD diterapkan pada konstruksi sebelumnya dan langsung menggunakan . Kemudian membandingkan output dari dua pendekatan. Waktu perhitungan adalah sekitar 50 detik untuk 100 kolom dan skala kira-kira secara kuadratik: bersiaplah untuk menunggu ketika melakukan SVD pada matriks 10K x 10K!prcomp
sumber
irlba
adalah Anda dapat menentukannu
untuk membatasi algoritma pada komponen prinsip n pertama, yang sangat meningkatkan kemanjurannya dan (saya pikir) mengabaikan perhitungan matriks XX '.irlba
dapat diterapkan pada yang terakhir untuk mendapatkan hanya beberapa komponen utama pertama, sehingga Anda mendapatkan yang terbaik dari kedua dunia.colMeans
matriks jarang dari matriks produk titik, kemudian jalankan irlba pada hasilnya?R
membuat