我有两个向量,比如大小为nx1的A
和大小为1xm的B
。我想从非线性公式创建结果矩阵C
(nxm),以便
C(i,j) = A(i)/(A(i)+B(j)).
我知道我可以通过循环执行此操作,例如:
for i=1:n,
C(i,1:m)=A(i)./(A(i)+B(1:m));
end
但是可以通过某种方式在不使用循环的情况下完成此操作吗?
编辑:谢谢你的回答!作为一个小小的补充,在我看到它们之前,一位朋友提出了以下解决方案:C = A*ones(1,m)./(ones(n,1)*B+A*ones(1,m))
答案 0 :(得分:6)
如果您使用的是MATLAB R2016a或更早版本,那么您将希望使用bsxfun
来完成此任务
result = bsxfun(@rdivide, A, bsxfun(@plus, A, B));
如果您使用的是R2016b或更新版本,则会有隐式扩展,允许您删除bsxfun
并直接应用元素运算符
result = A ./ (A + B);
<强>基准强>
以下是使用timeit
比较使用bsxfun
,repmat
,隐式广播和for
循环的执行速度的真实基准。从结果中可以看出,bsxfun
和隐式广播方法产生的执行时间最快。
function comparision()
sz = round(linspace(10, 5000, 30));
times1 = nan(size(sz));
times2 = nan(size(sz));
times3 = nan(size(sz));
times4 = nan(size(sz));
for k = 1:numel(sz)
A = rand(sz(k), 1);
B = rand(1, sz(k));
times1(k) = timeit(@()option1(A,B));
A = rand(sz(k), 1);
B = rand(1, sz(k));
times2(k) = timeit(@()option2(A,B));
A = rand(sz(k), 1);
B = rand(1, sz(k));
times3(k) = timeit(@()option3(A,B));
A = rand(sz(k), 1);
B = rand(1, sz(k));
times4(k) = timeit(@()option4(A,B));
end
figure
p(1) = plot(sz, times1 * 1000, 'DisplayName', 'bsxfun');
hold on
p(2) = plot(sz, times2 * 1000, 'DisplayName', 'repmat');
p(3) = plot(sz, times3 * 1000, 'DisplayName', 'implicit');
p(4) = plot(sz, times4 * 1000, 'DisplayName', 'for loop');
ylabel('Execution time (ms)')
xlabel('Elements in A')
legend(p)
end
function C = option1(A,B)
C = bsxfun(@rdivide, A, bsxfun(@plus, A, B));
end
function C = option2(A,B)
m = numel(B);
n = numel(A);
C = repmat(A,1,m) ./ (repmat(A,1,m) + repmat(B,n,1));
end
function C = option3(A, B)
C = A ./ (A + B);
end
function C = option4(A, B)
m = numel(B);
n = numel(A);
C = zeros(n, m);
for i=1:n,
C(i,1:m)=A(i)./(A(i)+B(1:m));
end
end
有关隐式扩展和bsxfun
的比较详情,请参阅此answer。
答案 1 :(得分:1)
如Suever所提到的,如果你有2016b或更新的话,隐式扩展就是你要走的路。没有这个的另一种方法是在使用repmat
使A和B与C相同之后进行逐元素操作...
A1 = repmat(A,1,m);
B1 = repmat(B,n,1);
C = A1 ./ (A1 + B1);
或者在一行......
C = repmat(A,1,m) ./ (repmat(A,1,m) + repmat(B,n,1));
作为基准测试,我运行了你的循环方法,上面的repmat
方法,以及bsxfun
的Suever m = 1000, n = 100
方法,每个方法平均超过1,000次运行:
Using for loop 0.00290520 sec
Using repmat 0.00014693 sec
Using bsxfun 0.00016402 sec
因此,对于大型矩阵,repmat
和bsxfun
与repmat
边缘相当。但是对于小矩阵,只需循环就可以比两者都快,特别是使用小n
,这就是你的循环变量!
值得测试特定用例的给定方法,因为时序结果看起来相当可变,具体取决于输入。