我拼命避免 Matlab 中的for
循环,但我不知道该怎么做。情况如下:
我有两个m x n
矩阵A
和B
以及两个向量v
和长度d
w
。我想将A
和v
进行外部乘法,以便得到一个m x n x d
矩阵,其中(i,j,k)
条目A_(i,j) * v_k
,B
和w
也是如此。
之后,我想添加生成的m x n x d
矩阵,然后沿最后一个维度取mean
以获得m x n
矩阵。
我很确定我可以处理后一部分,但第一部分让我完全卡住了。我尝试使用bsxfun
但无济于事。有人知道有效的方法来做到这一点吗?非常感谢!
编辑:此修订是在以下三个伟大答案之后进行的。 毫无疑问,gnovice对我提出的问题有最好的答案。但是,我想问的问题涉及在取平均值之前对每个条目进行平方。我最初忘了提到这部分。鉴于这种烦恼,其他两个答案都很好用,但是在编码之前做代数的聪明技巧这次无济于事。谢谢大家的帮助!
编辑:
即使问题中的问题已经更新,代数方法仍然可以用来简化问题。您仍然不必为3-D矩阵而烦恼。你的结果将是这样的:
output = mean(v.^2).*A.^2 + 2.*mean(v.*w).*A.*B + mean(w.^2).*B.^2;
如果您的矩阵和向量很大,则与使用 BSXFUN 或 REMMAT 的解决方案相比,由于所需的内存量减少,此解决方案将为您提供更好的性能。
解释:
假设M
是您在沿第三维取平均值之前得到的结果 m x-n-by-d 矩阵,这就是沿第三维的跨度将包含的内容:
M(i,j,:) = A(i,j).*v + B(i,j).*w;
换句话说,向量v
按 A(i,j)
缩放加上向量w
按 B(i,j)
缩放。这就是应用逐元素平方时得到的结果:
M(i,j,:).^2 = (A(i,j).*v + B(i,j).*w).^2;
= (A(i,j).*v).^2 + ...
2.*A(i,j).*B(i,j).*v.*w + ...
(B(i,j).*w).^2;
现在,当您跨第三维获取平均值时,每个元素output(i,j)
的结果将如下所示:
output(i,j) = mean(M(i,j,:).^2);
= mean((A(i,j).*v).^2 + ...
2.*A(i,j).*B(i,j).*v.*w + ...
(B(i,j).*w).^2);
= sum((A(i,j).*v).^2 + ...
2.*A(i,j).*B(i,j).*v.*w + ...
(B(i,j).*w).^2)/d;
= sum((A(i,j).*v).^2)/d + ...
sum(2.*A(i,j).*B(i,j).*v.*w)/d + ...
sum((B(i,j).*w).^2)/d;
= A(i,j).^2.*mean(v.^2) + ...
2.*A(i,j).*B(i,j).*mean(v.*w) + ...
B(i,j).^2.*mean(w.^2);
尝试重塑向量v
并w
1 x 1 x d
:
mean (bsxfun(@times, A, reshape(v, 1, 1, [])) ...
+ bsxfun(@times, B, reshape(w, 1, 1, [])), 3)
在这里,我在参数中使用[]
来reshape
告诉它根据所有其他维度的乘积和向量中元素的总数填充该维度。
使用 repmat
在第三维中平铺矩阵。
A =
1 2 3
4 5 6
>> repmat(A, [1 1 10])
ans(:,:,1) =
1 2 3
4 5 6
ans(:,:,2) =
1 2 3
4 5 6
等。
您仍然不必使用 bsxfun
等人诉诸任何显式循环或间接循环来满足更新的要求。您可以通过简单的矢量化解决方案实现所需的目标,如下所示
output = reshape(mean((v(:)*A(:)'+w(:)*B(:)').^2),size(A));
由于OP只说v
和w
是长度d
的向量,所以上面的解决方案应该适用于行向量和列向量。如果已知它们是列向量,则可以将v(:)
替换为 v
和 w
。
您可以检查这是否与 Lambdageek 的答案匹配(修改为平方项(,如下所示
outputLG = mean ((bsxfun(@times, A, reshape(v, 1, 1, [])) ...
+ bsxfun(@times, B, reshape(w, 1, 1, []))).^2, 3);
isequal(output,outputLG)
ans =
1