2010-07-09 7 views
18

Estoy tratando de encontrar algún modo de sustraer un vector de tamaño 3 de cada columna de una matriz de 3 * (un gran número) en Matlab. Por supuesto que podría usar un bucle, pero estoy tratando de encontrar una solución más eficiente, un poco como la transmisión numpy. Ah, y no puedo usar repmat porque simplemente no tengo suficiente memoria para usarlo (ya que crea otra matriz 3 * (un número grande)) ...Matlab equivalente a la transmisión de Numpy?

¿Esto es posible?

+1

Como señala una de las respuestas más recientes, Matlab R2016b parece haber agregado la transmisión como una función estándar. (https://nickhigham.wordpress.com/2016/09/20/implicit-expansion-matlab-r2016b/) –

Respuesta

18

Los bucles ya no están mal en MATLAB gracias a las optimizaciones del compilador como just-in-time acceleration (JITA). etc. La mayoría de las veces, he notado que una solución con bucles en las versiones actuales de MATLAB es mucho más rápido que complicado (aunque, genial: D) one-liners.

bsxfun podría hacer el truco, pero en mi experiencia, que tiende a tener problemas de memoria, así pero menos que repmat.

Así que la sintaxis sería:

AA = bsxfun(@minus,A,b) donde b es el vector y A es su gran matriz

pero insto a crear perfiles para la versión descabellada y luego decide! Probablemente, debido a restricciones de memoria, es posible que no tenga una opción :)

+0

Puede tener razón acerca de BSXFUN. Todavía tendrá problemas de memoria, pero creo que usualmente * es * mejor que usar REPMAT. – gnovice

+3

Lo que más me gusta de 'bsxfun' es que en las versiones de 2010a y 2010b nativamente multiplexará su código para un mejor rendimiento sin demasiada intervención de su parte. – JudoWill

+0

@JudoWill: ¡Eso es genial! He estado buscando un caso claro contra 'repmat' --- ¿tiene alguna documentación al respecto? – Jacob

4

No sé si esto acelerará el código, pero la sustracción de un escalar de un vector no tiene problemas de memoria. Dado que el tamaño de su matriz es tan asimétrico, la sobrecarga de un bucle for en la dimensión corta es insignificante.

Así que tal vez

matout = matin; 
for j = 1:size(matin, 1) %3 in this case 
    matout(j,:) = matin(j,:) - vec_to_subtract(j); 
end 

por supuesto, usted puede hacer esto en su lugar, pero yo no sabía si quería conservar la matriz original.

+0

En realidad, el bucle for está en la dimensión grande (ya que estoy restando un vector de tamaño 3 de cada columna de una matriz de tamaño 3 * (mucho)), así que era por eso que le tenía miedo al bucle for. – antony

+0

Piénselo de esta manera: divida su matriz en 3 vectores de tamaño 1xN. luego reste el escalar correspondiente de cada vector. Entonces, el bucle for está en la dimensión corta. – Marc

+0

OK, lo veo ahora. Gracias. – antony

10

Las otras respuestas están un poco desactualizadas - Matlab R2016b parece tener added broadcasting as a standard feature. Un ejemplo de esa publicación de blog que coincide con la pregunta:

>> A = ones(2) + [1 5]' 
A = 
    2  2 
    6  6 
+2

También hay otras características * sorprendentes * en 2016b, como cadenas de primera clase (https://www.mathworks.com/help/matlab/matlab_prog/create-string-arrays.html) que puede concatenar con "+ ". Oh, solo estaba siendo sarcástico :-) – antony

Cuestiones relacionadas