transpuesta - ¿Cómo tomar el producto externo de más de dos matrices en una sola toma, en matlab?
longitud de un vector en matlab (3)
En un caso multidimensional (tensor) de y = u⊗v
, creo que debe cambiar las dimensiones del segundo operando de la siguiente manera:
v_t = permute(v, circshift(1:(ndims(u) + ndims(v)), [0, ndims(u)]));
y luego multiplícalos con bsxfun
:
y = bsxfun(@times, u, v_t);
La multiplicación de la matriz regular se define solo para las matrices vector y 2-D, por lo que no podríamos usarla en el caso general.
También tenga en cuenta que este cálculo aún falla si el segundo operando es un vector 1-D, porque ndims
devuelve 2 en lugar de 1 para los vectores. Para este propósito, definamos nuestra propia función que cuenta las dimensiones:
my_ndims = @(x)(isvector(x) + ~isvector(x) * ndims(x));
Para completar la respuesta, puede definir una nueva función ( por ejemplo, una función anónima), de esta manera:
outprod = @(u, v)bsxfun(@times, u, permute(v, circshift(1:(my_ndims(u) + my_ndims(v)), [0, my_ndims(u)])));
y luego úsala tantas veces como quieras. Por ejemplo, y = a×a×a
se computaría así:
y = outprod(outprod(a, a), a);
Por supuesto, puede escribir una función mejor que tome una cantidad variable de argumentos para ahorrarle algo de tipeo. Algo en esta línea:
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
¡Espero tener las matemáticas correctas!
Quiero calcular y = a⊗a⊗a
, donde a
es un vector n-by-1, y ⊗
es el operador externo del producto . En este caso, y
debería ser un tensor n-by-n-by-n.
Si y = a⊗a
, es fácil. Simplemente lo hago:
y = a * a''
¿Pero qué hacer en el primer caso? ¿Cómo puedo calcular este producto externo de manera eficiente en MATLAB si hay más de dos vectores?
Puede usar también la función kron
:
kron(a * a'', a)
o cuando se necesitan cuatro productos externos (tensor de kronecker):
kron(kron(a * a'', a), a)
y así. El último te da una matriz mxn , donde m = n * n * n.
Si desea agregar dimensiones como sucede con los productos, puede usar la función de reshape
:
reshape(kron(a * a'', a), [n, n, n])
o
reshape(kron(kron(a * a'', a), a), [n, n, n, n])
y así. El último te da un tensor nxnxnxn .
El problema con el uso de kron
como en una solución anterior es que descarta la indexación canónica del producto externo.
En cambio, ndgrid
es ideal para este escenario:
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);
En papel, podemos verificar que la solución M
deseada es el cubo de datos:
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
Usando el enfoque del producto Kronecker
M2 = reshape(kron(a * b'', c), [length(a), length(b), length(c)]);
obtendríamos:
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 M2
tiene los mismos elementos que M
, pero estos elementos se reorganizan . Esto se debe a que kron(a * b'', c)
no contiene las porciones de M
en bloques contiguos para facilitar la aplicación directa de la función de reshape
. Para calcular el producto externo de esta manera, necesitaríamos aplicar una operación / función de reordenamiento (determinable, pero labriosa y lenta) a los elementos de kron(a * b'', c)
.
Otra ventaja del uso de ndgrid
es que se generaliza fácilmente a pedidos superiores.