【问题标题】:Efficiently compute a 3D matrix of outer products - MATLAB高效计算外积的 3D 矩阵 - MATLAB
【发布时间】:2014-11-10 17:42:46
【问题描述】:

假设我有一个这样的元素矩阵:

A = reshape(1:25, 5, 5)

A =

 1     6    11    16    21
 2     7    12    17    22
 3     8    13    18    23
 4     9    14    19    24
 5    10    15    20    25

我想有效地计算外积的 3D 矩阵,这样输出矩阵的第 ith 切片是第 ith 列的外积A 本身。如果uv 都是列向量,则两个向量uv 之间的外积就是u*v.'

因此,此输出矩阵B 的每个切片的结构应为:

B(:,:,1) = A(:,1) * A(:,1).';
B(:,:,2) = A(:,2) * A(:,2).';
        ...
        ...
B(:,:,5) = A(:,5) * A(:,5).';

我目前的方法如下。我尝试使用arrayfuncell2mat 这样做:

cellmatr = arrayfun(@(x) A(:,x) * A(:,x).', 1:size(A,2), 'uni', 0);
out = reshape(cell2mat(cellmatr), size(A,1), size(A,1), size(A,2));

我只是在1A 中的尽可能多的列之间循环一个线性索引数组,对于这个数组中的每个元素,我访问相应的列并计算外积。因此,输出将给出一个 1D 单元格网格,然后我将其转换回 2D 矩阵,然后重新整形为 3D 矩阵以找到外积的 3D 矩阵。

但是,对于大型矩阵,这非常慢。我还尝试在我的arrayfun 调用中用kron(即kron(A(:,x), A(:,x)))替换矩阵乘积,但这对于我的目的来说仍然很慢。


有谁知道以这种方式计算这个外部产品的 3D 矩阵的有效方法?

【问题讨论】:

  • @natan - 我没有,但感谢 FEX 的链接!
  • 我想知道这与 Divakar 的回答相比效率如何......
  • @natan - 我会从 FEX 下载那个库,我会告诉你的。现在我正在寻找一个纯粹基于 MATLAB 的解决方案。
  • @natan - 我将如何使用该库来计算 3D 外积还不太清楚。你有什么建议吗?

标签: matlab matrix vectorization


【解决方案1】:

这个-

B = permute(bsxfun(@times,A,permute(A,[3 2 1])),[1 3 2])

【讨论】:

  • 我总是与permute 斗争,所以我不得不一次一个地分解每个语句,看看每一步发生了什么。我明白现在发生了什么,我希望我能自己弄清楚!无论哪种方式,我认为这是一个很好的问题:)
  • 这似乎有点快,因为它用 2D 阵列置换替换了 3D 阵列置换:B = bsxfun(@times,permute(A,[1 3 2]),permute(A,[3 1 2]));
  • @LuisMendo - 您在解决方案中的调整实际上击败了for 循环。
【解决方案2】:

显而易见,您是否尝试过简单的 for 循环:

[m,n] = size(A);
B = zeros(m,m,n);
for i=1:n
    B(:,:,i) = A(:,i) * A(:,i).';
end

您会惊讶于它的竞争速度之快。

【讨论】:

  • 我没有考虑使用for 循环,因为我认为它实际上不会起作用。我刚刚进行了一些测试,这实际上比permute / bsxfun 稍快。干得好阿姆罗。
  • +1 amro,有时明显的需要也提一下。我也更喜欢这个而不是 bsxfun,更具可读性......
  • 这也是一个很好的解决方案! +1 BTW 预分配 B(m,m,n) = 0; 也可以考虑。
  • @natan - 我同意。我应该先尝试for 循环,哈哈。特别是因为循环内的计算很简单。
【解决方案3】:

这只是对Divakar's answer 的一个小改进。它更快一点,因为它用 2D 数组置换替换了 3D 数组置换:

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

【讨论】:

  • 只是对时间的评论 - 当我将它放入我的整体算法时,每个解决方案完成算法所需的时间如下,3125 x 3125 矩阵:Divakar:0.403 秒,Amro :0.304 秒,路易斯·门多:0.284 秒。我对随机数据进行了 100 次试验,并对时间进行了平均。
  • 刚刚检查以确保。这还将计算两个单独矩阵中向量之间的复杂“对角线”(仅匹配索引)外积集。用conj(B) 替换第二个A 将计算出for k=1:n; C(:,:,k)=A(:,k)*B(:,k)'; end;
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-11-07
  • 2014-07-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多