/ edit:irlba :: prcomp_irlbaを使用できるようになりました。
/ edit:自分の投稿のフォローアップ。 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:AはB_minerによって注目されました。「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
オブジェクトの「回転」要素に相当し、X %*% v
またはオブジェクトX %*% v %*% diag(d, ncol=length(d))
のx
要素を表しprcomp
ます。を見てくださいstats:::prcomp.default
。