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

发布于 2024-11-15 18:06:45 字数 688 浏览 4 评论 0原文

我拼命试图避免 Matlab 中的 for 循环,但我不知道该怎么做。情况是这样的:

我有两个 mx n 矩阵 AB 以及两个向量 vw长度为 d 的。我想要将 Av 进行外乘,以便得到一个 mxnx d 矩阵,其中 (i,j,k)< /code> 条目为 A_(i,j) * v_kBw 也类似。

之后,我想添加生成的 mxnx d 矩阵,然后沿最后一个维度取 mean 以获得 mx n 矩阵。

我很确定我可以处理后一部分,但第一部分让我完全陷入困境。我尝试使用 bsxfun 但没有成功。有人知道有效的方法吗?非常感谢!

编辑:此修订是在以下三个精彩答案之后进行的。毫无疑问,gnovice 对我提出的问题有最好的答案。然而,我想问的问题涉及在取平均值之前对每个条目进行平方。我原来忘记提到这部分了。考虑到这种烦恼,其他两个答案都效果很好,但是在编码之前做代数的聪明技巧这次没有帮助。谢谢大家的帮助!

I'm desperately trying to avoid a for loop in Matlab, but I cannot figure out how to do it. Here's the situation:

I have two m x n matrices A and B and two vectors v and w of length d. I want to outer multiply A and v so that I get an m x n x d matrix where the (i,j,k) entry is A_(i,j) * v_k, and similarly for B and w.

Afterward, I want to add the resulting m x n x d matrices, and then take the mean along the last dimension to get back an m x n matrix.

I'm pretty sure I could handle the latter part, but the first part has me completely stuck. I tried using bsxfun to no avail. Anyone know an efficient way to do this? Thanks very much!

EDIT: This revision comes after the three great answers below. gnovice has the best answer to the question I asked without a doubt. However,the question that I meant to ask involves squaring each entry before taking the mean. I forgot to mention this part originally. Given this annoyance, both of the other answers work well, but the clever trick of doing algebra before coding doesn't help this time. Thanks for the help, everyone!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

白云不回头 2024-11-22 18:06:45

编辑:

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

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

如果您的矩阵和向量很大,则该解决方案将为您提供更好的性能,因为与使用 BSXFUNREPMAT

解释:

假设M是在沿第三维取平均值之前得到的m×n×d矩阵,这就是跨度沿第三维将包含:

M(i,j,:) = A(i,j).*v + B(i,j).*w;

换句话说,按 A(i,j) 缩放的向量 v 加上按 w 缩放的向量 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);

EDIT:

Even though the problem in the question has been updated, an algebraic approach can still be used to simplify matters. You still don't have to bother with 3-D matrices. Your result is just going to be this:

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

If your matrices and vectors are large, this solution will give you much better performance due to the reduced amount of memory required as compared to solutions using BSXFUN or REPMAT.

Explanation:

Assuming M is the m-by-n-by-d matrix that you get as a result before taking the mean along the third dimension, this is what a span along the third dimension will contain:

M(i,j,:) = A(i,j).*v + B(i,j).*w;

In other words, the vector v scaled by A(i,j) plus the vector w scaled by B(i,j). And this is what you get when you apply an element-wise squaring:

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;

Now, when you take the mean across the third dimension, the result for each element output(i,j) will be the following:

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);
深海里的那抹蓝 2024-11-22 18:06:45

尝试将向量 vw 重塑为 1 x 1 x d

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

这里我在reshape 的参数,告诉它根据所有其他维度与向量中元素总数的乘积来填充该维度。

Try reshaping the vectors v and w to be 1 x 1 x d:

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

Here I am using [] in the argument to reshape to tell it to fill that dimension in based on the product of all the other dimensions and the total number of elements in the vector.

划一舟意中人 2024-11-22 18:06:45

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

ETC。

Use repmat to tile the matrix in the third dimension.

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

etc.

奈何桥上唱咆哮 2024-11-22 18:06:45

您仍然不必使用 bsxfun et al 诉诸任何显式循环或间接循环。以满足您的更新要求。您可以通过简单的向量化解决方案来实现您想要的效果,如下所示

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

由于OP仅表示vw是长度为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

You still don't have to resort to any explicit loops or indirect looping using bsxfun et al. for your updated requirements. You can achieve what you want by a simple vectorized solution as follows

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

Since OP only says that v and w are vectors of length d, the above solution should work for both row and column vectors. If they are known to be column vectors, v(:) can be replaced by v and likewise for w.


You can check if this matches Lambdageek's answer (modified to square the terms) as follows

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

isequal(output,outputLG)

ans =

     1
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文