Abrir en Google Colab
|
Descargar notebook
|
Tensores
Introducción
Podemos pensar en un tensor como un arreglo multidimensional, es decir, que son generalizaciones de los vectores y las matrices. En general, diremos que cualquier arreglo de numeros organizados en una estructura regular con una determinada cantidad de ejes es un tensor.
De esta forma un vector es un tensor unidimensional (o de orden 1) y una matriz es un tensor de 2 dimensiones (o de orden 2). Por lo tnato, muchas de las operaciones que se pueden realizar sobre vetores y matrices también pueden ser reformuladas para ejecutarse sobre tensores.

Imagen de Cassie Kozyrkov (@quaesita)
Algunas consideraciones:
Todos los valores dentro de un tensor son del mismo tipo.
Las dimensiones de los datos son las dimensiones del tensor.
Las dimensiones del tensor son conocidas o al menos parcialmente conocidas.
Tensores en Python
Los tensores en Python se pueden representar utilizando arreglos n-dimensionales. Diferentes librerias permiten representar tensores.
En numpy:
[ ]:
import numpy as np
t = np.array([
[[1,2,3], [4,5,6], [7,8,9]],
[[11,12,13], [14,15,16], [17,18,19]],
[[21,22,23], [24,25,26], [27,28,29]],
])
print(type(t))
<class 'numpy.ndarray'>
En TensorFlow:
[ ]:
import tensorflow as tf
t = tf.constant([
[[1,2,3], [4,5,6], [7,8,9]],
[[11,12,13], [14,15,16], [17,18,19]],
[[21,22,23], [24,25,26], [27,28,29]],
])
print(type(t))
<class 'tensorflow.python.framework.ops.EagerTensor'>
En PyTorch:
[ ]:
import torch
t = torch.tensor([
[[1,2,3], [4,5,6], [7,8,9]],
[[11,12,13], [14,15,16], [17,18,19]],
[[21,22,23], [24,25,26], [27,28,29]],
])
print(type(t))
<class 'torch.Tensor'>
Notemos la diferencia con un arreglo en Python:
[ ]:
arreglo = [
[[1,2,3], [4,5,6], [7,8,9]],
[[11,12,13], [14,15,16], [17,18,19]],
[[21,22,23], [24,25,26], [27,28,29]],
]
print(type(arreglo))
<class 'list'>
Nota: Veremos que en la mayoria de los casos numpy.ndarray es un tipo compatible para tensorflow.python.framework.ops.EagerTensor y torch.Tensor, sin embargo el tipo list no lo es. En esos casos, podemos utilizar:
[ ]:
np.asarray(arreglo)
Dimensiones de un tensor
Podemos acceder a las dimensiones de un tensor en cualquier momento utilizando la instrucción shape:
[ ]:
t.shape
torch.Size([3, 3, 3])
En este caso vemos que este tensor tiene 3 dimensiones. Cada una de las cuales tiene 3 elementos. Estos numeros que aparecen aqui se llaman ejes o axis y reciben numeros ordinales para identificarlos. La primera dimension corresponde a axis=0, la segunda a axis=1 y la tercera a axis=2.
Dado que un tensor no es mas que un arreglo de numeros, podemos cambiar sus dimensiones para llevarlo a otras dimensiones. Por ejemplo, el siguiente codigo crea un tensor de 1 dimensión con 30 elementos:
[ ]:
t = np.arange(30)
print(t)
[ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
24 25 26 27 28 29]
Las dimensiones de este tensor son:
[ ]:
t.shape
(30,)
Podemos convertir este tensor de 1 dimension a uno de 3 dimensiones:

Fuente de la imagen: https://www.tensorflow.org/guide/tensor
[ ]:
t = t.reshape((3, 2, 5))
print(t)
print("Shape:", t.shape)
[[[ 0 1 2 3 4]
[ 5 6 7 8 9]]
[[10 11 12 13 14]
[15 16 17 18 19]]
[[20 21 22 23 24]
[25 26 27 28 29]]]
Shape: (3, 2, 5)
Nota: Si trabaja con tensore en
TensorFlow, la operación anterior se realiza comotf.reshape(t, (3 , 2, 5)). No te como especificar estas operaciones en este framework a diferencia denumpyopytorch.
En muchas ocaciones necesitamos eliminar alguna de las dimensiones en particular.

