Качество набора весов мы умеем измерять одним числом — ошибкой. Осталось её уменьшать, а вот как? Перебрать все наборы нельзя, их бесконечно много, и двигаться вслепую тоже некуда.
Подсказку даёт наклон — насколько круто и в какую сторону меняется ошибка, если чуть тронуть вес. Наклон показывает, куда ошибка растёт, значит двигаться надо в противоположную сторону. Осталось научиться его считать и делать по нему шаг.
Обе функции, которые вы сейчас напишете, — сердце любого обучения. Шаг повторяется при обучении сети миллионы раз. Численная производная нужна не для счёта, а для проверки: ею сверяют формулы, выведенные вручную, и без такой сверки ошибка в знаке обнаруживается через часы бесполезного обучения.
Наклон численно берут центральной разностью: считают значение справа и слева и делят разность на расстояние между точками.
Шаг устроен так: новый вес равен старому минус наклон, умноженный на скорость обучения — множитель, который мы выбираем сами и которым решаем, насколько далеко шагнуть. Минус существен: наклон показывает, куда ошибка растёт, а нам нужно убывание.
Подробно: Наклон: численно и по формуле.
Задание
Напишите две функции
def numeric_grad(f, x, h): # наклон по центральной разности
...
def step_once(w, lr): # один шаг градиентного спуска, возвращает кортеж (наклон, новое w)
...
Центральная разность: (f(x + h) − f(x − h)) / (2h). Обратите внимание: numeric_grad принимает саму функцию первым аргументом.
В step_once вычисляем наклон как производную фуннкции потерь (один шаг градиентного спуска): 2(w − 3). (Функция потерь имеет вид: loss(w) = (w − 3)²)
Как проверить себя
Для функции потерь loss(w) = (w − 3)² точный наклон в точке 1 равен -4. Центральная разность даёт ровно -4 при любом h — это особенность параболы, у более изогнутых функций совпадение будет приблизительным.
Печатать ничего не надо - каждая функция должна возвращать значение.