python numpy linear-algebra tensor dot-product

python - Entendiendo tensordot



numpy linear-algebra (2)

La idea con tensordot es bastante simple: tensordot las matrices y los ejes respectivos a los que se destinan las reducciones de suma. Los ejes que participan en la reducción de suma se eliminan en la salida y todos los ejes restantes de las matrices de entrada se extienden como diferentes ejes en la salida manteniendo el orden en que se alimentan las matrices de entrada.

Veamos algunos casos de muestra con uno y dos ejes de reducción de suma y también intercambiemos los lugares de entrada y veamos cómo se mantiene el orden en la salida.

I. Un eje de reducción de suma

Entradas:

In [7]: A = np.random.randint(2, size=(2, 6, 5)) ...: B = np.random.randint(2, size=(3, 2, 4)) ...:

Caso 1:

In [9]: np.tensordot(A, B, axes=((0),(1))).shape Out[9]: (6, 5, 3, 4) A : (2, 6, 5) -> reduction of axis=0 B : (3, 2, 4) -> reduction of axis=1 Output : `(2, 6, 5)`, `(3, 2, 4)` ===(2 gone)==> `(6,5)` + `(3,4)` => `(6,5,3,4)`

Caso # 2 (igual que el caso # 1 pero las entradas se alimentan intercambiadas):

In [8]: np.tensordot(B, A, axes=((1),(0))).shape Out[8]: (3, 4, 6, 5) B : (3, 2, 4) -> reduction of axis=1 A : (2, 6, 5) -> reduction of axis=0 Output : `(3, 2, 4)`, `(2, 6, 5)` ===(2 gone)==> `(3,4)` + `(6,5)` => `(3,4,6,5)`.

II Dos ejes de reducción de suma

Entradas:

In [11]: A = np.random.randint(2, size=(2, 3, 5)) ...: B = np.random.randint(2, size=(3, 2, 4)) ...:

Caso 1:

In [12]: np.tensordot(A, B, axes=((0,1),(1,0))).shape Out[12]: (5, 4) A : (2, 3, 5) -> reduction of axis=(0,1) B : (3, 2, 4) -> reduction of axis=(1,0) Output : `(2, 3, 5)`, `(3, 2, 4)` ===(2,3 gone)==> `(5)` + `(4)` => `(5,4)`

Caso # 2:

In [14]: np.tensordot(B, A, axes=((1,0),(0,1))).shape Out[14]: (4, 5) B : (3, 2, 4) -> reduction of axis=(1,0) A : (2, 3, 5) -> reduction of axis=(0,1) Output : `(3, 2, 4)`, `(2, 3, 5)` ===(2,3 gone)==> `(4)` + `(5)` => `(4,5)`

Podemos extender esto a tantos ejes como sea posible.

Después de aprender a usar einsum , ahora estoy tratando de entender cómo funciona np.tensordot .

Sin embargo, estoy un poco perdido, especialmente con respecto a las diversas posibilidades para los axes parámetros.

Para entenderlo, como nunca he practicado el cálculo del tensor, utilizo el siguiente ejemplo:

A = np.random.randint(2, size=(2, 3, 5)) B = np.random.randint(2, size=(3, 2, 4))

En este caso, ¿cuáles son los diferentes np.tensordot posibles y cómo lo calcularía manualmente?


tensordot intercambia ejes y da nueva forma a las entradas para que pueda aplicar np.dot a 2 arrays 2d. Luego se intercambia y se forma de nuevo al objetivo. Puede ser más fácil experimentar que explicar. No hay matemática tensorial especial, solo se extiende el dot para trabajar en dimensiones más altas. tensor solo significa matrices con más de 2d. Si ya se siente cómodo con el einsum , será más sencillo comparar los resultados con eso.

Una prueba de muestra que suma 1 par de ejes.

In [823]: np.tensordot(A,B,[0,1]).shape Out[823]: (3, 5, 3, 4) In [824]: np.einsum(''ijk,lim'',A,B).shape Out[824]: (3, 5, 3, 4) In [825]: np.allclose(np.einsum(''ijk,lim'',A,B),np.tensordot(A,B,[0,1])) Out[825]: True

otro, sumando dos.

In [826]: np.tensordot(A,B,[(0,1),(1,0)]).shape Out[826]: (5, 4) In [827]: np.einsum(''ijk,jim'',A,B).shape Out[827]: (5, 4) In [828]: np.allclose(np.einsum(''ijk,jim'',A,B),np.tensordot(A,B,[(0,1),(1,0)])) Out[828]: True

Podríamos hacer lo mismo con el par (1,0) . Dada la combinación de dimensiones, no creo que haya otra combinación.