Operaciones con tensores en TensorFlow
Los tensores son la estructura de datos central en TensorFlow, y pueden entenderse como un concepto extendido de los arrays multidimensionales.
En el aprendizaje automático, casi todos los datos se representan en forma de tensores para su procesamiento.
Características básicas de los tensores
- Tipo de dato (dtype): cada tensor tiene un tipo de dato específico, como tf.float32, tf.int64, etc.
- Forma (shape): indica el tamaño de cada dimensión del tensor, como (2,3), que representa una matriz de 2 filas y 3 columnas.
- Ubicación del dispositivo (device): indica si el tensor se almacena en la CPU o en la GPU.
Dimensiones de los tensores
- Tensor de 0 dimensiones: escalar (scalar), como
tf.constant(5) - Tensor de 1 dimensión: vector (vector), como
tf.constant([1,2,3]) - Tensor de 2 dimensiones: matriz (matrix), como
tf.constant([[1,2],[3,4]]) - 3 dimensiones o más: tensor de orden superior, como
tf.ones((2,3,4))representa 2 matrices de 3×4
Métodos comunes para crear tensores
1. Crear desde listas de Python/arrays de NumPy
Ejemplo
import tensorflow as tf
import numpy as np
# Crear desde una lista de Python
tensor_from_list = tf.constant([[1, 2], [3, 4]])
# Crear desde un array de NumPy
numpy_array = np.array([[5, 6], [7, 8]])
tensor_from_numpy = tf.constant(numpy_array)
import numpy as np
# Crear desde una lista de Python
tensor_from_list = tf.constant([[1, 2], [3, 4]])
# Crear desde un array de NumPy
numpy_array = np.array([[5, 6], [7, 8]])
tensor_from_numpy = tf.constant(numpy_array)
2. Crear tensores con valores especiales
Ejemplo
# Tensor de todos ceros
zeros = tf.zeros((2, 3)) # Matriz de 2 filas y 3 columnas con todos los elementos 0
# Tensor de todos unos
ones = tf.ones((3, 2)) # Matriz de 3 filas y 2 columnas con todos los elementos 1
# Matriz identidad
eye = tf.eye(3) # Matriz identidad de 3×3
# Rellenar con un valor específico
filled = tf.fill((2, 2), 7) # Matriz de 2×2, todos los elementos son 7
zeros = tf.zeros((2, 3)) # Matriz de 2 filas y 3 columnas con todos los elementos 0
# Tensor de todos unos
ones = tf.ones((3, 2)) # Matriz de 3 filas y 2 columnas con todos los elementos 1
# Matriz identidad
eye = tf.eye(3) # Matriz identidad de 3×3
# Rellenar con un valor específico
filled = tf.fill((2, 2), 7) # Matriz de 2×2, todos los elementos son 7
3. Crear tensores aleatorios
Ejemplo
# Números aleatorios con distribución uniforme
uniform = tf.random.uniform((2, 2), minval=0, maxval=1)
# Números aleatorios con distribución normal
normal = tf.random.normal((3, 3), mean=0, stddev=1)
# Permutación aleatoria
shuffled = tf.random.shuffle(tf.constant([1, 2, 3, 4, 5]))
uniform = tf.random.uniform((2, 2), minval=0, maxval=1)
# Números aleatorios con distribución normal
normal = tf.random.normal((3, 3), mean=0, stddev=1)
# Permutación aleatoria
shuffled = tf.random.shuffle(tf.constant([1, 2, 3, 4, 5]))
Operaciones básicas con tensores
1. Operaciones matemáticas
Ejemplo
a = tf.constant([[1, 2], [3, 4]])
b = tf.constant([[5, 6], [7, 8]])
# Suma elemento a elemento
add = tf.add(a, b) # O usar la sobrecarga de operadores a + b
# Multiplicación elemento a elemento
mul = tf.multiply(a, b) # O a * b
# Multiplicación de matrices
matmul = tf.matmul(a, b) # O a @ b
# Otras operaciones matemáticas
sqrt = tf.sqrt(tf.cast(a, tf.float32)) # Raíz cuadrada (es necesario convertir a tipo flotante)
b = tf.constant([[5, 6], [7, 8]])
# Suma elemento a elemento
add = tf.add(a, b) # O usar la sobrecarga de operadores a + b
# Multiplicación elemento a elemento
mul = tf.multiply(a, b) # O a * b
# Multiplicación de matrices
matmul = tf.matmul(a, b) # O a @ b
# Otras operaciones matemáticas
sqrt = tf.sqrt(tf.cast(a, tf.float32)) # Raíz cuadrada (es necesario convertir a tipo flotante)
2. Operaciones de forma
Ejemplo
tensor = tf.constant([[1, 2, 3], [4, 5, 6]])
# Obtener la forma
shape = tensor.shape # Devuelve (2, 3)
# Cambiar la forma (reshape)
reshaped = tf.reshape(tensor, (3, 2)) # Se convierte en 3 filas y 2 columnas
# Transponer (transpose)
transposed = tf.transpose(tensor) # Se convierte en 3 filas y 2 columnas
# Expandir dimensiones (expand_dims)
expanded = tf.expand_dims(tensor, axis=0) # La forma cambia de (2,3) a (1,2,3)
# Obtener la forma
shape = tensor.shape # Devuelve (2, 3)
# Cambiar la forma (reshape)
reshaped = tf.reshape(tensor, (3, 2)) # Se convierte en 3 filas y 2 columnas
# Transponer (transpose)
transposed = tf.transpose(tensor) # Se convierte en 3 filas y 2 columnas
# Expandir dimensiones (expand_dims)
expanded = tf.expand_dims(tensor, axis=0) # La forma cambia de (2,3) a (1,2,3)
3. Indexación y segmentación (slicing)
Ejemplo
tensor = tf.constant([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
# Obtener un solo elemento
elem = tensor[1, 2] # Obtener el elemento de la fila 2, columna 3 (valor 6)
# Operación de segmentación (slicing)
row = tensor[1, :] # Obtener todos los elementos de la fila 2 [4,5,6]
col = tensor[:, 1] # Obtener todos los elementos de la columna 2 [2,5,8]
sub = tensor[0:2, 1:] # Obtener filas 1-2, columnas 2-3 [[2,3],[5,6]]
# Obtener un solo elemento
elem = tensor[1, 2] # Obtener el elemento de la fila 2, columna 3 (valor 6)
# Operación de segmentación (slicing)
row = tensor[1, :] # Obtener todos los elementos de la fila 2 [4,5,6]
col = tensor[:, 1] # Obtener todos los elementos de la columna 2 [2,5,8]
sub = tensor[0:2, 1:] # Obtener filas 1-2, columnas 2-3 [[2,3],[5,6]]
Mecanismo de difusión (broadcasting) de tensores
La difusión (broadcasting) es un mecanismo importante en TensorFlow para manejar operaciones entre tensores de diferentes formas; automáticamente expande el tensor más pequeño para que coincida con la forma del tensor más grande.
Reglas de difusión
- Comparar desde la última dimensión hacia adelante
- Las dos dimensiones deben ser iguales, o una de ellas debe ser 1, o una de ellas no existe
- Se replica y expande en las dimensiones que faltan o que son 1
Ejemplo de difusión
Ejemplo
# Sumar un vector (3,) con un escalar ()
a = tf.constant([1, 2, 3])
b = tf.constant(2)
c = a + b # El resultado es [3,4,5], b se difunde como [2,2,2]
# Sumar una matriz (3,1) con un vector (3,)
d = tf.constant([[1], [2], [3]])
e = tf.constant([10, 20, 30])
f = d + e # d se difunde como [[1,1,1],[2,2,2],[3,3,3]]
# El resultado es [[11,21,31],[12,22,32],[13,23,33]]
a = tf.constant([1, 2, 3])
b = tf.constant(2)
c = a + b # El resultado es [3,4,5], b se difunde como [2,2,2]
# Sumar una matriz (3,1) con un vector (3,)
d = tf.constant([[1], [2], [3]])
e = tf.constant([10, 20, 30])
f = d + e # d se difunde como [[1,1,1],[2,2,2],[3,3,3]]
# El resultado es [[11,21,31],[12,22,32],[13,23,33]]
Operaciones de agregación en tensores
Funciones de agregación comunes
Ejemplo
tensor = tf.constant([[1, 2, 3], [4, 5, 6]])
# Suma
sum_all = tf.reduce_sum(tensor) # Suma de todos los elementos → 21
sum_axis0 = tf.reduce_sum(tensor, 0) # Suma a lo largo de la dimensión 0 (filas) → [5,7,9]
sum_axis1 = tf.reduce_sum(tensor, 1) # Suma a lo largo de la dimensión 1 (columnas) → [6,15]
# Media
mean_all = tf.reduce_mean(tensor) # Media de todos los elementos → 3.5
# Máximo/Mínimo
max_val = tf.reduce_max(tensor) # Máximo → 6
min_val = tf.reduce_min(tensor) # Mínimo → 1
# Operaciones lógicas
any_true = tf.reduce_any(tensor > 4) # ¿Hay algún elemento > 4? → True
all_true = tf.reduce_all(tensor > 0) # ¿Son todos los elementos > 0? → True
# Suma
sum_all = tf.reduce_sum(tensor) # Suma de todos los elementos → 21
sum_axis0 = tf.reduce_sum(tensor, 0) # Suma a lo largo de la dimensión 0 (filas) → [5,7,9]
sum_axis1 = tf.reduce_sum(tensor, 1) # Suma a lo largo de la dimensión 1 (columnas) → [6,15]
# Media
mean_all = tf.reduce_mean(tensor) # Media de todos los elementos → 3.5
# Máximo/Mínimo
max_val = tf.reduce_max(tensor) # Máximo → 6
min_val = tf.reduce_min(tensor) # Mínimo → 1
# Operaciones lógicas
any_true = tf.reduce_any(tensor > 4) # ¿Hay algún elemento > 4? → True
all_true = tf.reduce_all(tensor > 0) # ¿Son todos los elementos > 0? → True
Ejercicios prácticos
Ejercicio 1: Crear y manipular tensores
Ejemplo
# 1. Crear una matriz aleatoria de 3×3 con valores entre 0 y 10
random_matrix = tf.random.uniform((3, 3), minval=0, maxval=10, dtype=tf.int32)
# 2. Calcular la transpuesta de la matriz
transposed_matrix = tf.transpose(random_matrix)
# 3. Calcular el producto de la matriz por su transpuesta
product = tf.matmul(random_matrix, transposed_matrix)
# 4. Calcular la suma de los elementos de la diagonal de la matriz resultante
diag_sum = tf.reduce_sum(tf.linalg.diag_part(product))
random_matrix = tf.random.uniform((3, 3), minval=0, maxval=10, dtype=tf.int32)
# 2. Calcular la transpuesta de la matriz
transposed_matrix = tf.transpose(random_matrix)
# 3. Calcular el producto de la matriz por su transpuesta
product = tf.matmul(random_matrix, transposed_matrix)
# 4. Calcular la suma de los elementos de la diagonal de la matriz resultante
diag_sum = tf.reduce_sum(tf.linalg.diag_part(product))
Ejercicio 2: Aplicación del mecanismo de difusión
Ejemplo
# 1. Crear una matriz de 4×1 y un vector de 1×4
matrix = tf.constant([[1], [2], [3], [4]])
vector = tf.constant([10, 20, 30, 40])
# 2. Calcular su suma utilizando el mecanismo de difusión
broadcast_sum = matrix + vector
# 3. Verificar la forma y los valores del resultado
print("Forma:", broadcast_sum.shape) # Debe ser (4,4)
print("Resultado:", broadcast_sum.numpy())
matrix = tf.constant([[1], [2], [3], [4]])
vector = tf.constant([10, 20, 30, 40])
# 2. Calcular su suma utilizando el mecanismo de difusión
broadcast_sum = matrix + vector
# 3. Verificar la forma y los valores del resultado
print("Forma:", broadcast_sum.shape) # Debe ser (4,4)
print("Resultado:", broadcast_sum.numpy())