tutorial tamaño que multiplicar matrices libreria español ejemplos arreglos arreglo array python numpy matrix-multiplication python-3.5

tamaño - Diferencia entre numpy dot() y Python 3.5+ matrix multiplication @



que es un array en python (4)

Recientemente me mudé a Python 3.5 y noté que el nuevo operador de multiplicación de matrices (@) a veces se comporta de manera diferente al operador de punto numpy . Por ejemplo, para matrices 3d:

import numpy as np a = np.random.rand(8,13,13) b = np.random.rand(8,13,13) c = a @ b # Python 3.5+ d = np.dot(a, b)

El operador @ devuelve una matriz de formas:

c.shape (8, 13, 13)

mientras que la función np.dot() devuelve:

d.shape (8, 13, 8, 13)

¿Cómo puedo reproducir el mismo resultado con numpy dot? ¿Hay alguna otra diferencia significativa?


El operador @ llama al método __matmul__ la matriz, no al dot . Este método también está presente en la API como la función np.matmul .

>>> a = np.random.rand(8,13,13) >>> b = np.random.rand(8,13,13) >>> np.matmul(a, b).shape (8, 13, 13)

De la documentación:

matmul difiere de dot en dos formas importantes.

  • La multiplicación por escalares no está permitida.
  • Las pilas de matrices se transmiten juntas como si las matrices fueran elementos.

El último punto deja en claro que los métodos de dot y matmul comportan de manera diferente cuando se pasan matrices 3D (o de dimensiones más altas). Citando de la documentación un poco más:

Para matmul :

Si cualquiera de los argumentos es ND, N> 2, se trata como una pila de matrices que residen en los últimos dos índices y se transmite en consecuencia.

Para np.dot :

Para las matrices en 2-D es equivalente a la multiplicación de matrices, y para las matrices en 1-D al producto interno de los vectores (sin conjugación compleja). Para N dimensiones es un producto suma sobre el último eje de a y el penúltimo de b


En matemáticas, creo que el punto numpy tiene más sentido

punto (a, b) _ {i, j, k, a, b, c} = / sum_m a_ {i, j, k, m} b_ {a, b, m, c}

dado que da el producto escalar cuando a y b son vectores, o la multiplicación matricial cuando a y b son matrices

En cuanto a la operación matmul en numpy, consta de partes del resultado de punto , y se puede definir como

matmul (a, b) _ {i, j, k, c} = / sum_m a_ {i, j, k, m} b_ {i, j, m, c}

Entonces, puede ver que matmul (a, b) devuelve una matriz con una forma pequeña, que tiene un menor consumo de memoria y tiene más sentido en las aplicaciones. En particular, combinando con la broadcasting , puede obtener

matmul (a, b) _ {i, j, k, l} = / sum_m a_ {i, j, k, m} b_ {j, m, l}

por ejemplo.

De las dos definiciones anteriores, puede ver los requisitos para usar esas dos operaciones. Suponga que a.shape = (s1, s2, s3, s4) y b.shape = (t1, t2, t3, t4)

  • Para usar el punto (a, b) necesitas

    1. **t3=s4**;

  • Para usar matmul (a, b) necesitas

    1. t3 = s4
    2. t2 = s2 , o uno de t2 y s2 es 1
    3. t1 = s1 , o uno de t1 y s1 es 1

Use el siguiente código para convencerse.

Muestra de código

import numpy as np for it in xrange(10000): a = np.random.rand(5,6,2,4) b = np.random.rand(6,4,3) c = np.matmul(a,b) d = np.dot(a,b) #print ''c shape: '', c.shape,''d shape:'', d.shape for i in range(5): for j in range(6): for k in range(2): for l in range(3): if not c[i,j,k,l] == d[i,j,k,j,l]: print it,i,j,k,l,c[i,j,k,l]==d[i,j,k,j,l] #you will not see them


La respuesta de @ajcr explica cómo difieren el dot y el matmul (invocado por el símbolo @ ). Al observar un ejemplo simple, uno ve claramente cómo los dos se comportan de manera diferente cuando operan en ''pilas de matrices'' o tensores.

Para aclarar las diferencias, tome una matriz de 4x4 y devuelva el producto de dot y el producto matmul con una ''pila de matrices'' o tensor de 2x4x3.

import numpy as np fourbyfour = np.array([ [1,2,3,4], [3,2,1,4], [5,4,6,7], [11,12,13,14] ]) twobyfourbythree = np.array([ [[2,3],[11,9],[32,21],[28,17]], [[2,3],[1,9],[3,21],[28,7]], [[2,3],[1,9],[3,21],[28,7]], ]) print(''4x4*4x2x3 dot:/n {}/n''.format(np.dot(fourbyfour,twobyfourbythree))) print(''4x4*4x2x3 matmul:/n {}/n''.format(np.matmul(fourbyfour,twobyfourbythree)))

Los productos de cada operación aparecen a continuación. Observe cómo es el producto escalar,

... un producto de suma sobre el último eje de a y el penúltimo de b

y cómo se forma el producto de la matriz transmitiendo la matriz juntos.

4x4*4x2x3 dot: [[[232 152] [125 112] [125 112]] [[172 116] [123 76] [123 76]] [[442 296] [228 226] [228 226]] [[962 652] [465 512] [465 512]]] 4x4*4x2x3 matmul: [[[232 152] [172 116] [442 296] [962 652]] [[125 112] [123 76] [228 226] [465 512]] [[125 112] [123 76] [228 226] [465 512]]]


Solo para su información, @ y sus equivalentes numpy dot y matmul son casi igual de rápidos. (Parcela creada con perfplot , un proyecto mío).

Código para reproducir la trama:

import perfplot import numpy def setup(n): A = numpy.random.rand(n, n) x = numpy.random.rand(n) return A, x def at(data): A, x = data return A @ x def numpy_dot(data): A, x = data return numpy.dot(A, x) def numpy_matmul(data): A, x = data return numpy.matmul(A, x) perfplot.show( setup=setup, kernels=[at, numpy_dot, numpy_matmul], n_range=[2 ** k for k in range(12)], logx=True, logy=True, )