可能重复:
如何将行向量添加到列向量,如矩阵乘法
我有一个nx1
向量和一个1xn
向量。我想以一种特殊的方式添加它们,比如以一种有效的方式(向量化)进行矩阵乘法:
例子:
A=[1 2 3]'
B=[4 5 6]
A \odd_add B =
[1+4 1+5 1+6
2+4 2+5 2+6
3+4 3+5 3+6
]
我bsxfun
在MATLAB中使用过,但我认为它很慢。请帮我...
可能重复:
如何将行向量添加到列向量,如矩阵乘法
我有一个nx1
向量和一个1xn
向量。我想以一种特殊的方式添加它们,比如以一种有效的方式(向量化)进行矩阵乘法:
例子:
A=[1 2 3]'
B=[4 5 6]
A \odd_add B =
[1+4 1+5 1+6
2+4 2+5 2+6
3+4 3+5 3+6
]
我bsxfun
在MATLAB中使用过,但我认为它很慢。请帮我...
我对这里提到的不同方法进行了比较。我正在使用TIMEIT函数来获得可靠的估计(负责预热代码、多次运行的平均时间......):
function testBSXFUN(N)
%# data
if nargin < 1
N = 500; %# N = 10, 100, 1000, 10000
end
A = (1:N)';
B = (1:N);
%# functions
f1 = @() funcRepmat(A,B);
f2 = @() funcTonyTrick(A,B);
f3 = @() funcBsxfun(A,B);
%# timeit
t(1) = timeit( f1 );
t(2) = timeit( f2 );
t(3) = timeit( f3 );
%# time results
fprintf('N = %d\n', N);
fprintf('REPMAT: %f, TONY_TRICK: %f, BSXFUN: %f\n', t);
%# validation
v{1} = f1();
v{2} = f2();
v{3} = f3();
assert( isequal(v{:}) )
end
在哪里
function C = funcRepmat(A,B)
N = numel(A);
C = repmat(A,1,N) + repmat(B,N,1);
end
function C = funcTonyTrick(A,B)
N = numel(A);
C = A(:,ones(N,1)) + B(ones(N,1),:);
end
function C = funcBsxfun(A,B)
C = bsxfun(@plus, A, B);
end
时间安排:
>> for N=[10 100 1000 5000], testBSXFUN(N); end
N = 10
REPMAT: 0.000065, TONY_TRICK: 0.000013, BSXFUN: 0.000031
N = 100
REPMAT: 0.000120, TONY_TRICK: 0.000065, BSXFUN: 0.000085
N = 1000
REPMAT: 0.032988, TONY_TRICK: 0.032947, BSXFUN: 0.010185
N = 5000
REPMAT: 0.810218, TONY_TRICK: 0.824297, BSXFUN: 0.258774
BSXFUN 显然是赢家。
正如@b3 所述。这将是一个合适的地方使用repmat
。但是总的来说,特别是如果您正在处理非常大的矩阵,bsxfun
通常是更好的替代品。在这种情况下:
>> bsxfun(@plus, [1,2,3]', [4,5,6])
返回相同的结果,使用大矩阵限制中大约三分之一的内存。
bsxfun
基本上将第一个参数中的函数应用于第二个和第三个参数中的每个项目组合,根据输入向量的形状将结果放置在矩阵中。
在 matlab 矢量化中,与任何其他内置的 Matlab 函数Tony's Trick
相比,在速度方面没有替代品。repmat
我确信以下代码对于您的目的必须是最快的。
>> A = [1 2 3]';
>> B = [4 5 6];
>> AB_sum = A(:,ones(3,1)) + B(ones(3,1),:);
A
对于较大的和,速度差异将更加明显(至少一个数量级)B
。请参阅我前段时间进行的此测试Tony's Trick
,以确定overrepmat
在时间消耗方面的优势。
REPMAT是你的朋友:
>> A = [1 2 3]'; >> B = [4 5 6]; >> AplusB = repmat(A, 1, 3) + repmat(B, 3, 1) 加 B = 5 6 7 6 7 8 7 8 9