matlab numpy

matlab - ¿Cómo pueden conservarse todas las dimensiones que quedan después de la especificada, sin enumerarlas explícitamente?



numpy (2)

Enfoque 1: usar una lista separada por comas con '':''

No conozco una manera de especificar

: tantas veces como sea necesario

conservando la forma. Pero puedes especificar

: un número arbitrario de veces

donde ese número de veces se define en tiempo de ejecución . Con este método puede conservar la forma, siempre que el número de índices coincida con el número de dimensiones.

Esto se hace usando una lista separada por comas generada a partir de una matriz de celdas y aprovechando el hecho de que la cadena '':'' se puede usar como un índice en lugar de :

function y = fun(x) colons = repmat({'':''}, 1, ndims(x)-1); % row cell array containing the string '':'' % repeated the required number of times y = x(1,colons{:}).*x(2,colons{:}) + x(3,colons{:});

Este enfoque se puede generalizar fácilmente para indexar a lo largo de cualquier dimensión , no solo la primera:

function y = fun(x, dim) % Input argument dim is the dimension along which to index colons_pre = repmat({'':''}, 1, dim-1); colons_post = repmat({'':''}, 1, ndims(x)-dim); y = x(colons_pre{:}, 1, colons_post{:}) ... .*x(colons_pre{:}, 2, colons_post{:}) ... + x(colons_pre{:}, 3, colons_post{:});

Enfoque 2: dividir la matriz

Puede dividir la matriz a lo largo de la primera dimensión usando num2cell , y luego aplicar la operación a las subarrays resultantes. Por supuesto esto usa más memoria; y como lo señaló @Adriaan es más lento.

function y = fun(x) xs = num2cell(x, [2:ndims(x)]); % x split along the first dimension y = xs{1}.*xs{2} + xs{3};

O, para indexar a lo largo de cualquier dimensión :

function y = fun(x, dim) xs = num2cell(x, [1:dim-1 dim+1:ndims(x)]); % x split along dimension dim y = xs{1}.*xs{2} + xs{3};

O, de manera equivalente, "cuál es el equivalente de los índices de puntos suspensivos de NumPy en Matlab"

Digamos que tengo una matriz de alta dimensión:

x = zeros(3, 4, 5, 6);

Quiero escribir una función que tome una matriz de tamaño (3, ...) y realice algunos cálculos. En NumPy, podría escribir esto:

def fun(x): return x[0]*x[1] + x[2]

Sin embargo, el equivalente en MATLAB no funciona, porque la indexación con un entero alisa la matriz a 1d

function y = fun_bad(x) y = x(1)*x(2) + x(3)

Puedo hacer este trabajo para arreglos de hasta 3 dimensiones con

function y = fun_ok3d(x) y = x(1,:,:)*x(2,:,:) + x(3,:,:)

Si quiero que esto funcione para arrays de hasta 10 dimensiones, puedo escribir

function y = fun_ok10d(x) y = x(1,:,:,:,:,:,:,:,:,:)*x(2,:,:,:,:,:,:,:,:,:) + x(3,:,:,:,:,:,:,:,:,:)

¿Cómo puedo evitar escribir números estúpidos de dos puntos aquí y hacer que esto funcione para cualquier dimensión? ¿Hay alguna sintaxis x(1,...) que implique esto?

NumPy puede usar el literal ... ( Ellipsis ) en una expresión de indexación para significar " : tantas veces como sea necesario" , lo que resolvería este problema.


MATLAB aplana todas las dimensiones finales cuando se usa un solo punto, de modo que puede usar eso para obtener de su matriz N- D a una matriz 2D, que puede volver a reshape en las dimensiones N originales después del cálculo.

A lo largo de la primera dimensión

Si desea utilizar la primera dimensión, puede utilizar un código relativamente simple y corto:

function y = MyMultiDimensional(x) x_size = size(x); % Get input size yflat = x(1,:) .* x(2,:) + x(3,:); % Calculate "flattened" 2D function y = reshape(yflat, [1 x_size(2:end)]); % Reshape output back to original size end

A lo largo de una dimensión arbitraria, ahora con permute ND.

Cuando quiere que su función actúe a lo largo de la n -ésima dimensión de un total de N , puede permute esa cota al frente primero:

function y = MyMultiDimensional(x,n) x_size = size(x); % Get input size Order = 1:numel(x_size); Order(n)=[]; % Remove n-th dimension Order2 = [n, Order]; % Prepend n-th dimension xPermuted = permute(x,Order2); % permute the n-th dimension to the front yTmp = xPermuted (1,:) .* xPermuted (2,:) + xPermuted (3,:); % Calculate "flattened" 2D function y = reshape(yTmp, x_size(Order)); % Reshape output back to original size end

Programé los resultados de los dos métodos de Luis y mis métodos:

function timeMultiDim() x = rand(1e1,1e1,1e1,1e1,1e1,1e1,1e1,1e1); function y = Luis1(x) colons = repmat({'':''}, 1, ndims(x)-1); % row cell array containing the string '':'' % repeated the required number of times y = x(1,colons{:}).*x(2,colons{:}) + x(3,colons{:}); end function y = Luis2(x) xs = num2cell(x, [2:ndims(x)]); % x split along the first dimension y = xs{1}.*xs{2} + xs{3}; end function y = Adriaan(x) x_size = size(x); % Get input size yflat = x(1,:) .* x(2,:) + x(3,:); % Calculate "flattened" 2D function y = reshape(yflat, [1 x_size(2:end)]); % Reshape output back to original size end n=1; function y = Adriaan2(x,n) x_size = size(x); % Get input size Order = 1:numel(x_size); Order(n)=[]; % Remove n-th dimension Order2 = [n, Order]; % Prepend n-th dimension xPermuted = permute(x,Order2); % permute the n-th dimension to the front yTmp = xPermuted (1,:) .* xPermuted (2,:) + xPermuted (3,:); % Calculate "flattened" 2D function y = reshape(yTmp, x_size(Order)); % Reshape output back to original size end t1 = timeit(@() Luis1(x)); t2 = timeit(@() Luis2(x)); t3 = timeit(@() Adriaan(x)); t4 = timeit(@() Adriaan2(x,n)); format long g; fprintf(''Luis 1: %f seconds/n'', t1); fprintf(''Luis 2: %f seconds/n'', t2); fprintf(''Adriaan 1: %f seconds/n'', t3); fprintf(''Adriaan 2: %f seconds/n'', t4); end Luis 1: 0.698139 seconds Luis 2: 4.082378 seconds Adriaan 1: 0.696034 seconds Adriaan 2: 0.691597 seconds

Por lo tanto, ir a una celda es malo, lleva más de 5 veces más tiempo, reshape y '':'' están apenas separados, por lo que eso se reduce a la preferencia.