Construye tu propia red neuronal
Etapa 3 de 6v1 · dca58b13

Funciones de pérdida y cálculo de error

Cuantifica el error entre predicciones y objetivos utilizando Mean Squared Error (MSE) y Binary Cross-Entropy (BCE).

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: ¿Cómo sabe una máquina que se equivocó?

Imagina que estás practicando tiro al blanco. Si disparas y la flecha cae a 10 centímetros de la diana, mides esa distancia y ajustas tu puntería en el siguiente tiro. Si no midieras la distancia del fallo, nunca podrías mejorar.

En machine learning ocurre exactamente lo mismo: para que un modelo aprenda, necesitamos una medida matemática precisa de qué tan lejos estuvo su predicción de la realidad. A esa medida la llamamos función de pérdidaFunción matemática que cuantifica el costo o discrepancia entre las predicciones del modelo y las etiquetas realesVer documentación oficial o función de costo (loss function).

Las dos métricas de pérdida esenciales

En esta etapa implementarás las dos funciones más fundamentales del aprendizaje supervisado:

1. Error Cuadrático Medio (MSE - Mean Squared Error)

Usado comúnmente en problemas de regresión y aproximación:

MSE=1N∑i=1N(pi−yi)2 \text{MSE} = \frac{1}{N} \sum_{i=1}^{N} (p_i - y_i)^2

¿Por qué se eleva al cuadrado la diferencia?

  1. Evita cancelaciones: Si en un ejemplo fallamos por +0.5+0.5 y en otro por −0.5-0.5, la suma simple daría 00 (aparentando error nulo). Al elevar al cuadrado, todo error se vuelve positivo.
  2. Penaliza errores grandes: Un error pequeño de 0.10.1 al cuadrado es 0.010.01 (casi inofensivo), pero un error grande de 2.02.0 al cuadrado se convierte en 4.04.0 (penalización severa).

2. Entropía Cruzada Binaria (BCE - Binary Cross-Entropy)

Es la función estándar para clasificaciones donde el objetivo real es binario (yi∈{0,1}y_i \in \{0, 1\}) y el modelo predice una probabilidad (pi∈(0,1)p_i \in (0, 1)):

BCE=−1N∑i=1N[yiln⁡(pi)+(1−yi)ln⁡(1−pi)] \text{BCE} = -\frac{1}{N} \sum_{i=1}^{N} \left[ y_i \ln(p_i) + (1 - y_i) \ln(1 - p_i) \right]

¿Por qué es ideal para clasificación?

  • Si la etiqueta real es y=1y=1, la fórmula simplifica a −ln⁡(p)-\ln(p): si el modelo predijo p=0.99p=0.99, el costo es casi nulo (−ln⁡(0.99)≈0.01-\ln(0.99) \approx 0.01). Pero si predijo p=0.01p=0.01, el costo se dispara (−ln⁡(0.01)≈4.60-\ln(0.01) \approx 4.60).
  • Estabilidad numérica (ϵ\epsilon): En programación, si p=0p=0, la operación ln⁡(0)\ln(0) genera −∞-\infty o errores de cálculo (NaN). Para prevenirlo de forma robusta, recortamos pip_i al intervalo seguro [ϵ,1−ϵ][\epsilon, 1 - \epsilon] con ϵ=10−7\epsilon = 10^{-7}: pi′=max⁡(10−7,min⁡(1−10−7,pi))p_i' = \max(10^{-7}, \min(1 - 10^{-7}, p_i)) Dato curioso de la industria: Frameworks profesionales como PyTorch (torch.nn.BCELoss) implementan este mismo recorte por debajo para evitar que los modelos se rompan durante el entrenamiento.

Tu objetivo en esta etapa

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

  • metric: nombre de la métrica ("mse" o "bce")
  • predictions: lista de predicciones numéricas [p1,…,pN][p_1, \dots, p_N]
  • targets: lista de valores objetivo reales [y1,…,yN][y_1, \dots, y_N]

Ejemplo guiado (MSE)

json
{
  "op": "loss",
  "metric": "mse",
  "predictions": [0.8, 0.2],
  "targets": [1.0, 0.0]
}
  1. Error muestra 1: (0.8−1.0)2=(−0.2)2=0.04(0.8 - 1.0)^2 = (-0.2)^2 = 0.04.
  2. Error muestra 2: (0.2−0.0)2=(0.2)2=0.04(0.2 - 0.0)^2 = (0.2)^2 = 0.04.
  3. Promedio: 0.04+0.042=0.04\frac{0.04 + 0.04}{2} = 0.04.
  4. Salida: {"loss":0.04}.

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

  • Cálculo de MSE:
    python
    # Python
    mse = sum((p - y) ** 2 for p, y in zip(preds, targets)) / len(preds)
    
    typescript
    // TypeScript
    const sumSq = preds.reduce((acc, p, i) => acc + (p - targets[i]) ** 2, 0);
    const mse = sumSq / preds.length;
    
  • Cálculo de BCE con recorte seguro:
    python
    # Python
    eps = 1e-7
    total = 0.0
    for p, y in zip(preds, targets):
        p_c = max(eps, min(1.0 - eps, p))
        total += y * math.log(p_c) + (1.0 - y) * math.log(1.0 - p_c)
    bce = -total / len(preds)
    
    typescript
    // TypeScript
    const eps = 1e-7;
    let total = 0;
    for (let i = 0; i < preds.length; i++) {
      const p = Math.max(eps, Math.min(1 - eps, preds[i]));
      total += targets[i] * Math.log(p) + (1 - targets[i]) * Math.log(1 - p);
    }
    const bce = -total / preds.length;
    

Reglas de validación y salida

  1. Si predictions y targets tienen longitudes diferentes o están vacías, escribe error en stderr y termina con código 1.
  2. Si metric no es "mse" ni "bce", escribe error en stderr y termina con código 1.
  3. Redondea el valor de pérdida a 4 decimales. Si el número resulta entero (como 0), emítelo como entero.
  4. Salida compacta:
    json
    { "loss": 0.04 }
    

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.