在Matlab中,有没有一种更快的方法来计算矩阵的按元素指数?

时间:2019-02-14 21:31:08

标签: matlab performance

我正在分析我的代码,这一行似乎是瓶颈。这个想法是基于相同维度的theta向量创建一个包含给定维度的n个观测值的空间相关矩阵-包含要拟合的维度超参数。

在我的整体代码中,在计算似然函数以优化我的theta参数时,这个空间相关函数被调用了数千次(每次迭代)。观察的数量在整个代码的每次迭代中增加一,并且theta参数必须在每次迭代中都进行调整。因此,您可以看到随着算法的发展,这一行代码如何变得至关重要。

我认为最慢的线,即R = exp(sum(bsxfun(@times, -abs(D_X).^corr_model,reshape(theta,[1 1 d])),3));花了最多的时间来计算最终的n×n矩阵的最终元素指数(n×n矩阵是在3维上求和后得出的距离矩阵)。但是这条线上有很多事情要做,所以我不确定这是否是整体性能的最关键方面。

感谢您的任何见解!

我已经用repmat替换了bsxfun命令,以在维度距离矩阵D_X上乘以给定的theta,这显着加快了代码的速度。但是,嵌套第二个bsxfun来执行距离的平方,即替换abs(D_X).^corr_model会使代码的运行速度变慢。

n = 500;
dimension = 20;
D_X = repmat(rand(n),[1 1 dimension]);
theta = rand(dimension, 1);
corr_model = 2;

R = corr(corr_model,theta, D_X);

function R = corr(corr_model,theta,D_X)
% calculate the correlation matrix for the modified nugget effect model
% corr_model - the correlation model used for the spatial correlation
% corr_model = 2: gaussian correlation function
% theta - vector of hyperparameters
% D_X - the distance matrix for the input locations

d = size(theta,1);

switch corr_model
    case 2 %Gaussian correlation function  
        R = exp(sum(bsxfun(@times, -abs(D_X).^corr_model,reshape(theta,[1 1 d])),3));
end
end

1 个答案:

答案 0 :(得分:2)

这是一个更优化的版本:

n = 500;
dimension = 20;
D_X = rand(n);
theta = rand(dimension, 1);
corr_model = 2;

function R = corr(corr_model, theta, D_X)
    switch corr_model
        case 2  
            R = exp(-sum(theta)) .^ ( D_X .^ corr_model );
    end
end

已采取以下步骤:

R = exp(sum(bsxfun(@times, -abs(D_X).^corr_model,reshape(theta,[1 1 d])),3));
R = exp((-abs(D_X) .^ corr_model) .* sum(theta)) ;
R = exp((-D_X .^ corr_model) .* sum(theta)) ;
R = exp((D_X .^ corr_model) .* (-sum(theta)));
R = exp(-sum(theta)) .^ ( D_X .^ corr_model );
  • 您可以仅设置repmat而不是D_X = rand(n),以便可以分解出(-abs(D_X) .^ corr_model)并将其乘以theta的总和。

  • 因为D_X是实矩阵abs(D_X)^2等效于D_X^2

  • (-D_X.^corr_model) .*sum(theta)转换为(D_X.^corr_model) .*(-sum(theta))可能会加快计算速度,因为您只需要取消标量,而标量应该比取消数组便宜。

  • 知道x^(ab) = (x^a)^b表达式exp(( D_X .^ corr_model ) .* (-sum(theta)))可以转换为exp(-sum(theta)) .^ ( D_X .^ corr_model )。在第一个表达式中,我们对D_X进行了三个操作,但是在第二个表达式中,对D_X应用了两个操作。

编辑:

D_X矩阵的注释片段中所指出的不同,因此上述方法不适用,因此可以使用以下方法:

D_X1 = reshape(permute(D_X, [3 2 1]), dimension,[]);
%calling thousands of times
for k = 1 : 10000
    R = corr(corr_model,theta, D_X1);
end
% matrix reshaped to its original size
Result = reshape(R,n,n);

function R = corr(corr_model, theta, D_X)
    switch corr_model
        case 2  
            R = exp(-theta.' * (D_X.^corr_model));
    end
end

这里D_X被置换并重整为[20 x 250000]矩阵,因此可以使用矩阵乘法来代替乘积之和。
同样,如果相关矩阵是对称的,则可以使用其一半的元素。现在矩阵大小为[20 x 125250]

idx = tril(true(n));
D_X1 = reshape(permute(D_X, [3 2 1]), dimension,[]);
D_X1 = D_X1(:,idx);

for k = 1 : 10000
    R = corr(corr_model,theta, D_X1);
end

% matrix reshaped to its original size
Result = zeros(n);
Result(idx) = R;
d = diag(Result);
Result = Result + Result.'
Result(1:n+1:end)=d;