Construye tu propia red neuronal
Etapa 2 de 6v1 · 3edf98c2

Funciones de activación no lineales

Implementa las activaciones Sigmoide y ReLU para introducir no linealidad en la red.

Constrúyelo en tu lenguaje

El tester trata tu programa como una caja negra: sirve cualquier lenguaje. Estos son los más cómodos para este proyecto.

Fundamentos: ¿Por qué necesitamos funciones de activación?

En la etapa anterior aprendiste a calcular la combinación afín de una neurona: z=∑wixi+bz = \sum w_i x_i + b. Pero hay una limitación matemática fundamental: las combinaciones lineales solo pueden trazar líneas rectas o planos.

Si conectas múltiples capas de neuronas lineales en cascada, la combinación de una recta con otra recta sigue siendo matemáticamente una recta. Ninguna red meramente lineal, sin importar cuán profunda sea, podría resolver problemas no lineales elementales como la compuerta XOR o clasificar datos que forman círculos concéntricos.

Para otorgar a las redes neuronales la capacidad de aprender formas, curvas y fronteras de decisión complejas, la salida lineal zz debe pasar a través de una función de activaciónFunción matemática aplicada a la salida ponderada de una neurona para transformar la señal de forma no linealVer documentación oficial no lineal.

Entradas (x) ──> [ Suma ponderada: z = Σ w·x + b ] ──> [ Activación: f(z) ] ──> Salida (y)

Las dos funciones esenciales de esta etapa

Implementarás las dos funciones más influyentes en la historia del aprendizaje profundo:

1. Sigmoide (σ\sigma)

Comprime cualquier número real del rango (−∞,+∞)(-\infty, +\infty) en un valor estrictamente comprendido en el intervalo (0,1)(0, 1). Esto la convierte en la herramienta perfecta para modelar probabilidades:

σ(z)=11+e−z \sigma(z) = \frac{1}{1 + e^{-z}}

Propiedades intuitivas:

  • Si z=0z = 0, la neurona está en un punto neutro: e−0=1e^{-0} = 1, por lo que σ(0)=11+1=0.5\sigma(0) = \frac{1}{1 + 1} = 0.5 (50% de probabilidad).
  • Con valores positivos crecientes (ej. z=2.0z = 2.0), e−2≈0.1353e^{-2} \approx 0.1353, y σ(2.0)=11+0.1353≈0.8808\sigma(2.0) = \frac{1}{1 + 0.1353} \approx 0.8808.
  • Con valores negativos decrecientes (ej. z=−2.0z = -2.0), e2≈7.3891e^{2} \approx 7.3891, y σ(−2.0)=11+7.3891≈0.1192\sigma(-2.0) = \frac{1}{1 + 7.3891} \approx 0.1192.

2. ReLU (Rectified Linear Unit)

Es la función de activación más utilizada en redes profundas modernas gracias a su simplicidad computacional y a que no sufre saturación en la región positiva:

ReLU(z)=max⁡(0,z) \text{ReLU}(z) = \max(0, z)
  • Si z≥0z \ge 0, devuelve exactamente zz (deja pasar la señal).
  • Si z<0z < 0, devuelve 00 (apaga la neurona).

Tu objetivo en esta etapa

Cuando la entrada contenga "op": "activation", tu programa debe leer:

  • function: nombre de la función ("sigmoid" o "relu")
  • value: valor flotante zz a activar

Ejemplos de entrada y salida

Ejemplo A (Sigmoide):

json
{ "op": "activation", "function": "sigmoid", "value": 2.0 }

Salida:

json
{ "output": 0.8808 }

Ejemplo B (ReLU):

json
{ "op": "activation", "function": "relu", "value": -3.2 }

Salida:

json
{ "output": 0 }

Implementación práctica y consejos de código

  • En Python: Usa el módulo estándar math:
    python
    import math
    
    if fn == "relu":
        out = max(0.0, float(value))
    elif fn == "sigmoid":
        out = 1.0 / (1.0 + math.exp(-float(value)))
    
  • En TypeScript: Usa el objeto global Math:
    typescript
    if (fn === "relu") {
      return { output: roundValue(Math.max(0, value)) };
    }
    if (fn === "sigmoid") {
      return { output: roundValue(1 / (1 + Math.exp(-value))) };
    }
    

Errores comunes de principiantes

  • Olvidar el signo negativo en el exponente de la sigmoide: la fórmula es e−ze^{-z}, no eze^{z}.
  • En ReLU, no confundir con el valor absoluto abs(z): los números negativos deben convertirse en 0, no en números positivos.

Reglas de validación y salida

  1. Funciones válidas: Si el campo function no es exactamente "sigmoid" ni "relu", escribe error en stderr y finaliza con código 1.
  2. Formato numérico: Redondea el valor resultante a 4 decimales. Si el número resultante no tiene parte decimal (como 0 o 3), emítelo como entero.
  3. Salida compacta: Emite únicamente el JSON resultante en una línea:
    json
    { "output": 0.5 }
    

Formato de salida y errores

Los ejemplos multilínea se muestran así para facilitar la lectura. Emite JSON compacto, sin espacios opcionales, con las propiedades en el orden de los ejemplos de salida y un salto de línea final. No escribas logs en stdout. Las pruebas comparan texto exacto. Para entradas inválidas, usa stderr con la palabra error, stdout vacío y código 1. Para entradas válidas, código 0. Usa números JSON enteros cuando el resultado sea entero; en neural-network aplica el redondeo a cuatro decimales indicado en la etapa.