Plain gradient descent uses one learning rate for every parameter, which goes badly when gradients differ wildly in scale. RMSProp gives each parameter its own effective rate by tracking a decaying average of that parameter's recent squared gradients.
One step, applied element-wise:
1cache = decay_rate * cache + (1 - decay_rate) * grad²2param = param - learning_rate * grad / (sqrt(cache) + epsilon)
Task: write rmsprop_step(params, grads, cache, learning_rate, decay_rate, epsilon) returning [new_params, new_cache], all values rounded to 4 decimal places.
epsilon only exists to stop division by zero — don't drop it.Look at what the division does to units. A consistently large gradient inflates its own denominator, so the actual step size stays roughly constant no matter how steep that direction is. RMSProp is closer to normalising direction than to scaling magnitude.