【问题标题】:Product of a multi-dimensional array (or tensor) and vectors多维数组(或张量)和向量的乘积
【发布时间】:2017-03-11 10:41:44
【问题描述】:

我想寻求一种快速的方法来执行以下操作,无论是在原生 Matlab、C++ 中,还是使用工具箱/库,都可以提供最快的解决方案。

M为D维的张量:n1 x n2 x... x nD,设v1,v2,...,vDD维数分别为n1,@987654328的向量@,..., nD.

  1. 计算乘积M*vi (1
  2. 计算M 与除vi 之外的所有向量的乘积。

例如,当 D = 3:

  • Mv1 的乘积是一个二维张量N(即矩阵),其中

N[i2][i3] = Sum_over_i1 of M[i1][i2][i3]*v1[i1]

  • Mv2 的乘积是矩阵N 其中

N[i1][i3] = Sum_over_i2 of M[i1][i2][i3]*v2[i2]

  • Mv2v3 的乘积是一个向量 v 其中

v[i1] = Sum_over_i2 of (Sum_over_i3 of M[i1][i2][i3]*v2[i2]*v3[i3])

还有一个问题:以上只是针对稀疏张量。

Matlab 代码示例如下。

非常感谢您的帮助!

n1 = 3;
n2 = 5;
n3 = 4;

M = randn(n1,n2,n3);
v1 = randn(n1,1);
v2 = randn(n2,1);
v3 = randn(n3,1);

%% N = M*v2
N = zeros(n1,n3);
for i1=1:n1
    for i3=1:n3
        for i2=1:n2
            N(i1,i3) = N(i1,i3) + M(i1,i2,i3)*v2(i2);
        end
    end
end

%% v = M*v2*v3
v = zeros(n1,1);
for i1=1:n1
    for i2=1:n2
        for i3=1:n3
            v(i1) = v(i1) + M(i1,i2,i3)*v2(i2)*v3(i3);
        end
    end
end

【问题讨论】:

  • 至少你可以通过只使用N(i1,i3) = M(i1,:,i3)*v2;来简化内部for循环
  • @RobertStettler:谢谢,但我想写一个最明显的例子。 (可能有一种方法可以计算第二种类型的乘积,而无需循环并应用第一种。否则我不会要求两次操作,而只要求第一种。)

标签: c++ arrays matlab multidimensional-array


【解决方案1】:

我注意到您所描述的操作采用 M 的 (D - 1) 个维度切片,并通过 vi 的相应条目对它们进行缩放,随后将结果与 vi 的索引相加。此代码似乎适用于在您的示例中获取 N

N2 = squeeze(sum(M.*(v2)', 2));

要在您的代码中获得v,您只需将N 乘以v3

v2 = N2*v3;

编辑

在较旧版本的 MatLab 上,逐元素运算符 .* 不能像我上面使用的那样工作。一种选择是bsxfun

N2 = squeeze(sum(bsxfun(@times, M, v2'), 2));

刚刚检查:就性能而言,bsxfun 方式似乎与 .* 方式一样快,至少在 R2016b 上是这样。

【讨论】:

  • 谢谢,但我在编译您的代码时收到此错误:“使用错误。* 矩阵尺寸必须一致。”你能查一下吗?
  • 可能是我们使用了不同版本的 MatLab。在我使用这样的代码的版本中:ones(2,3).*[1; 2]ones(2, 3).*[1, 2, 3] 工作正常,但我记得在 R2015 中不是这种情况。要让它工作,您可能必须使用bsxfun,这可能会更慢(请参阅编辑)。
  • 非常感谢,尤里!
猜你喜欢
  • 1970-01-01
  • 2019-01-07
  • 2019-04-21
  • 2013-07-19
  • 1970-01-01
  • 2021-12-22
  • 1970-01-01
  • 1970-01-01
  • 2020-08-23
相关资源
最近更新 更多