web-dev-qa-db-ja.com

行列の各行からベクトルを減算する方法は?

可能性のある複製:
マトリックスの各行を固定行で分割するにはどうすればよいですか?

マトリックスの各行から同じベクトルを減算するエレガントな方法を探しています。エレガントな方法ではありません。

a = [1 2 3];
b = Rand(7,3);
c(:,1) = b(:,1) - a(1);
c(:,2) = b(:,2) - a(2);
c(:,3) = b(:,3) - a(3);

また、エレガントな方法はこの方法より遅くなることはありません。

私はもう試した

c = b-repmat(a,size(b,1),1); 

そしてそれは遅いようです。

編集:勝者はこの方法です。

c(:,1) = b(:,1) - a(1);
c(:,2) = b(:,2) - a(2);
c(:,3) = b(:,3) - a(3);

編集:他のメソッド、およびチック目次の結果:

n = 1e6;
m = 3;
iter = 100;
a = Rand(1,m);
b = Rand(n,m);

tic
c = zeros(size(b));
for i = 1:iter
    c(:,1) = b(:,1) - a(1);
    c(:,2) = b(:,2) - a(2);
    c(:,3) = b(:,3) - a(3);
end
toc

tic
c = zeros(size(b));
for i = 1:iter
    c(:,1) = b(:,1) - a(1);
    c(:,2) = b(:,2) - a(2);
    c(:,3) = b(:,3) - a(3);
end
toc

tic
c = zeros(size(b));
for i = 1:iter
    for j = 1:3
        c(:,j) = b(:,j) - a(j);
    end
end
toc

tic
for i = 1:iter
    c = b-repmat(a,size(b,1),1);
end
toc

tic
for i = 1:iter
    c = bsxfun(@minus,b,a);
end
toc

tic
c = zeros(size(b));
for i = 1:iter
    for j = 1:size(b,1)
        c(j,:) = b(j,:) - a;
    end
end
toc

結果

Elapsed time is 0.622730 seconds.
Elapsed time is 0.627321 seconds.
Elapsed time is 0.713384 seconds.
Elapsed time is 2.621642 seconds.
Elapsed time is 1.323490 seconds.
Elapsed time is 17.269901 seconds.
26
Miebster

これが私の貢献です。

c = b - ones(size(b))*diag(a)

次に、テストを高速化します。

tic
for i = 1:10000
    c = zeros(size(b));
    b = Rand(7,3);
    c = b - ones(size(b))*diag(a);
end
toc

結果:

Elapsed time is 0.099979 seconds.

それほど高速ではありませんが、きれいです。

6
MudPhud

明らかな答えは3つしかありませんが、質問では2つを答えました。

3番目は行ごとです。

c(1,:) = b(1,:) - a; %...

しかし、メモリ順序が異なる要素にアクセスするため、大きな行列の列ごとの処理よりも遅くなると予想されます。

列ごとの処理を* .mファイルまたはサブ関数でforループに変換しても、repmatバージョンよりも高速ですか?

速度をテストするもう1つのこと:cを事前に割り当ててみてください。

c = zeros(size(b));
c(:,1) = b(:,1) - a(1); %...
1
aschepler