我有一个非常大的矩阵(20000 * 20000),我想计算它的最大特征值。 当我在Matlab中进行操作时,需要几秒钟,但在R中,计算需要一个多小时。目前我使用的是rARPACK,计算时间需要数小时。
library("rARPACK")
eigs_sym(cov(TS), k = 1, which = "LM", opts = list(retvec = FALSE))
任何替代方案或解决方案?
答案 0 :(得分:1)
rARPACK曾经是库ARPACK的包装器,但现在是Spectra的包装器,是相同算法的改进和重新实现版本,在many tests中优于ARPACK。
由于matlab cov(TS)
函数也是ARPACK包的包装器,如果在两种情况下都有相同的参数,则问题似乎不太可能是解算器。
花时间的步骤是否可能是协方差矩阵的计算(即{{1}})?
答案 1 :(得分:0)
令我惊讶的是,RSpectra::eigs_sym
的速度还没有base::eigen
快。我做了一个基准,比较了各种样本量和特征值数量。
通常,RSpectra::eigs_sym
比base::eigen
快3-5倍。但是考虑到base::eigen
将花费20000 * 20000的永恒值,RSpectra::eigs_sym
仍然应该花费相当长的四分之一时间!
library(RSpectra)
library(tidyverse)
library(microbenchmark)
library(clusterGeneration)
library(tictoc)
## generate S
S_dat <- tibble(size = c(50, 100, 500, 1000, 2000, 5000)) %>%
mutate(S=map(size, ~genPositiveDefMat(.)$Sigma))
### benvhmark function
bench_oneS <- function(S, n_eigens=5){
dim <- nrow(S)
n_rep <- case_when(dim<=1000 ~20,
TRUE~10)
microbenchmark("base::eigen" = eigen(S)$values[1:n_eigens],
"RSpectra::eigs_sym" =eigs_sym(S,n_eigens, opts = list(retvec = FALSE))$values,
times=n_rep) %>%
summary(a, unit="ms") %>%
as_tibble() %>%
mutate(expr = as.character(expr))
}
## do benchmark
tic()
bench_out <- S_dat %>%
mutate(bench_5=map(S, ~bench_oneS(.)),
bench_1=map(S, ~bench_oneS(., n_eigens=1))) %>%
dplyr::select(-S)%>%
pivot_longer(starts_with("bench"), names_to="n_eigens", values_to="bench",
names_prefix="bench_", names_transform=list(n_eigens=as.integer)) %>%
unnest(bench)
toc()
##
pl_ratio <- bench_out %>%
dplyr::select(size, n_eigens, expr, mean) %>%
spread(expr, mean) %>%
mutate(ratio=`base::eigen` /`RSpectra::eigs_sym`) %>%
ggplot(aes(x=size, y= ratio, linetype=factor(n_eigens))) +
geom_line()+
geom_point()+
labs(color="Method:", linetype="N eigens")+
theme(legend.position="bottom")+
ylab("Ratio time (eigen/eigs_sym)")+
xlab("Sample size")+
ggtitle("Ratio of average timing, base::eigen vs RSpectra::eigs_sym")