我想在2个矩阵上对以下操作进行矢量化。
A是“k×m”矩阵,B是“n×m”矩阵。我定义了一个函数F(a,B),它对A的行“a”和整个矩阵B进行操作.F的输出是“1 x n”行向量。
我想将F(a,B)应用于A的每一行,并堆叠k“1 x n”结果行向量以形成最终的“k x n”矩阵。使用for循环时,此操作为:
result = [];
for i = 1:k
result = [result ; F(A(i,:),B)];
endfor
有没有人知道如何在此操作中消除for循环?我可以使用类似“bsxfun”Octave内置函数的东西吗?
作为Octave的新人,如果我错过了一些明显的方法来执行此类操作,我很抱歉。
感谢您的任何建议。
编辑: 事实上,B可以被封装。我可以定义函数f(a),它在A的“1×m”行“a”上操作,使得f的输出是“1×n”行向量。然后,当使用for循环时,我的操作将变为:
result = zeros(k,n);
for i = 1:k
result(i,:) = f(A(i,:));
endfor
我需要一次操作整行A(i,:),因为函数f需要A(i,:)中的整个信息来生成输出行向量。
因为m,n可能很大(几万或更多),我正在寻找方法来消除简单的for循环,试图让程序运行得更快。
我想知道Octave是否有一些内置函数用于矢量化我的这种情况。
答案 0 :(得分:2)
使用ndpar
包http://wiki.octave.org/NDpar_package,
你可以直接实现这个目标
pkg load ndpar
k = 3;
m = 2;
A = rand(k, m);
B = rand(m, k);
F = @(a, B) a * B;
result_ndpar = ndpar_arrayfun(nproc, F, A, B, "IdxDimensions", [1, 0], "CatDimensions", [1])
"IdxDimensions"
选项[1, 0]
表示第一个参数A
应沿第一个方向切片(并行化),第二个参数B
不应切片(因此通过"按原样#34;)
"CatDimensions"
选项[1]
表示输出值应沿第一个方向连接。
答案 1 :(得分:1)
我认为F(a,B)类似于:
function F(a, B)
for i=1:size(B,1)
result = f(a,B(i,:));
end
所以我将从这里开始,并在每个相应的行上应用f(a,b):
A = repmat (A, [n 1]);
B = repmat (B, [k 1]); %(kxn) x m matrix
答案 2 :(得分:1)
首先,您应该检查for
循环是否花费了相当多的时间,然后花费太多精力来删除它。您的主要问题是您在每次迭代时重新分配内存。 Matlab的编辑会警告你 - 我不确定Octave。对于小型阵列来说这不是什么大问题,但对于较大的阵列,重新分配很多次都会很昂贵。您只需要预先分配:
result = zeros(k,n);
for i = 1:k
result(k,:) = F(A(i,:),B);
end
或者你可以改变索引的方向而不用打电话给zeros
(小心这种技巧):
for i = k:-1:1
result(k,:) = F(A(i,:),B);
end
要回答您的问题,bsxfun
不能用于此类事情。它用于元素操作。如果您重新编写F
函数(或者您可以通过矩阵数学运算完成所有操作),则可以使用它。如果你只是想摆脱循环以摆脱它,你可能会看arrayfun
。但是,arrayfun
只是伪装的for
循环,并且通常比显式写循环慢。
答案 3 :(得分:1)
经过一些研究,我最终可以使用“mat2cell”,“cellfun”和“cell2mat”来对我的代码进行矢量化。 想法是将A的每一行转换为单元格C的单元格条目,然后将f(a)应用于C的每个单元格条目,最后将得到的单元格转换回矩阵。代码是:
C = mat2cell(A, ones(1,size(A,1)));
f = @(a) F(a,B);
result_cell = cellfun(f, C, "UniformOutput", false);
result = cell2mat(result_cell);
然而,这个矢量化代码的运行时间似乎与原始的“for循环”实现几乎相同。似乎一级“for循环”效率不是很低,或者只有当k很大时(即A有很多行)才会产生差异。此外,内置的“cellfun”可能不如其帮助状态那么有效:
`cellfun'函数是避免循环的有用工具。它通常与匿名函数句柄一起使用;但是,调用匿名函数涉及的开销与m文件函数的开销相当。将句柄传递给内置函数更快,因为解释器不参与内部循环。
希望我的答案也能为其他人提供一个很好的参考。