在Matlab中创建和操作三维矩阵

在Matlab中创建和操作三维矩阵,matlab,matrix-multiplication,bsxfun,Matlab,Matrix Multiplication,Bsxfun,我拼命地想避免Matlab中的for循环,但我不知道怎么做。情况如下: 我有两个mn矩阵A和B和两个长度d的向量v和w。我想把A和v相乘,得到一个mxnxd矩阵,其中(I,j,k)条目是A(I,j)*v_k,同样的B和w 之后,我想添加得到的mxnxd矩阵,然后沿着最后一个维度取平均值,得到mxn矩阵 我很确定我能处理好后一部分,但第一部分让我完全卡住了。我尝试使用bsxfun,但没有效果。有人知道这样做的有效方法吗?非常感谢 编辑:本次修订是在以下三个重要答案之后进行的。毫无疑问,gnovic

我拼命地想避免Matlab中的
for
循环,但我不知道怎么做。情况如下:

我有两个
mn
矩阵
A
B
和两个长度
d
的向量
v
w
。我想把
A
v
相乘,得到一个
mxnxd
矩阵,其中
(I,j,k)
条目是
A(I,j)*v_k
,同样的
B
w

之后,我想添加得到的
mxnxd
矩阵,然后沿着最后一个维度取
平均值
,得到
mxn
矩阵

我很确定我能处理好后一部分,但第一部分让我完全卡住了。我尝试使用
bsxfun
,但没有效果。有人知道这样做的有效方法吗?非常感谢

编辑:本次修订是在以下三个重要答案之后进行的。毫无疑问,gnovice是我所问问题的最佳答案。然而,我想问的问题是,在取平均值之前,要对每个条目进行平方运算。我原来忘了提到这一部分。考虑到这一点,其他两个答案都很有效,但在编码之前先做代数的巧妙技巧这次没有帮助。谢谢大家的帮助

编辑:

即使问题中的问题已经更新,代数方法仍然可以用来简化问题。你仍然不必为三维矩阵而烦恼。您的结果将是:

output = mean(v.^2).*A.^2 + 2.*mean(v.*w).*A.*B + mean(w.^2).*B.^2;
如果矩阵和向量较大,由于与使用or的解决方案相比所需的内存量减少,因此此解决方案将为您提供更好的性能


说明:

假设
M
是在沿三维取平均值之前得到的M-by-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;
现在,当你取第三维的平均值时,每个元素
输出(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)

在这里,我使用
[]
进行整形的参数告诉它根据所有其他维度与向量中元素总数的乘积填充该维度。

使用
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


您可以按如下方式检查此项是否匹配(修改为将项平方)

outputLG = mean ((bsxfun(@times, A, reshape(v, 1, 1, [])) ...
        + bsxfun(@times, B, reshape(w, 1, 1, []))).^2, 3);

isequal(output,outputLG)

ans =

     1

@gnovice:我认为OP希望首先添加结果矩阵,然后取平均值。所以,独立地取每个向量的平均值并不能做到这一点。@Lambdageek:实际上,在这种情况下是这样的。上面的代码给出的结果与答案中更复杂的步骤集相同。我要补充一个解释。@gnovice,嗯。是的,你说得对。由于A和B基本上是作为标量参与的,因此您的断言只需考虑
sum
,而不是
mean
。将删除我的答案。最好用代数方法来做这个。@gnovice:谢谢。我是如此专注于我做不到的那一步,以至于我没有想到要把代数学习到底。很好。@gnovice:很遗憾,但我遗漏了一点,那就是在取不可转换的平均值之前,我必须再做一次运算,所以我需要知道如何进行矩阵转换。尽管如此,这仍然是一个很好的答案,但我接受了
repmat
解决方案。这更快,更干净。在取平均值之前,我需要对每个条目进行平方运算,这种方法使我能够轻松地完成这项工作。非常感谢@PengOne:我假设
v
w
是列向量(因为您只提到它的长度
d
)。因此,也许您有行向量,在这种情况下,请尝试
v(:)*A(:)'
和类似的
w
。我将编辑我的答案以包含这些内容。@yoda:transposing
v
成功了。这同样有效。谢谢@彭根:没问题:)只是出于好奇,你的矩阵和向量的大小是多少?@yoda大约是10K乘10K,虽然不是正方形。理想情况下,它们应该是1米乘1米(同样,不完全是正方形),但for循环太慢,即使是10公里。不过,这应该会加快速度。@PengOne:1M乘1M??那太疯狂了。
d
的大小是多少?