如何在Matlab中一次性对多个矩阵进行外积操作?

10
我想计算 y = a⊗a⊗a,其中 a 是一个 n 行 1 列的向量,外积运算符。在这种情况下,y 应该是一个 n 行 n 列 n 深度的张量。
如果 y = a⊗a,那么很容易。我只需要这样做:
y = a * a' 

但是第一种情况该怎么办呢?如果有两个以上的向量,我该如何在MATLAB中高效地计算这个外积?

我不明白你想要计算什么。是 y = a x a x a 吗?如果是,当其中一个操作数是矩阵时,外积如何定义? - Eitan T
是的,我想计算 y = a x a x a。或者更高阶的,比如 y = a x a x a x a x a。 - Cem S.
3个回答

7
在多维(张量)情况下的 y = u⊗v,我认为您需要移动第二个操作数的维度,如下所示:
v_t = permute(v, circshift(1:(ndims(u) + ndims(v)), [0, ndims(u)]));

然后使用bsxfun函数对它们进行乘法运算:

y = bsxfun(@times, u, v_t);

常规矩阵乘法仅适用于向量和二维矩阵,因此我们无法在一般情况下使用它。

还要注意,如果第二个操作数是一维向量,则此计算仍将失败,因为 ndims 返回2而不是1。 为此,让我们定义一个自己的函数来计算维度:

my_ndims = @(x)(isvector(x) + ~isvector(x) * ndims(x));

为了完整回答问题,您可以定义一个新的函数(例如匿名函数),如下所示:

outprod = @(u, v)bsxfun(@times, u, permute(v, circshift(1:(my_ndims(u) + my_ndims(v)), [0, my_ndims(u)])));

然后你可以随心所欲地使用它。例如,y = a×a×a 可以这样计算:

y = outprod(outprod(a, a), a);

当然,您可以编写一个更好的函数,以接受可变数量的参数,以便节省输入。可以按照以下方式编写该函数:
function y = outprod(u, varargin)
    my_ndims = @(x)(isvector(x) + ~isvector(x) * ndims(x));
    y = u;
    for k = 1:numel(varargin)
        v = varargin{k};
        v_t = permute(v, circshift(1:(my_ndims(y) + my_ndims(v)),[0, my_ndims(y)]));
        y = bsxfun(@times, y, v_t);
    end

我希望我的计算没错!


3
您可以使用kron函数:
kron(a * a', a)

或者当需要四个外部(Kronecker张量)积时:

kron(kron(a * a', a), a)

等等。最后一个给出了一个 m x n 矩阵,其中 m = n * n * n。

如果希望随着乘积的进行添加维度,则可以使用 reshape 函数:

reshape(kron(a * a', a), [n, n, n])

或者

reshape(kron(kron(a * a', a), a), [n, n, n, n])

等等。最后一个给你一个n x n x n x n张量。


3
使用kron,如先前的解决方案所示存在问题,会打乱外积的规范索引。
相反,ndgrid是这种情况下的理想选择:
a = [1; 2; 3];
b = [4; 5];
c = [6; 7; 8; 9];

[xx, yy, zz] = ndgrid(1:length(a), 1:length(b), 1:length(c));

% desired outerproduct
M = a(xx) .* b(yy) .* c(zz);

在纸面上,我们可以确认所需的解决方案 M 是数据立方体:

M(:,:,1) = | M(:,:,2) = | M(:,:,3) = | M(:,:,4) = 
           |            |            |
24    30   | 28    35   | 32    40   | 36    45
48    60   | 56    70   | 64    80   | 72    90
72    90   | 84   105   | 96   120   | 108   135

使用Kronecker乘积方法
M2 = reshape(kron(a * b', c), [length(a), length(b), length(c)]);

我们将得到:

M2(:,:,1) = | M2(:,:,2) = | M2(:,:,3) = | M2(:,:,4) = 
            |             |             |
24    36    | 64    84    | 30    45    | 80   105
28    48    | 72    96    | 35    60    | 90   120
32    56    | 72   108    | 40    70    | 90   135

Datacube M2M 具有相同的元素,但这些元素被重新排列。这是因为kron(a * b', c)不包含M的切片,以便直接应用reshape函数。要以这种方式计算外积,我们需要对kron(a * b', c)的元素进行一次重新排列操作/函数(可确定,但费时且繁琐)。

使用ndgrid的另一个优点是它很容易推广到更高的阶数。


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