我目前正在通过采用已知向量并使用两个外部乘积的元素逐次乘法作为输入矩阵来计算二次形式。具体来说,我的代码看起来像这样
set.seed(42) # for sake of reproducibility
library(emulator)
Fun <- function(a,b) sqrt((1/(2*pi)))*exp(-0.5*(a-b)^2)
n <- 5000
x <- rnorm(n)
y <- rnorm(n)
u <- rnorm(n)
I <- quad.form(outer(x,x,Fun)*outer(y,y,Fun),u)
这很慢,并且随着n的增加,问题变得更加严重。据我所知,导致问题的部分是二次形式中的外部(x,x,Fun)*外部(y,y,Fun)项。
有什么办法可以加快速度吗?
答案 0 :(得分:3)
您可以利用对称性来减少计时的一半。我发现快速编写Rcpp函数最简单:
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
NumericMatrix foo(NumericVector x, NumericVector y) {
double n = x.size();
NumericMatrix M(n, n);
for(double i = 0; i < n; i++) {
for(double j = 0; j <= i; j++) {
M(i,j) = ((1/(2*M_PI))) *
(exp(-0.5*(pow(x(i)-x(j), 2) + pow(y(i)-y(j), 2))));
M(j,i) = M(i,j);
}
}
return M;
}
时间:
set.seed(42) # for sake of reproducibility
library(emulator)
Fun <- function(a,b) sqrt((1/(2*pi)))*exp(-0.5*(a-b)^2)
n <- 1e4
x <- rnorm(n)
y <- rnorm(n)
u <- rnorm(n)
system.time({
I <- quad.form(outer(x,x,Fun)*outer(y,y,Fun),u)
})
# user system elapsed
# 4.287 1.373 5.687
system.time({
J <- quad.form(foo(x, y),u)
})
# user system elapsed
# 2.232 0.168 2.409
all.equal(I, J)
#[1] TRUE
进一步的改进将要求并行化(或可能使用一些数学方法)。