Operaciones con tensores

Los tensores pueden operarse de distintas formas para producir nuevos tensores. Como otras estructuras matemáticas, los tensores permiten operaciones básicas como la suma o el producto. Otras operaciones importantes se pueden hacer con los tensores. Revisamos estas operaciones:

Transposición

La transposición es una operación que se presenta en tensores de rango mayor o igual a 2. Si bien podemos pensar que un vector (tensor de rango 1) puede transponerse al considerarlo como una columna (vector en vertical) en lugar de un renglón (vector en horizontal). En el caso de las paqueterías con las que operamos la transposición de un vector no surge ningún efecto, sigue siendo un arreglo de números.

En los tensores de mayor rango, la transposición es una permutación que invierte el valor de los índices de un tensor. Es decir, si el tensor $T$ tiene los índices $i_1, i_2,...,i_n$, el vector transpuesto $T^T$ tendrá los índices $i_n, i_{n-1}, ..., i_2, i_1$.

En el caso de las matrices, la tranposición invierte los índices $i,j$ a $j,i$. Así, la transposición de la matriz $A$ tiene como entradas $(A^T)_{i,j} = A_{j,i}$. Es decir,m la transposición de las matrices cambia las columnas por renglones.

En tensores de rango 3, los tres índices $i,j,k$ se invierten como $k,j,i$; pot ejemplo, un tensor de tamaño $(2,4,3)$ tendrá una transpuesta de tamaño $(3,4,2)$. De tal forma, que las entradas del tensor transpuesto de grado 3 estarán dadas como: $$(T^T)_{i,j,k} = T_{k,j,i}$$

En tensores de mayor rango, la transposición invierte los índices de tal forma que:

$$(T^T)_{i_1,i_2,...,i_{n-1},i_n} = T_{i_n, i_{n-1},...,i_2, i_1}$$

Podemos generar un tensro de manera aleatoria (usamos la función torch.rand()) y ver cómo se comportan sus índices:

Suma de tensores

La suma de tensores es una operación sencilla que únicamente consiste en sumar cada una de las entradas de ambos tensores. Por tanto, la suma sólo puede hacerse entre tensores del mismo rango, y de las mismas dimensiones. La suma se da como:

$$(A + B)_{i_1,...,i_n} = A_{i_1,...,i_n} + B_{i_1,...,i_n}$$

Producto por escalares

El producto por un escalar toma un número real $\lambda$ y multiplica cada entrada por este elemento. Por lo que las entradas de un tensor multiplicado por un escalar es de la forma $(\lambda T)_{i_1,...,i_n} = \lambda T_{i_1,...,i_n}$. En este sentido, lo que hace el producto por el escalar es precisamente "escalar" el tensor. En PyTorch, tanto como en Tensorflow y Numpy este producto se hace como:

scalar = a*T

Donde $a$ es un valor numérico, entero o flotante.

Producto punto entre vectores

El producto punto entre dos vectores $x, y$ de la misma dimensión se calcula como:

$$x^T y = \sum_{i=1}^d x_i y_i$$

Este producto punto se realiza de diferentes formas según el lenguaje de programación que estemos usando:

Productos con matrices

Los tensores de rango 2 pueden multiplicar a otros tensores de diferente rango. Por ejemplo, se puede realizar el producto entre una matriz $A$ y un vector $x$ donde la dimensiones de las columnas de $A$ deben coincidir con la dimensión de $x$. El resultado de producto es un vector que está determinado como:

$$(Ax)_i = \sum_j A_{i,j} x_j$$

En este caso, se utilizan las mismas funciones que en el producto punto. En este caso, tenemos la función torch.matmul().

Asimismo, se puede realizar el producto entre dos matrices que compartan una dimensión. Es decir, la primera matriz tendrá tantas columnas como renglones la segunda. El producto entre matrices está dado como:

$$(AB)_{i,j} = \sum_k A_{i,k} B_{k,j}$$

Producto entre tensores de mayor rango

Los tensores de rango 3 o mayores pueden multiplicarse con otros tensores de menor o igual rango. Por ejemplo, podemos multiplicar un vector de rango 3 por un vector como:

$$(Tx)_{i,j} = \sum_{k} T_{i,j,k} x_k$$

Por su parte, también podemos multiplicar el tensor por una matriz, de la siguiente forma:

$$(TA)_{i,j,k} = \sum_{l} T_{i,j,l} A_{l,k}$$

Finalmente, podemos realizar el producto entre tensores de mayor rango. Por ejemplo, entre tensores de rango 3. En todos estos casos, como vemos, se utiliza la función torch.matmul().

Producto de Hadamard

El producto de Hadamard es un producto punto a punto, en donde cada entrada de los tensores se multiplican entre si. Es decir, se tiene que:

$$(T \odot U)_{i_1,...,i_n} = T_{i_1,...,i_n}U_{i_1,...,i_n}$$

Este producto suele hacerse por medio del operador *.

Producto externo

El producto externo es importante para algunas operaciones entre vectores, pues produce una matriz cuyas entradas son productos entre los elementos de ambos vectores. En este caso, el resultado se obtiene como:

$$(x \otimes y)_{i,j} = x_i y_j $$