Las funciones de activación son componentes clave en las redes neuronales artificiales. Su función principal es introducir no linealidad en el modelo, lo que permite a las redes aprender relaciones complejas y representar patrones no triviales entre la entrada y la salida. Sin funciones de activación, una red neuronal serĆa simplemente una combinación lineal de sus entradas, sin poder capturar la complejidad necesaria para tareas como reconocimiento de voz, visión por computadora o procesamiento del lenguaje natural.
A continuación se explican cinco funciones de activación comunes, sus aplicaciones, fórmulas, derivadas y grÔficas.
Aplicación: La función sigmoide se utiliza principalmente en problemas de clasificación binaria, como detectar si un correo es spam o no. También puede usarse en la capa de salida de una red cuando se necesita una probabilidad como resultado.
Explicación: Esta función tiene una forma de āSā y su salida estĆ” limitada entre 0 y 1, lo que la hace ideal para modelar probabilidades. Sin embargo, puede causar que el gradiente se desvanezca en redes profundas.
Fórmula:
\[ f(x) = \frac{1}{1 + e^{-x}} \]
Derivada:
\[ f'(x) = f(x)(1 - f(x)) \]
sigmoid <- function(x) 1 / (1 + exp(-x))
curve(sigmoid, from = -10, to = 10, col = "blue", lwd = 2,
ylab = "Sigmoid(x)", main = "Función Sigmoide")
abline(h = 0.5, lty = 2, col = "gray")
sigmoid_deriv <- function(x) {
s <- sigmoid(x)
s * (1 - s)
}
curve(sigmoid_deriv, from = -10, to = 10, col = "darkblue", lwd = 2,
ylab = "Sigmoid'(x)", main = "Derivada de la función Sigmoide")
abline(h = 0, v = 0, lty = 2, col = "gray")
Aplicación: ReLU es ampliamente utilizada en redes neuronales profundas modernas, especialmente en capas ocultas. Es común en arquitecturas como CNNs y DNNs por su eficiencia computacional y comportamiento estable.
Explicación: Esta función devuelve cero si la entrada es negativa y el mismo valor si es positiva. Introduce una no linealidad que mantiene el gradiente constante en la parte positiva, ayudando a acelerar la convergencia durante el entrenamiento.
Fórmula:
\[ f(x) = \max(0, x) \]
Derivada:
\[ f'(x) = \begin{cases} 0 & \text{si } x < 0 \\ 1 & \text{si } x \geq 0 \end{cases} \]
relu <- function(x) ifelse(x > 0, x, 0)
curve(relu, from = -10, to = 10, col = "red", lwd = 2,
ylab = "ReLU(x)", main = "Función ReLU")
abline(h = 0, v = 0, lty = 2, col = "gray")
relu_deriv <- function(x) ifelse(x > 0, 1, 0)
curve(relu_deriv, from = -10, to = 10, col = "darkgreen", lwd = 2,
ylab = "ReLU'(x)", main = "Derivada de la función ReLU")
abline(h = 0, v = 0, lty = 2, col = "gray")
Aplicación: Es útil en redes neuronales recurrentes (RNN) y en modelos donde se prefiere una salida centrada en cero. También mejora el aprendizaje en comparación con la función sigmoide en muchas tareas.
Explicación: La función tangente hiperbólica es similar a la sigmoide pero escala los valores entre -1 y 1. Esto permite que las salidas sean negativas o positivas, mejorando la dinÔmica del aprendizaje.
Fórmula:
\[ f(x) = \tanh(x) = \frac{e^x - e^{-x}}{e^x + e^{-x}} \]
Derivada:
\[ f'(x) = 1 - f(x)^2 \]
curve(tanh, from = -10, to = 10, col = "purple", lwd = 2,
ylab = "tanh(x)", main = "Función Tanh")
abline(h = 0, v = 0, lty = 2, col = "gray")
tanh_deriv <- function(x) 1 - tanh(x)^2
curve(tanh_deriv, from = -10, to = 10, col = "darkorange", lwd = 2,
ylab = "tanh'(x)", main = "Derivada de la función Tanh")
abline(h = 0, v = 0, lty = 2, col = "gray")
Aplicación: Usada en redes profundas cuando se quiere evitar el problema de las āneuronas muertasā, donde ciertas unidades dejan de activarse con ReLU tradicional.
Explicación: Es una variación de ReLU que permite que los valores negativos pasen con una pequeña pendiente, lo que evita que el gradiente se anule por completo.
Fórmula:
\[ f(x) = \begin{cases} x & \text{si } x \geq 0 \\ \alpha x & \text{si } x < 0 \end{cases} \]
Derivada:
\[ f'(x) = \begin{cases} 1 & \text{si } x \geq 0 \\ \alpha & \text{si } x < 0 \end{cases} \]
leaky_relu <- function(x, alpha = 0.01) ifelse(x > 0, x, alpha * x)
curve(leaky_relu, from = -10, to = 10, col = "orange", lwd = 2,
ylab = "Leaky ReLU(x)", main = "Función Leaky ReLU")
abline(h = 0, v = 0, lty = 2, col = "gray")
leaky_relu_deriv <- function(x, alpha = 0.01) ifelse(x > 0, 1, alpha)
curve(leaky_relu_deriv, from = -10, to = 10, col = "darkblue", lwd = 2,
ylab = "Leaky ReLU'(x)", main = "Derivada de la función Leaky ReLU")
abline(h = 0, v = 0, lty = 2, col = "gray")
Aplicación: Es la elección estĆ”ndar para la capa de salida en problemas de clasificación multiclase, como reconocimiento de dĆgitos o imĆ”genes con mĆŗltiples categorĆas.
Explicación: Toma un vector de valores reales (logits) y los convierte en probabilidades que suman 1. Cada salida representa la probabilidad de pertenecer a una clase.
Fórmula:
\[ f(x_i) = \frac{e^{x_i}}{\sum_{j=1}^n e^{x_j}} \]
Derivada:
La derivada de Softmax es una matriz jacobiana. No se representa como
una curva, pero se puede observar cómo cambia la probabilidad con
respecto a los valores de entrada.
x <- seq(-5, 5, length.out = 300)
softmax_batch <- function(x) {
sapply(x, function(xi) {
input <- c(xi, 0, -xi)
exp_input <- exp(input - max(input))
exp_input / sum(exp_input)
})
}
softmax_vals <- softmax_batch(x)
softmax_matrix <- t(softmax_vals)
matplot(x, softmax_matrix, type = "l", lwd = 2,
col = c("red", "blue", "green"), lty = 1,
ylab = "Probabilidad", main = "Función Softmax simulada")
legend("topright", legend = c("Clase 1", "Clase 2", "Clase 3"),
col = c("red", "blue", "green"), lty = 1, lwd = 2)
dx <- 0.01
x_plus <- x + dx
x_minus <- x - dx
softmax_vals_plus <- softmax_batch(x_plus)
softmax_vals_minus <- softmax_batch(x_minus)
deriv_softmax_1 <- (softmax_vals_plus[1, ] - softmax_vals_minus[1, ]) / (2 * dx)
plot(x, deriv_softmax_1, type = "l", col = "darkred", lwd = 2,
ylab = "d/dx Softmax(x)[1]", main = "Derivada aproximada de Softmax (Clase 1)")
abline(h = 0, v = 0, lty = 2, col = "gray")