多维数组(或张量)和向量的乘积

Product of a multi-dimensional array (or tensor) and vectors

本文关键字:向量 张量 数组      更新时间:2023-10-16

我想问一种快速的方式来执行以下操作,无论是在本机 Matlab、C++ 中还是使用工具箱/库,无论哪种都能提供最快的解决方案。

M是 D 维张量:n1 x n2 x... x nD,设 v1v2 ,..., vD是维数分别为 n1 n2 ,..., nDD向量。

  1. 计算乘积M*vi (1 <= i <= D(。结果是一个 (D-1( 维度的多维数组。
  2. 计算除vi以外的所有向量的M乘积。

例如,D = 3 时:

  • Mv1的乘积是 2 维张量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

我注意到您描述的操作需要 (D - 1( M的维度切片,并通过相应的条目对其进行缩放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));

刚刚检查:就性能而言,至少在R2016b上,bsxfun方法似乎与大型阵列的.*方法一样快。