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

时间:2011-06-15 18:46:56

标签: matlab matrix-multiplication bsxfun

我拼命想避免在Matlab中使用for循环,但我无法弄清楚如何做到这一点。情况如下:

我有两个m x n矩阵AB以及两个长度为v的{​​{1}}和w个向量。我希望外部乘以dA,以便我得到一个v矩阵,其中m x n x d条目为(i,j,k),类似于A_(i,j) * v_kB

之后,我想添加生成的w矩阵,然后沿最后一维获取m x n x d以获取mean矩阵。

我很确定我可以处理后一部分,但第一部分让我完全陷入困境。我尝试使用m x n无济于事。有人知道这样做的有效方法吗?非常感谢!

编辑:此修订版位于以下三个最佳答案之后。毫无疑问,gnovice对我提出的问题有最好的答案。但是,我打算提出的问题涉及在取平均值之前对每个条目进行平方。我最初忘了提这个部分。鉴于这种烦恼,其他两个答案都运作良好,但在编码之前进行代数的聪明伎俩并没有帮助。感谢大家的帮助!

4 个答案:

答案 0 :(得分:7)

修改

即使问题中的问题已经更新,仍然可以使用代数方法来简化问题。您仍然不必费心使用3-D矩阵。你的结果就是这样:

output = mean(v.^2).*A.^2 + 2.*mean(v.*w).*A.*B + mean(w.^2).*B.^2;

如果您的矩阵和向量很大,与使用BSXFUNREPMAT的解决方案相比,此解决方案可以提供更好的性能,因为所需的内存量会减少。


说明:

假设M是在沿着第三维度取平均值之前得到的m-by-by-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);

答案 1 :(得分:1)

尝试将向量vw重新整形为1 x 1 x d

  mean (bsxfun(@times, A, reshape(v, 1, 1, [])) ...
        + bsxfun(@times, B, reshape(w, 1, 1, [])), 3)

我在[]的参数中使用reshape告诉它根据所有其他维度的乘积和向量中元素的总数来填充该维度。

答案 2 :(得分:1)

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

答案 3 :(得分:1)

您仍然不必使用bsxfun 来使用任何显式循环或间接循环。为了您的更新要求。您可以通过简单的矢量化解决方案实现您想要的目标,如下所示

output = reshape(mean((v(:)*A(:)'+w(:)*B(:)').^2),size(A));

由于OP仅表示vw是长度为d的向量,因此上述解决方案应适用于行和列向量。如果知道它们是列向量,v(:)可以替换为vw也可以替换。{/ p>


您可以检查这是否与Lambdageek's answer匹配(修改为方括号),如下所示

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

isequal(output,outputLG)

ans =

     1