📖 Teoría

Perceptrón Multicapa (MLP)

La arquitectura que superó las limitaciones del perceptrón simple. Capas de neuronas conectadas que pueden aprender cualquier función continua gracias al backpropagation.

💡 Motivación: más allá del perceptrón

En el módulo anterior, vimos que el perceptrón simple solo puede resolver problemas linealmente separables. La función XOR, los patrones circulares o cualquier frontera curva quedan fuera de su alcance.

La solución, sorprendentemente elegante, consiste en apilar perceptrones en capas. Cada capa transforma el espacio de representación, creando características cada vez más abstractas. Esto es el Perceptrón Multicapa (Multi-Layer Perceptron, MLP), también conocido como red neuronal feedforward (de alimentación directa). Históricamente, la idea de combinar perceptrones en capas se propuso en los años 60, pero no fue hasta 1986, con la publicación del algoritmo de backpropagation por Rumelhart, Hinton y Williams, cuando se demostró que era posible entrenar estas redes de forma eficiente.

🔑

Idea fundamental: Un MLP no es simplemente "muchos perceptrones juntos". Es un sistema de transformaciones compuestas: cada capa deforma el espacio de entrada, y las capas sucesivas trabajan sobre representaciones cada vez más útiles para la tarea.

De lineal a no lineal

Un solo perceptrón traza una frontera lineal (una recta en 2D, un plano en 3D). Pero al combinar múltiples perceptrones en una capa oculta, cada uno traza su propia frontera, y la capa de salida combina estas fronteras para crear regiones de decisión arbitrariamente complejas.

La clave de esta capacidad está en las funciones de activación no lineales. Sin ellas, apilar capas lineales seguiría produciendo una transformación lineal (la composición de funciones lineales es lineal). Es la no linealidad la que permite que cada capa «doble» y «deforme» el espacio, creando representaciones internas donde los datos son separables. Si quieres profundizar en las funciones de activación, consulta el explorador de funciones de activación.

🧪 Frontera de decisión: perceptrón vs MLP

Selecciona un dataset y observa cómo un perceptrón simple (1 frontera lineal) no puede clasificarlo, mientras que un MLP (múltiples fronteras combinadas) sí puede.

Perceptrón simple
MLP (2 capas ocultas)
Época: 0 · Loss perceptrón: · Loss MLP:

🏗️ Arquitectura del MLP

Un MLP está formado por capas de neuronas organizadas secuencialmente. Cada neurona en una capa está conectada a todas las neuronas de la capa siguiente — por eso también se llaman capas fully connected o densas.

Componentes

  • Capa de entrada: Recibe los datos crudos. No realiza ningún cálculo — simplemente pasa los valores a la primera capa oculta. Su tamaño viene determinado por el número de características del dato.
  • Capas ocultas: Una o más capas intermedias donde ocurre la magia. Cada neurona aplica una transformación lineal (pesos + bias) seguida de una no linealidad (función de activación).
  • Capa de salida: Produce el resultado final. Su tamaño y función de activación dependen de la tarea (1 neurona para regresión, N neuronas con softmax para clasificación en N clases).

Todas las conexiones entre neuronas se representan internamente como tensores: los pesos de cada capa son una matriz y los biases un vector. La operación fundamental de cada capa es una multiplicación matricial seguida de una suma y una no linealidad. A esta conexión donde todas las neuronas de una capa se conectan con todas las de la siguiente se le denomina capa densa o fully connected, y es lo que diferencia al MLP de arquitecturas como las CNNs (donde las conexiones son locales) o las RNNs (donde hay conexiones recurrentes).

🧪 Construye tu MLP

Configura la arquitectura y observa el diagrama. El número de parámetros se calcula automáticamente.

Pesos: 0 Biases: 0 Total: 0

Notación

