在MATLAB中矩阵数组的乘法

4

我有一个数据集,其中包含两个1800 x 900 x 3 x 3的数组,每个数组都应解释为一个1800 x 900的3 x 3矩阵数组。作为分析的一部分,在某一点上,我需要通过将对应的3 x 3矩阵相乘来在每个1800 x 900矩阵中创建另一个这样的数组。

我认为有两种方法可以实现这个目标。显而易见的方法是:

C = zeros(size(A))
for i = 1:900
    for j = 1:1800
        C(i,j,:,:) = A(i,j,:,:)*B(i,j,:,:)
    end
end

但是这种方法的循环较长,不能充分利用MATLAB的向量化。另一种方法是

C = zeros(size(A))
for i = 1:3
    for j = 1:3
        for k = 1:3
            C(:,:,i,j) = C(:,:,i,j) + A(:,:,i,k).*B(:,:,k,j)
        end
    end
end

当向量的维度很大时,我会使用for循环来实现Einstein求和约定。但这种方法看起来非常不优雅,我认为应该有更好的方式。有吗?

1个回答

4

使用bsxfunpermute进行完美的it技术工作:

C = permute(sum(bsxfun(@times, A, permute(B, [1 2 5 3 4])), 4), [1 2 3 5 4]);

从R2016b开始,由于隐式单例扩展,您可以避免使用bsxfun

C = permute(sum(A .* permute(B, [1 2 5 3 4]), 4), [1 2 3 5 4]);

你可能需要更详细地向我解释那段代码在做什么。我以前没有使用过bsxfun或permute。我想我在第一个示例中忘记了压缩操作,是吗? - eyeballfrog
关于bsxfun,我很难比链接帖子中的解释更好。请阅读它并让我知道您是否有任何问题。在这里使用permute是为了“对齐”维度,以便根据需要进行单例扩展。 - Luis Mendo
@eyeballfrog 是的,你忘了 squeeze。或者更好的方法是使用 permute。在你的情况下并不重要,但如果矩阵是 1x3 而不是 3x3squeeze 函数会将 A(i,j,:,:)(大小为 1x1x 1x4)转换为 4x1,而不是所需的 1x4。因此,请使用 permute(..., [3 4 1 2]) 将第三和第四维度移动到“前面”。 - Luis Mendo
1
哦,所以你要将B的第三维(一个常规的3x3矩阵)旋转90度,找到逐元素乘积,然后相对于A的第四维(另一个常规矩阵)和B的第三维求和。太棒了! - Yvon

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接