改善MATLAB函数的执行时间

时间:2012-08-15 22:18:09

标签: matlab time execution

以下函数计算高斯核,并且是我编写的Kernel Ridge回归算法的一部分。我想知道如何才能正确地修改这个功能,以便改善执行时间(即摆脱两个for循环)。有什么想法吗?

function [K] = calculate_krr_gaussiankernel(Xi,Xj,S)
    K = zeros(size(Xi,1),size(Xj,1));
    for Ixi = 1:size(Xi,1),
        for Ixj = 1:size(Xj,1),
            K(Ixi,Ixj) = exp((-norm(Xi(Ixi,:) - Xj(Ixj,:)) .^ 2) ./ (2 * (S .^ 2)));
        end
    end
end

编辑:公式: enter image description here

2 个答案:

答案 0 :(得分:3)

这是一个最有可能更快的版本。但是,它可能会导致大Xi / Xj的内存问题。

function K = calculate_krr_gaussiankernel(Xi, Xj, S)

  %# create an array of difference between Xi(r,:) and Xj(s,:) for all r,s
  delta = bsxfun(@minus, permute(Xi,[1 3 2]), permute(Xj,[3 1 2]));

  %# calculate the squared norm
  ssq = sum(delta.^2, 3);

  %# calculate the kernel
  K = exp(-ssq./(2*S.^2));

以下是我正在做的事情的解释:

  • bsxfun行:我重塑输入,这样我就可以在每个(i,j)得到第三维中的差异向量
  • ssq线只取平方和。我可以在这里取平方根,从而得到规范,但既然我们将再次对此进行调整,无论如何,那都没有意义。
  • 最后一行在OP中实现公式,其中ssq是差异的平方范数。

答案 1 :(得分:2)

由于K是对称的,因此当然可以使速度加倍(大约)。此外,您可以计算差异向量的norm,然后拨打exp()一次,这可能比一次又一次地调用exp()更快。把它放在一起:

function [K] = calculate_krr_gaussiankernel(Xi,Xj,S)
    arg = zeros(size(Xi,1),size(Xj,1));
    for Ixi = 1:size(Xi,1),
        % diagonal elements can be done in outer loop:
        arg(Ixi,Ixi) = norm(Xi(Ixi,:) - Xj(Ixi,:));
        for Ixj = Ixi+1:size(Xj,1), % off-diagonals done once and copied
            arg(Ixi,Ixj) = norm(Xi(Ixi,:) - Xj(Ixj,:));
            arg(Ixj,Ixi) = arg(Ixi,Ixj);
        end
    end
end

K = exp(( -arg.^ 2) ./ (2 * (S .^ 2)))