以下函数计算高斯核,并且是我编写的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
编辑:公式:
答案 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));
以下是我正在做的事情的解释:
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)))