Para una red con \(L\) capas (sin contar la entrada), denotamos:

  • \(n^{[l]}\) = número de neuronas en la capa \(l\) (donde \(l = 0\) es la entrada).
  • \(\mathbf{W}^{[l]} \in \mathbb{R}^{n^{[l]} \times n^{[l-1]}}\) = matriz de pesos de la capa \(l\).
  • \(\mathbf{b}^{[l]} \in \mathbb{R}^{n^{[l]}}\) = vector de biases de la capa \(l\).
  • \(\mathbf{a}^{[l]}\) = vector de activaciones de la capa \(l\) (con \(\mathbf{a}^{[0]} = \mathbf{x}\)).

Número de parámetros

El número total de parámetros entrenables es la suma de pesos y biases:

Parámetros

Por ejemplo, una red [3, 4, 3, 2] tiene: \(3 \times 4 + 4 + 4 \times 3 + 3 + 3 \times 2 + 2 = 12 + 4 + 12 + 3 + 6 + 2 = 39\) parámetros.

Supongamos una red para clasificar dígitos MNIST (imágenes 28×28 = 784 píxeles, 10 clases). La arquitectura es [784, 256, 128, 10]:

Capa 1 (784 → 256):
Pesos: 784 × 256 = 200.704 | Biases: 256 | Subtotal: 200.960

Capa 2 (256 → 128):
Pesos: 256 × 128 = 32.768 | Biases: 128 | Subtotal: 32.896

Capa 3 (128 → 10):
Pesos: 128 × 10 = 1.280 | Biases: 10 | Subtotal: 1.290

Total: 235.146 parámetros

Nota cómo la primera capa concentra el ~85% de los parámetros. Por eso técnicas como la reducción de dimensionalidad o las redes convolucionales (que comparten pesos) son tan importantes para datos de alta dimensión.

🧪 Construye tu propia arquitectura en el MLP interactivo →

➡️ Forward pass (propagación directa)

El forward pass es el proceso de calcular la salida de la red dada una entrada. Se propaga la información capa por capa, de izquierda a derecha.

Para cada capa \(l = 1, 2, \dots, L\):

Forward pass

Esto es simplemente una multiplicación matricial seguida de una suma del bias y una función de activación elemento a elemento. Es lo mismo que hace un perceptrón... ¡pero ahora con matrices! Comprender bien esta operación es fundamental: cada capa densa de tu red ejecuta exactamente este cálculo, y todo el entrenamiento consiste en ajustar las matrices \(\mathbf{W}^{[l]}\) y los vectores \(\mathbf{b}^{[l]}\) para que la composición de todas las capas produzca la salida deseada.

📊

En la práctica: El forward pass se computa con operaciones de álgebra lineal altamente optimizadas (BLAS/cuBLAS). Por eso las GPU, diseñadas para multiplicar matrices en paralelo, son tan eficientes para redes neuronales.

Ejemplo concreto

Para una red [2, 3, 1] con activación sigmoid, el forward pass completo sería:

Capa 1: \(\mathbf{z}^{[1]} = \mathbf{W}^{[1]} \mathbf{x} + \mathbf{b}^{[1]}\),   \(\mathbf{a}^{[1]} = \sigma(\mathbf{z}^{[1]})\)
Capa 2: \(z^{[2]} = \mathbf{W}^{[2]} \mathbf{a}^{[1]} + b^{[2]}\),   \(a^{[2]} = \sigma(z^{[2]})\)
Salida: \(\hat{y} = a^{[2]}\)

💻 Forward pass en PyTorch

Así de simple es implementar un MLP con forward pass en PyTorch:

import torch
import torch.nn as nn

class MLP(nn.Module):
    def __init__(self, input_size, hidden_sizes, output_size):
        super().__init__()
        layers = []
        prev = input_size
        for h in hidden_sizes:
            layers.append(nn.Linear(prev, h))
            layers.append(nn.ReLU())
            prev = h
        layers.append(nn.Linear(prev, output_size))
        self.network = nn.Sequential(*layers)

    def forward(self, x):
        return self.network(x)

# Crear red [784, 256, 128, 10]
model = MLP(784, [256, 128], 10)

# Forward pass
x = torch.randn(32, 784)  # batch de 32
output = model(x)          # → (32, 10)
print(output.shape)

