假设我有两个向量:
A = [1 2 3];
B = [10;20;30];
它们也可能是两个向量 - 无所谓,我会选择最好的东西。我现在想要通过将B与A:
的每个元素相乘来创建线矢量 C = [1*10;1*20;1*30;2*20;2*20;2*30;3*10;3*20;3*30];
通过使用张量积B*A
并将其重新整形为线矢量,可以轻松高效地完成此操作。但是有更快的方法吗?这发生在拟合函数中,因此可以传递其他向量,如索引数组。
答案 0 :(得分:4)
我第五次回答过去两天的kron
:
kron(A',B)
10
20
30
20
40
60
30
60
90
时间比较:
C = B*A;
C = C(:);
给出以下结果:
t1 = 0.21601 % kron
t2 = 0.56776 % C = B*A
我刚刚离开了我的MATLAB计算机,因此获得了这些结果here:
A = rand(1,4000);
B = rand(4000,1);
tic
for ii = 1:10
D = kron(A',B);
end
t1 = toc
tic
for ii = 1:10
D2 = B*A;
D2 = D2(:);
end
t2 = toc
tic
for ii = 1:10
D3 = bsxfun(@times, A,B);
D3 = D3(:);
end
t3 = toc
sum(sum(abs(D-D2))) < 1e-10
sum(sum(abs(D-D3))) < 1e-10
t1 = 0.43138
t2 = 0.85762
t3 = 0.43332
ans = 1
ans = 1
答案 1 :(得分:4)
我很惊讶没有人想到过这个:
C = bsxfun(@times, A,B);
C = C(:);
小比较(Win 7 64位,MATLAB R2010a 64位):
A = rand(1,1000);
B = rand(1000,1);
tic
D = kron(A.',B);
toc
tic
D2 = B*A;
D2 = D2(:);
toc
tic
D3 = bsxfun(@times, A,B);
D3 = D3(:);
toc
isequal(D,D2)
isequal(D,D3)
结果:
Elapsed time is 0.123301 seconds. %// kron
Elapsed time is 0.034271 seconds. %// B*A
Elapsed time is 0.010617 seconds. %// bsxfun
ans =
1
ans =
1
A = rand(1,5000); B = rand(5000,1);
的结果:
Elapsed time is 7.134506 seconds. %// kron
Elapsed time is 0.119705 seconds. %// B*A
Elapsed time is 0.162295 seconds. %// bsxfun
kron
下面的算法似乎是O(N²)或更差......
答案 2 :(得分:1)
实际上我怀疑在这种情况下是否可以有显着的改进,因为已知矩阵乘法是Matlab的强度而扁平化数组是微不足道的,这就是我得出的结论,使用kron将无济于事:
A = [1 2 3];
B = [10;20;30];
tic,C = B*A;C = C(:);toc % Typically takes about 0.000012 seconds
tic, C=kron(A',B);toc % Typically takes about 0.000093 seconds
当然,对于不同的输入大小,这可能会有所改变,但这是我从问题中得到的结果。
我认为matlab版本并不重要,但它在2012b上进行了测试。 它用12个核心进行了测试。当在循环中使用两种解决方案时,似乎每种情况下都使用了6个核心,因此我认为这也不是“问题”。