重複の可能性:
行列の乗算のように行ベクトルを列ベクトルに追加する方法
私は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
]
MATLABで使っbsxfun
たことありますが遅いと思います。私を助けてください...
重複の可能性:
行列の乗算のように行ベクトルを列ベクトルに追加する方法
私は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
]
MATLABで使っbsxfun
たことありますが遅いと思います。私を助けてください...
ここで紹介したさまざまな方法の比較を紹介します。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])
は同じ結果を返しますが、大きな行列の制限で約 3 分の 1 のメモリを使用します。
bsxfun
基本的に、最初の引数の関数を 2 番目と 3 番目の引数のアイテムのすべての組み合わせに適用し、結果を入力ベクトルの形状に従って行列に配置します。
Matlab のベクトル化では、Matlab に組み込まれている他の関数Tony's Trick
と比較して、速度の点で代替手段はありません。repmat
次のコードは、あなたの目的にとって最速でなければならないと確信しています。
>> A = [1 2 3]';
>> B = [4 5 6];
>> AB_sum = A(:,ones(3,1)) + B(ones(3,1),:);
と のサイズが大きいほど、速度差は (少なくとも 1 桁は) より明白にA
なりB
ます。少し前に行ったこのテストを参照して、時間消費の観点からTony's Trick
overの優位性を確認してください。repmat
REPMATはあなたの友達です:
>> A = [1 2 3]'; >> B = [4 5 6]; >> AplusB = repmat(A, 1, 3) + repmat(B, 3, 1) AplusB = 5 6 7 6 7 8 7 8 9