Cada nn.Linear realiza \(\mathbf{z} = \mathbf{W}\mathbf{x} + \mathbf{b}\), y nn.ReLU() aplica la activación. PyTorch se encarga automáticamente del backpropagation gracias a su sistema de autograd.

🔄 Backpropagation

El backpropagation (retropropagación) es el algoritmo que permite entrenar un MLP. Es simplemente la regla de la cadena del cálculo diferencial aplicada de forma eficiente a toda la red.

La idea en 3 pasos

  1. Forward pass: Calcular la salida \(\hat{y}\) y almacenar todas las activaciones intermedias.
  2. Calcular el error: Comparar \(\hat{y}\) con la etiqueta real \(y\) usando una función de coste \(\mathcal{L}(y, \hat{y})\).
  3. Backward pass: Propagar el error hacia atrás, calculando el gradiente \(\frac{\partial \mathcal{L}}{\partial w}\) para cada peso, usando la regla de la cadena.

Regla de la cadena

La clave es que cada capa es una composición de funciones. Si \(f = f_L \circ f_{L-1} \circ \dots \circ f_1\), entonces:

Regla de la cadena

Gradientes por capa

Para la capa \(l\), los gradientes son:

Gradientes

Donde \(\delta^{[l]} = \frac{\partial \mathcal{L}}{\partial \mathbf{z}^{[l]}}\) es el error local de la capa \(l\), y \(\odot\) es el producto elemento a elemento (Hadamard).

Actualización de pesos

Con los gradientes calculados, actualizamos los pesos con descenso de gradiente:

Descenso de gradiente

Este proceso de actualización iterativa es el descenso del gradiente, que estudiamos en detalle en su propio submódulo. En la práctica existen variantes más sofisticadas (SGD con momentum, Adam, AdamW…) que aceleran la convergencia y se tratan en el módulo de optimizadores y schedulers.

⚠️

Problema del gradiente desvaneciente: Al propagar gradientes muchas capas hacia atrás, si la derivada de la activación es pequeña (como sigmoid para valores extremos), los gradientes se multiplican por valores < 1 repetidamente y se desvanecen exponencialmente. Esto hace que las primeras capas apenas aprendan, mientras las últimas se actualizan con normalidad. ReLU mitiga parcialmente este problema porque su derivada es exactamente 1 para \(z > 0\), pero puede causar el problema inverso: neuronas muertas (dead neurons) cuando \(z \leq 0\) de forma permanente. Variantes como LeakyReLU y GELU abordan ambos problemas.

Este tema se trata en profundidad en el submódulo de Estabilidad del Entrenamiento, donde verás técnicas avanzadas como batch normalization, gradient clipping, skip connections y estrategias de inicialización de pesos que permiten entrenar redes con decenas o cientos de capas.

🌌 Teorema de aproximación universal

El resultado teórico más importante del MLP es el Teorema de Aproximación Universal, demostrado independientemente por Cybenko (1989) y Hornik (1991):

🏛️

Teorema: Una red neuronal feedforward con una sola capa oculta y un número suficiente de neuronas puede aproximar cualquier función continua en un subconjunto compacto de \(\mathbb{R}^n\) con precisión arbitraria, siempre que la función de activación sea no constante, acotada y continua.

Este teorema es existencial: dice que la red existe, pero no dice que sea fácil de encontrar ni cuántas neuronas serán necesarias. En la práctica, suele ser más eficiente usar redes con múltiples capas más estrechas que una sola capa muy ancha. Esto se conoce como el beneficio de la profundidad (depth) frente a la anchura (width).

Resultados más recientes, como los de Eldan y Shamir (2016), han demostrado formalmente que existen funciones que una red de 3 capas puede representar de forma compacta pero que requerirían un número exponencial de neuronas en una red de 2 capas. Esto justifica teóricamente lo que la práctica ya sugería: la profundidad importa. Sin embargo, añadir profundidad trae sus propios desafíos (gradientes evanescentes, dificultad de optimización), que se abordan con las técnicas del módulo de estabilidad del entrenamiento.

