我使用高斯 - 拉盖尔积分来近似大矩阵中每个点的积分。目前我要评估每个节点上整个矩阵的函数,并在for
循环中求和矩阵。虽然速度不是非常慢,但是这个函数需要大约1秒才能获得~2e6点和~30个节点,并且我希望在期望最大化例程中使用该函数。计算weights[i]*func(nodes[i], x, mu)
(x是点的矩阵,mu是行特定的局部均值),R的内置向量化很快,所以我认为减速(不出所料)是矩阵上的循环。使用numpy中的ndarrays,我只需重新整形每个数组,以便将结果广播到m by p数组,其中n,m作为x的维数,p作为节点数,并沿最后一维求和。 R中的多路数组似乎没有这样的功能;操作似乎只适用于相同形状的数组。虽然将数据复制到相同的形状是微不足道的,但是带有~2e6元素的4个数组似乎是浪费。 R中是否有另一个用于多维数组的包/结构,其广播规则类似于numpys?代码如下。查看here了解上下文。
integral.local <- function(x, mu, func, params) {
# func must be vectorized for x and mu
integral.sums <- matrix(0,nrow = nrow(x), ncol= ncol(x))
for (i in 1:length(nodes)){
integral.sums <- integral.sums + weights[i]*func(nodes[i], x, mu, params)
}
integral.sums
}
pow.const.func <- function (theta, x, mu, params) {
# for use in Gauss-Laguerre quadrature
# implicitly assumes phi > 0
# vectorized for x and mu
s <- exp(1/2*params['beta0'])*(params['phi']*theta + mu)^
(1/2*params['beta1'])
tmp <- x-(params['phi']*theta + mu)
1/(sqrt(2*pi)*s)*exp(-tmp*tmp/(2*s*s))
}
编辑:我的基准测试已关闭。这是基于system.time
,当我在循环之前使用repmat
将mu
复制为x
的形状时。对于39个节点,上面的函数下面是microbenchmark
。差不多差不多~1秒,但我仍然不介意加快一个数量级。
Unit: milliseconds
expr min lq mean median uq max neval
integral.local 216.8249 219.7517 233.6998 220.9933 225.3213 1044.216 100