una transpuesta sumar recorrer multiplicar matriz matrices funciones elementos ejemplos columnas array agregar numpy scipy vectorization matrix-multiplication dot-product

numpy - transpuesta - sumar columnas de una matriz python



Forma vectorizada de calcular dos matrices de productos de puntos por filas con Scipy (5)

Quiero calcular el producto de puntos de dos matrices de la misma dimensión lo más rápido posible. Esta es la forma en que lo estoy haciendo:

import numpy as np a = np.array([[1,2,3], [3,4,5]]) b = np.array([[1,2,3], [1,2,3]]) result = np.array([]) for row1, row2 in a, b: result = np.append(result, np.dot(row1, row2)) print result

y por supuesto la salida es:

[ 26. 14.]


Echa un vistazo a numpy.einsum para otro método:

In [52]: a Out[52]: array([[1, 2, 3], [3, 4, 5]]) In [53]: b Out[53]: array([[1, 2, 3], [1, 2, 3]]) In [54]: einsum(''ij,ij->i'', a, b) Out[54]: array([14, 26])

Parece que einsum es un poco más rápido que inner1d :

In [94]: %timeit inner1d(a,b) 1000000 loops, best of 3: 1.8 us per loop In [95]: %timeit einsum(''ij,ij->i'', a, b) 1000000 loops, best of 3: 1.6 us per loop In [96]: a = random.randn(10, 100) In [97]: b = random.randn(10, 100) In [98]: %timeit inner1d(a,b) 100000 loops, best of 3: 2.89 us per loop In [99]: %timeit einsum(''ij,ij->i'', a, b) 100000 loops, best of 3: 2.03 us per loop


Encontré esta respuesta y volví a verificar los resultados con Numpy 1.14.3 ejecutándose en Python 3.5. En su mayor parte, las respuestas anteriores son verdaderas en mi sistema, aunque encontré que para matrices muy grandes (vea el ejemplo a continuación), todos los métodos, excepto uno, están tan próximos entre sí que la diferencia de rendimiento no tiene sentido.

Para matrices más pequeñas, encontré que einsum fue el más rápido por un margen considerable, hasta un factor de dos en algunos casos.

Mi gran ejemplo de matriz:

import numpy as np from numpy.core.umath_tests import inner1d a = np.random.randn(100, 1000000) # 800 MB each b = np.random.randn(100, 1000000) # pretty big. def loop_dot(a, b): result = np.empty((a.shape[1],)) for i, (row1, row2) in enumerate(zip(a, b)): result[i] = np.dot(row1, row2) %timeit inner1d(a, b) # 128 ms ± 523 µs per loop (mean ± std. dev. of 7 runs, 10 loops each) %timeit np.einsum(''ij,ij->i'', a, b) # 121 ms ± 402 µs per loop (mean ± std. dev. of 7 runs, 10 loops each) %timeit np.sum(a*b, axis=1) # 411 ms ± 1.99 ms per loop (mean ± std. dev. of 7 runs, 10 loops each) %timeit loop_dot(a, b) # note the function call took negligible time # 123 ms ± 342 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

Así que einsum sigue siendo el más rápido en matrices muy grandes, pero en una cantidad muy pequeña. ¡Sin embargo, parece ser una cantidad estadísticamente significativa (pequeña)!


Jugó un poco con esto y encontré inner1d el más rápido:

La trama fue creada con perfplot (un pequeño proyecto mío)

import numpy from numpy.core.umath_tests import inner1d import perfplot perfplot.show( setup=lambda n: (numpy.random.rand(n, 3), numpy.random.rand(n, 3)), n_range=[2**k for k in range(1, 18)], kernels=[ lambda data: numpy.sum(data[0] * data[1], axis=1), lambda data: numpy.einsum(''ij, ij->i'', data[0], data[1]), lambda data: inner1d(data[0], data[1]) ], labels=[''np.sum(a*b, axis=1)'', ''einsum'', ''inner1d''], logx=True, logy=True, xlabel=''len(a), len(b)'' )


Lo harás mejor evitando el append , pero no puedo pensar en una manera de evitar el bucle de python. Un Ufunc personalizado tal vez? No creo que numpy.vectorize te ayude aquí.

import numpy as np a=np.array([[1,2,3],[3,4,5]]) b=np.array([[1,2,3],[1,2,3]]) result=np.empty((2,)) for i in range(2): result[i] = np.dot(a[i],b[i])) print result

EDITAR

Según esta respuesta , parece que inner1d podría funcionar si los vectores en su problema del mundo real son 1D.

from numpy.core.umath_tests import inner1d inner1d(a,b) # array([14, 26])


Una forma sencilla de hacerlo es:

import numpy as np a=np.array([[1,2,3],[3,4,5]]) b=np.array([[1,2,3],[1,2,3]]) np.sum(a*b, axis=1)

que evita el bucle de python y es más rápido en casos como:

def npsumdot(x, y): return np.sum(x*y, axis=1) def loopdot(x, y): result = np.empty((x.shape[0])) for i in range(x.shape[0]): result[i] = np.dot(x[i], y[i]) return result timeit npsumdot(np.random.rand(500000,50),np.random.rand(500000,50)) # 1 loops, best of 3: 861 ms per loop timeit loopdot(np.random.rand(500000,50),np.random.rand(500000,50)) # 1 loops, best of 3: 1.58 s per loop