📜 Teorema de Aproximación Universal

Enunciado formal (Cybenko, 1989):

Sea \(\sigma\) una función de activación continua y sigmoidal (es decir, \(\sigma(t) \to 1\) cuando \(t \to +\infty\) y \(\sigma(t) \to 0\) cuando \(t \to -\infty\)). Entonces, para cualquier función continua \(f\) en el hipercubo unitario \([0,1]^n\) y cualquier \(\varepsilon > 0\), existen constantes \(\alpha_i, b_i \in \mathbb{R}\) y vectores \(\mathbf{w}_i \in \mathbb{R}^n\) tales que:

\(\left| \sum_{i=1}^{N} \alpha_i \sigma(\mathbf{w}_i^T \mathbf{x} + b_i) - f(\mathbf{x}) \right| < \varepsilon\)

para todo \(\mathbf{x} \in [0,1]^n\).

Implicaciones prácticas:

  • El teorema NO garantiza que podamos encontrar los pesos óptimos (solo dice que existen).
  • El número de neuronas necesario puede ser astronómicamente grande.
  • Hornik (1991) demostró que el resultado se extiende a cualquier función de activación no constante.
  • En la práctica, redes profundas (muchas capas) son más eficientes que redes anchas (una sola capa con muchas neuronas).

🧪 Aproximación de funciones

Observa cómo un MLP con más neuronas ocultas puede aproximar funciones cada vez más complejas. Cada neurona oculta "traza una pieza" de la curva.

4
Época: 0 MSE:

🛠️ Diseño práctico de un MLP

Diseñar un MLP eficaz es tanto ciencia como arte. Las siguientes son guías prácticas orientativas que funcionan bien como punto de partida, pero no deben tomarse como reglas universales. Cada problema tiene sus particularidades: la cantidad de datos disponible, la complejidad de la tarea, las restricciones de memoria y latencia, e incluso el presupuesto computacional para búsqueda de hiperparámetros influyen en la arquitectura óptima. Lo más importante es experimentar sistemáticamente: empieza con una configuración sencilla, evalúa, y ajusta.

💡

Importante: Estas recomendaciones son heurísticas basadas en la experiencia acumulada de la comunidad, no leyes universales. Un problema concreto puede requerir más o menos capas, neuronas diferentes de las potencias de 2, o combinaciones de activaciones que no aparecen aquí. La búsqueda sistemática de hiperparámetros (que veremos en optimización de hiperparámetros) es siempre recomendable para proyectos serios.

Número de capas

  • 1 capa oculta: Suficiente para la mayoría de problemas tabulares simples.
  • 2-3 capas ocultas: Permiten representaciones jerárquicas más ricas. Recomendado para problemas complejos.
  • 4+ capas: Raramente útil en MLPs clásicos. Para problemas que requieren mucha profundidad, es mejor usar CNNs, RNNs o Transformers.

Número de neuronas por capa

  • Regla general: Empezar con un valor entre el número de entradas y salidas.
  • Forma de embudo: Reducir gradualmente el número de neuronas (ej: 128 → 64 → 32).
  • Forma de reloj de arena: Reducir y luego aumentar (autoencoders).
  • Potencias de 2: Usar 32, 64, 128... por eficiencia en GPU.

Funciones de activación recomendadas

La función de activación que usamos en cada capa determina la capacidad expresiva de la red y cómo se propagan los gradientes durante el entrenamiento. En las capas ocultas, la elección estándar hoy en día es ReLU (\(f(z) = \max(0, z)\)) o alguna de sus variantes modernas como GELU (usada en Transformers) o Swish (usada en EfficientNet). ReLU es rápida de computar, no satura para valores positivos y produce gradientes de magnitud constante, lo que facilita el entrenamiento de redes profundas.

En la capa de salida, la activación depende enteramente del tipo de tarea. La siguiente tabla resume las combinaciones estándar. Si quieres explorar el comportamiento de cada función de activación en detalle, visita el explorador de funciones de activación.

