Multiplicando a través de una matriz numpy

Estoy tratando de multiplicar cada uno de los términos en una matriz 2D por los términos correspondientes en una matriz 1D. Esto es muy fácil si quiero multiplicar cada columna por la matriz 1D, como se muestra en la función numpy.multiply . Pero quiero hacer lo contrario, multiplicar cada término en la fila. En otras palabras quiero multiplicar:

[1,2,3] [0] [4,5,6] * [1] [7,8,9] [2] 

y obten

 [0,0,0] [4,5,6] [14,16,18] 

pero en cambio me dan

 [0,2,6] [0,5,12] [0,8,18] 

¿Alguien sabe si hay una manera elegante de hacer eso con adormecimiento? Muchas gracias alex

Multiplicación normal como la mostraste:

 >>> import numpy as np >>> m = np.array([[1,2,3],[4,5,6],[7,8,9]]) >>> c = np.array([0,1,2]) >>> m * c array([[ 0, 2, 6], [ 0, 5, 12], [ 0, 8, 18]]) 

Si agrega un eje, se multiplicará de la forma que desee:

 >>> m * c[:, np.newaxis] array([[ 0, 0, 0], [ 4, 5, 6], [14, 16, 18]]) 

También podrías transponer dos veces:

 >>> (mT * c).T array([[ 0, 0, 0], [ 4, 5, 6], [14, 16, 18]]) 

He comparado las diferentes opciones de velocidad y descubrí que, para mi sorpresa, todas las opciones (excepto diag ) son igualmente rápidas. Yo personalmente uso

 A * b[:, None] 

(o (AT * b).T ) porque es corto.

introduzca la descripción de la imagen aquí


Código para reproducir la ttwig:

 import numpy import perfplot def newaxis(data): A, b = data return A * b[:, numpy.newaxis] def none(data): A, b = data return A * b[:, None] def double_transpose(data): A, b = data return (AT * b).T def double_transpose_contiguous(data): A, b = data return numpy.ascontiguousarray((AT * b).T) def diag_dot(data): A, b = data return numpy.dot(numpy.diag(b), A) def einsum(data): A, b = data return numpy.einsum("ij,i->ij", A, b) perfplot.save( "p.png", setup=lambda n: (numpy.random.rand(n, n), numpy.random.rand(n)), kernels=[ newaxis, none, double_transpose, double_transpose_contiguous, diag_dot, einsum, ], n_range=[2 ** k for k in range(14)], logx=True, logy=True, xlabel="len(A), len(b)", ) 

También puedes usar la multiplicación de matrices (también conocido como punto):

 a = [[1,2,3],[4,5,6],[7,8,9]] b = [0,1,2] c = numpy.diag(b) numpy.dot(c,a) 

Lo que es más elegante es probablemente una cuestión de gustos.

Otro truco más (a partir de v1.6)

 A=np.arange(1,10).reshape(3,3) b=np.arange(3) np.einsum('ij,i->ij',A,b) 

Soy experto en la transmisión de números ( newaxis ), pero todavía estoy encontrando mi camino en esta nueva herramienta de einsum . Así que tuve que jugar un poco para encontrar esta solución.

Tiempos (usando Ipython timeit):

 einsum: 4.9 micro transpose: 8.1 micro newaxis: 8.35 micro dot-diag: 10.5 micro 

Por cierto, al cambiar una i a una j , np.einsum('ij,j->ij',A,b) , se obtiene la matriz que Alex no quiere. Y np.einsum('ji,j->ji',A,b) hace, en efecto, la doble transposición.

Para aquellas almas perdidas en google, usar numpy.expand_dims luego numpy.repeat funcionará, y también funcionará en casos de dimensiones más altas (es decir, multiplicar una forma (10, 12, 3) por una (10, 12)).

 >>> import numpy >>> a = numpy.array([[1,2,3],[4,5,6],[7,8,9]]) >>> b = numpy.array([0,1,2]) >>> b0 = numpy.expand_dims(b, axis = 0) >>> b0 = numpy.repeat(b0, a.shape[0], axis = 0) >>> b1 = numpy.expand_dims(b, axis = 1) >>> b1 = numpy.repeat(b1, a.shape[1], axis = 1) >>> a*b0 array([[ 0, 2, 6], [ 0, 5, 12], [ 0, 8, 18]]) >>> a*b1 array([[ 0, 0, 0], [ 4, 5, 6], [14, 16, 18]]) 

Porque no solo haces

 >>> m = np.array([[1,2,3],[4,5,6],[7,8,9]]) >>> c = np.array([0,1,2]) >>> (mT * c).T 

??