Descenso de gradiente y actualización de parámetros
Aplica la regla de optimización w = w - α * ∇w y b = b - α * ∇b para dar un paso en dirección opuesta al gradiente.
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: Bajando una colina con los ojos vendados
¿Cómo se logra que un conjunto de números "aprenda"? Todo se reduce a una intuición geométrica brillante: el descenso de gradienteMétodo de optimización iterativo para encontrar mínimos locales de funciones diferenciablesVer documentación oficial.
Imagina que estás en una montaña empinada en medio de una densa niebla que no te deja ver a más de un metro de distancia. Tu objetivo es descender hasta el fondo del valle, donde la altitud (el error o pérdida) sea la menor posible:
- No puedes ver el valle desde donde estás, pero puedes palpar el terreno con tus pies para sentir la inclinación inmediata.
- Esa inclinación es la derivada o gradiente (): apunta en la dirección en la que el terreno sube con mayor fuerza.
- Para bajar hacia el valle, debes moverte en la dirección exactamente contraria (con signo negativo: ).
- El tamaño del paso que decides dar en esa dirección es la tasa de aprendizaje (learning rate, ).
Posición de pérdida alta (error)
\
\ <-- Pasos dados en dirección contraria al gradiente (-α·∇)
\
\____ Fondo del valle: Mínimo de pérdida (aprendizaje óptimo)El dilema de la tasa de aprendizaje ()
- Paso demasiado pequeño (): Cada paso es seguro, pero el modelo necesitará millones de iteraciones para aprender algo útil.
- Paso demasiado grande (): Podrías sobrepasar el fondo del valle de un solo salto y terminar en una ladera opuesta aún más alta (el entrenamiento diverge y explota).
- Paso equilibrado (): El modelo desciende de forma ágil y estable hacia el mínimo de error.
La regla de actualización de parámetros
Cada peso y cada sesgo se actualizan restando el producto de la tasa de aprendizaje por su gradiente respectivo:
Tu objetivo en esta etapa
Cuando la entrada contenga "op": "gradient-step", procesa el payload:
{
"op": "gradient-step",
"learning_rate": 0.1,
"weights": [0.5, -0.2],
"bias": 0.1,
"grad_weights": [0.2, -0.4],
"grad_bias": 0.05
}
Ejemplo guiado paso a paso
- Actualizamos el primer peso:
- Actualizamos el segundo peso:
- Actualizamos el sesgo:
- Resultado:
{"bias":0.095,"weights":[0.48,-0.16]}.
Implementación práctica y consejos de código
- Estructura en Python:
python if len(weights) != len(grad_weights) or lr <= 0: raise ValueError("Parámetros de gradiente inválidos") new_weights = [round_value(w - lr * gw) for w, gw in zip(weights, grad_weights)] new_bias = round_value(bias - lr * grad_bias) # Construye el diccionario insertando 'bias' primero: return { "bias": new_bias, "weights": new_weights } - Estructura en TypeScript:
typescript if (weights.length !== grad_weights.length || lr <= 0) { throw new Error("Parámetros de gradiente inválidos"); } const newWeights = weights.map((w, i) => roundValue(w - lr * grad_weights[i]), ); const newBias = roundValue(bias - lr * grad_bias); // Inserta 'bias' antes de 'weights' para asegurar orden alfabético: return { bias: newBias, weights: newWeights, };
Reglas de validación y salida
- Si
learning_rate <= 0, escribeerrorenstderry sal con código1. - Si
weightsygrad_weightstienen longitudes diferentes, escribeerrorenstderry sal con código1. - Redondea cada número a 4 decimales con
round_value. Si tras el redondeo el valor es entero o cero (como0), emítelo como entero. - Orden de las claves en JSON: Emite las claves en orden alfabético estricto (
"bias"primero, seguido de"weights"):json { "bias": 0.095, "weights": [0.48, -0.16] }
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.