UbicaciónTareaActivación
Capas ocultasCualquieraReLU (o variantes: LeakyReLU, GELU, Swish)
SalidaRegresiónLineal (identidad)
SalidaClasificación binariaSigmoid
SalidaClasificación multiclaseSoftmax
SalidaRegresión acotada [0,1]Sigmoid
SalidaRegresión acotada [-1,1]Tanh

Funciones de coste

La función de coste (o loss function) cuantifica el error entre la predicción del modelo y el valor real. Es la señal que guía todo el proceso de aprendizaje: los gradientes que calculamos en el backward pass son, literalmente, las derivadas parciales de esta función respecto a cada peso.

La elección de la función de coste está íntimamente ligada a la activación de la capa de salida. Por ejemplo, cross-entropy combinada con softmax produce gradientes numéricamente estables y bien comportados, mientras que usar MSE con softmax puede causar gradientes muy pequeños cuando el modelo está «seguro pero equivocado», ralentizando el aprendizaje. Si quieres experimentar con diferentes funciones de pérdida, prueba el explorador de funciones de pérdida.

TareaFunción de costeFórmula
Regresión MSE (Mean Squared Error) \(\mathcal{L} = \frac{1}{n}\sum(y - \hat{y})^2\)
Clasificación binaria Binary Cross-Entropy \(\mathcal{L} = -[y\log\hat{y} + (1-y)\log(1-\hat{y})]\)
Clasificación multiclase Categorical Cross-Entropy \(\mathcal{L} = -\sum_k y_k \log\hat{y}_k\)

Regla rápida: Si tu salida es continua → MSE. Si es probabilidad binaria → Binary Cross-Entropy. Si es una de \(K\) clases → Categorical Cross-Entropy. En caso de duda, Cross-Entropy suele funcionar mejor que MSE para clasificación porque penaliza más las predicciones seguras pero incorrectas.

🧪 Prueba arquitecturas en el MLP interactivo → 🎨 Diseña tu diagrama de red →

🚀 Más allá del MLP

El MLP es la base sobre la que se construye todo el deep learning moderno. Cada arquitectura avanzada es, en esencia, un MLP con restricciones estructurales que lo hacen más eficiente para un tipo específico de datos.

Pero es importante entender que estas arquitecturas no reemplazan al MLP: lo combinan con otras estructuras. Un Transformer, por ejemplo, alterna capas de atención con capas MLP (llamadas feed-forward networks) dentro de cada bloque. Una CNN extrae features espaciales con convoluciones, pero luego suele alimentar esas features a capas densas (MLP) para la clasificación final. Incluso las GNNs más sofisticadas usan MLPs como componente interno en sus funciones de paso de mensajes. Dominar el MLP no es solo aprender «lo básico»: es entender el bloque que aparece dentro de prácticamente toda arquitectura de deep learning.

ArquitecturaTipo de datosInnovación claveEstudiar
CNN Imágenes, datos espaciales Pesos compartidos + convoluciones locales Convolución y fundamentos →
RNN / LSTM Secuencias, texto, series temporales Conexiones recurrentes + memoria RNN fundamentos →
Transformer Texto, cualquier secuencia Atención (atender a todas las posiciones) Transformers →
GNN Grafos, moléculas Paso de mensajes entre nodos Redes de grafos →
Autoencoder Compresión, generación Bottleneck para representación latente Autoencoders →

A pesar de la sofisticación de estas arquitecturas, el MLP sigue siendo la opción más directa y competitiva para datos tabulares (tablas con features numéricos y categóricos). Investigaciones recientes como Gorishniy et al. (2021) han demostrado que MLPs bien ajustados siguen rivalizando con métodos como XGBoost o arquitecturas tabulares especializadas en muchos benchmarks. Si tus datos vienen en forma de tabla, un MLP es casi siempre un excelente punto de partida.

🎯

Siguiente paso: Prueba las demos interactivas para ver el MLP en acción. Configura la arquitectura, ajusta los pesos, observa el forward pass y diseña tu propia red neuronal para exportar como imagen.

🧪 Herramientas interactivas
🏭 Casos de uso