我正在编写一个计算某种矩阵的Matlab应用程序。我试图用基于矢量的计算替换程序中的for循环,但是,我被卡住了。
到目前为止,我已经想到了这个简单的代码部分代码:
kernel = zeros(5,5,5);
offset = 3;
sig=1;
for x=-2:2
for y=-2:2
for z=-2:2
IN = x.^2/(sig^2) + y.^2/(sig^2) + z.^2/(sig^2);
kernel(offset+x, offset+y, offset+z) = exp(-IN/2);
end
end
end
可以用这样的结构代替:
[x,y,z] = ndgrid(-2:2,-2:2,-2:2);
IN = x.^2/(sig^2) + y.^2/(sig^2) + z.^2/(sig^2);
kernel = exp(-IN/2);
并给出相同的结果。 但是,如果我需要进行一些小改动怎么办呢?
kernel = zeros(5,5,5);
offset = 3;
sig=1;
%sample 3x3 matrix
R=magic(3)/10;
for x=-2:2
for y=-2:2
for z=-2:2
% calculation of new x, y, z
point = [x,y,z]*R;
IN = (point(1)^2 )/(sig^2) + (point(2)^2)/(sig^2) + (point(3)^2)/(sig^2);
kernel(offset+x, offset+y, offset+z) = exp(-IN/2);
end
end
end
如何加快这种结构?可以轻松地进行矢量化吗?我对Matlab很新,所以我很感激任何帮助。非常感谢!
答案 0 :(得分:3)
一种选择是使用arrayfun
。
sig=1;
%sample 3x3 matrix
R=magic(3)/10;
[x,y,z] = ndgrid(-2:2,-2:2,-2:2);
kernel = arrayfun(@(x, y, z) exp(-(norm([x,y,z]*R/sig)^2)/2), x,y,z);
说明:
arrayfun
采用一个函数作用于标量输入以产生标量输出,以及传递给函数的输入数组。然后它遍历输入数组,在每个数组上运行你的函数,并将每个输出放在输出矩阵(-es)中的相应条目中。所以arrayfun
基本上是嵌套循环,这会减慢你的一切。
在这个例子中,我还使用anonymous function(也称为lambda函数)在最内层循环中完成工作。由于lambda函数需要在Matlab中是单个表达式,我不得不重写内部循环(使用简单的代数操作)。如果您需要将arrayfun
与不易表示为lambda的函数一起使用,则可以始终在单独的.m文件中编写该函数并将其传递给arrayfun
。
编辑:请注意,您不必再预先分配kernel
,也不需要offset
。