Fuente de la imagen: https://www.tensorflow.org/guide/tensor
[ ]:
t = t.reshape((3, -1))
print(t)
print("Shape:", t.shape)
[[ 0 1 2 3 4 5 6 7 8 9]
[10 11 12 13 14 15 16 17 18 19]
[20 21 22 23 24 25 26 27 28 29]]
Shape: (3, 10)
Noten como eliminamos la ultima posición del tensor. El valor -1 indica «la cantidad de elementos que entren». Esto significa que queremos que la primera componente del tensor sea de dimension 3 y la segunda de «la cantidad restante de elementos». Es importante que las dimensiones tengan sentido con la cantidad de elementos para evitar un error:
[ ]:
t.reshape((4, -1))
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
/tmp/ipykernel_13468/1980147985.py in <module>
----> 1 t.reshape((4, -1))
ValueError: cannot reshape array of size 30 into shape (4,newaxis)
Agregando dimensiones
Podemos agregar dimensiones extras pero sin distorcionar las otras dimensiones. Esto es util cuando por ejemplo la entrada de una red es una «lote» de valores pero nosotros queremos introducir solo un valor. Asi podemos convertir un tensor de 2 dimensiones en uno de 3.
[ ]:
print("Dimensiones antes:", t.shape)
Dimensiones antes: (3, 10)
[ ]:
t = t.reshape((1,3,10))
print("Dimensiones despues:", t.shape)
Dimensiones despues: (1, 3, 10)
Permutando dimensiones
Podemos cambiar el orden de las dimensiones. Esto es util cuando queremos ver la información de otra forma: La instrucción permute permite hacerlo, pero no está disponible en todos los tipos de tensores, solo en TensorFlow y PyTorch
[ ]:
t_torch = torch.tensor(t)
[ ]:
print("Dimensiones antes:", t_torch.shape)
Dimensiones antes: torch.Size([1, 3, 10])
[ ]:
t_torch = t_torch.permute(1,0,2)
print("Dimensiones despues:", t_torch.shape)
Dimensiones despues: torch.Size([3, 1, 10])
Quitando dimensiones
De igual forma podemos eliminarla si no la necesitaramos. La instrucción squeeze nos permite eliminar alguna dimensión cuya cantidad de elementos es 1. El argumento axis=0 indica cual es la dimensión a quitar, en este caso la primera:
[ ]:
print("Dimensiones antes:", t.shape)
Dimensiones antes: (1, 3, 10)
[ ]:
t = t.squeeze(axis=0)
print("Dimensiones despues:", t.shape)
Dimensiones despues: (3, 10)
Tipos de dato de un tensor
Todos los elementos de un tensor deben tener el mismo tipo de datos. Podemos ver el tipo de datos de cualquier tensor con la propiedad dtype
[ ]:
t.dtype
dtype('int64')
En muchos casos necesitamos cambiar el tipo de dato a otro, por ejemplo float32 o int32:
[ ]:
t_float = t.astype('float32')
print(t_float.dtype)
float32
Esto es importante sobre todo cuando estamos integrando datos de diferentes origines y necesitamos que todos los tensores tengan tipos que sean compatibles y con la misma precisión.
Operaciones sobre tensores
De igual forma que podemos sumar, multiplicar y dividir un vector, estas operaciones estan definidas para los tensores. Dependiendo del Framework que utilizamos, serán las operaciones disponibles. En general, todos implementan las mismas APIs:
En tensorflow por ejemplo:
tf.add(a, b)
tf.substract(a, b)
tf.multiply(a, b)
tf.div(a, b)
tf.pow(a, b)
tf.exp(a)
tf.sqrt(a)
Otras estructuras de datos
No dedemos confundir los tensores con otras estructuras comunes como ser los DataFrame en Pandas. Un DataFrame tiene 2 grandes diferencias con un Tensor:
Los
DataFrametienen 2 dimensiones. LasSeriestienen dimensiones 1.Los
DataFramey lasSeriestienen un nombre de columna.
[ ]:
datos = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
]
[ ]:
import pandas as pd
df = pd.DataFrame(datos, columns=["col1", "col2", "col3"])
[ ]:
df
| col1 | col2 | col3 | |
|---|---|---|---|
| 0 | 1 | 2 | 3 |
| 1 | 4 | 5 | 6 |
| 2 | 7 | 8 | 9 |
Podemos de todas formas convertir desde DataFrame a numpy.ndarray:
[ ]:
df.to_numpy()
array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
Abrir en Google Colab
Descargar notebook