Filtros (kernels)
En el contexto de redes neuronales convolucionales, un filtro o kernel es una pequeña matriz de pesos que se desplaza sobre la imagen o el conjunto de datos de entrada para extraer características específicas. La operación de convolución realizada por estos filtros permite que la red detecte patrones importantes en diferentes partes de la imagen, como bordes, texturas y formas.
Concepto Básico de un Filtro o Kernel
Un kernel es generalmente una matriz de números (como una matriz de 3×3 o 5×5) que define una operación para extraer características en cada paso. El proceso se llama convolución, y es el núcleo de las redes neuronales convolucionales. En cada paso, el filtro se desplaza o “convoluciona” a través de la imagen de entrada, y en cada posición realiza un cálculo (generalmente una multiplicación y suma) que genera un valor de salida en una nueva imagen llamada mapa de características.
Ejemplo de un filtro de 3×3 en una imagen de entrada de 5×5:
- Entrada: Matriz de 5×5 que representa la imagen en escala de grises o una sola capa de color.
- Filtro: Matriz de 3×3 con valores predefinidos.
La salida es una nueva matriz donde cada valor representa el resultado de la operación del filtro en la correspondiente sub-sección de la imagen.
Operación de Convolución: Cómo Funciona
Supongamos que tenemos una matriz de entrada (una imagen) y queremos aplicar un filtro. Para cada posición en la imagen:
- Multiplicación Elemento a Elemento: El filtro se superpone a una parte de la imagen, y cada elemento de la matriz de filtro se multiplica por el elemento correspondiente de la imagen.
- Suma: Los productos se suman para dar un solo número, que representa un valor de característica en el mapa de características.
- Desplazamiento: El filtro se mueve a la siguiente posición en la imagen (hacia la derecha o hacia abajo) y el proceso se repite.
Ejemplo de Implementación en Python
En este ejemplo, vamos a realizar una operación de convolución simple usando un kernel de detección de bordes en una imagen en escala de grises.
import numpy as np
from scipy.ndimage import convolve
import matplotlib.pyplot as plt
# Crear una imagen en escala de grises simple (5x5)
image = np.array([
[1, 2, 3, 4, 5],
[5, 6, 7, 8, 9],
[9, 10, 11, 12, 13],
[13, 14, 15, 16, 17],
[17, 18, 19, 20, 21]
])
# Definir un filtro para detectar bordes (kernel 3x3)
edge_filter = np.array([
[-1, -1, -1],
[-1, 8, -1],
[-1, -1, -1]
])
# Aplicar la convolución utilizando scipy
filtered_image = convolve(image, edge_filter, mode='constant', cval=0.0)
# Mostrar la imagen original y la filtrada
plt.figure(figsize=(8, 4))
plt.subplot(1, 2, 1)
plt.title("Imagen Original")
plt.imshow(image, cmap='gray')
plt.subplot(1, 2, 2)
plt.title("Imagen Filtrada (Bordes)")
plt.imshow(filtered_image, cmap='gray')
plt.show()
Explicación del Código
- Imagen: Creamos una matriz
image
de 5×5 que simula una imagen en escala de grises. - Filtro de Detección de Bordes: Definimos un filtro
edge_filter
de 3×3 que detectará cambios bruscos en la intensidad de los píxeles (bordes). - Convolución: Usamos
convolve
de SciPy para aplicar el filtro a la imagen. La opciónmode='constant'
asegura que los bordes de la imagen se manejen adecuadamente. - Visualización: Usamos
matplotlib
para mostrar tanto la imagen original como la imagen filtrada.
Tipos Comunes de Filtros
- Filtro de Borde: Destaca los bordes en la imagen (donde la intensidad de los píxeles cambia abruptamente).
- Filtro de Suavizado: Suaviza o desenfoca la imagen para reducir el ruido (media o mediana de los valores).
- Filtro de Realce: Aumenta el contraste y resalta los detalles.
Filtros en Redes Neuronales Convolucionales
En redes neuronales convolucionales, los filtros son entrenados automáticamente, en lugar de estar predefinidos. La red aprende los valores de los filtros que mejor resaltan las características necesarias para la tarea en cuestión. Por ejemplo, en las primeras capas de una CNN para la clasificación de imágenes, los filtros podrían aprender a detectar bordes, mientras que en capas más profundas podrían aprender a detectar formas complejas como ojos o ruedas.
Ejemplo de una CNN Simple con Filtros Automáticamente Aprendidos
import tensorflow as tf
from tensorflow.keras import layers, models
from tensorflow.keras.datasets import mnist
# Cargar datos de ejemplo (MNIST)
(train_images, train_labels), (test_images, test_labels) = mnist.load_data()
train_images = train_images.reshape((60000, 28, 28, 1)).astype('float32') / 255
test_images = test_images.reshape((10000, 28, 28, 1)).astype('float32') / 255
# Crear una red CNN simple
model = models.Sequential([
layers.Conv2D(32, (3, 3), activation='relu', input_shape=(28, 28, 1)),
layers.MaxPooling2D((2, 2)),
layers.Conv2D(64, (3, 3), activation='relu'),
layers.MaxPooling2D((2, 2)),
layers.Conv2D(64, (3, 3), activation='relu'),
layers.Flatten(),
layers.Dense(64, activation='relu'),
layers.Dense(10, activation='softmax')
])
# Compilar y entrenar el modelo
model.compile(optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
model.fit(train_images, train_labels, epochs=5, batch_size=64)
# Evaluación del modelo
test_loss, test_acc = model.evaluate(test_images, test_labels)
print(f'Precisión en test: {test_acc:.2f}')
Interpretación
En esta CNN:
- Filtros Convolucionales (Conv2D): Se aplican automáticamente para extraer características de la imagen en capas profundas.
- Entrenamiento: Durante el entrenamiento, el modelo ajusta los valores de los filtros para aprender qué características de la imagen son útiles para la clasificación.
- Salida: Al final, la red utiliza las características aprendidas para clasificar los dígitos de las imágenes de MNIST.
En el siguiente ejemplo vemos las salidas de diferentes capas para una imagen
import tensorflow as tf from tensorflow.keras import layers, models import numpy as np import matplotlib.pyplot as plt from tensorflow.keras.preprocessing import image # Cargar y preprocesar la imagen img_path = 'julia.jpeg' # Reemplaza con la ruta de tu imagen img = image.load_img(img_path, target_size=(128, 128), color_mode='grayscale') img_array = image.img_to_array(img) img_array = np.expand_dims(img_array, axis=0) / 255.0 # Escalar la imagen entre 0 y 1 # Definir un modelo con varias capas convolucionales model = models.Sequential([ layers.Conv2D(8, (3, 3), activation='relu', input_shape=(128, 128, 1)), layers.Conv2D(16, (3, 3), activation='relu'), layers.Conv2D(32, (3, 3), activation='relu') ]) # Crear un modelo que devuelva la salida de cada capa convolucional layer_outputs = [layer.output for layer in model.layers] activation_model = models.Model(inputs=model.inputs, outputs=layer_outputs) # Obtener las activaciones de cada capa activations = activation_model.predict(img_array) # Función para graficar las activaciones layer_names = [layer.name for layer in model.layers] # Nombres de cada capa for layer_name, activation in zip(layer_names, activations): n_features = activation.shape[-1] # Número de filtros en la capa size = activation.shape[1] # Tamaño de la activación (ancho y alto) plt.figure(figsize=(15, 15)) plt.suptitle(f'Activaciones en la capa: {layer_name}') # Visualizar cada filtro en la capa de activación for i in range(n_features): ax = plt.subplot(n_features // 4, 4, i + 1) ax.set_xticks([]) ax.set_yticks([]) plt.imshow(activation[0, :, :, i], cmap='viridis') plt.show()
https://www.ellaberintodefalken.com/2019/10/vision-artificial-redes-convolucionales-CNN.html