Доброго времени суток, сегодня поговорим о градиентном спуске, что это, зачем он нужен и как его сделать в коде с помощью языка программирования Python.
Градиентный спуск, метод градиентного спуска — численный метод нахождения локального минимума или максимума функции с помощью движения вдоль градиента, один из основных численных методов современной оптимизации.
Активно используется в вычислительной математике не только для непосредственного решения задач оптимизации (минимизации), но и для задач, которые могут быть переписаны на языке оптимизации (решение нелинейных уравнений, поиск равновесий, обратные задачи и т. д.). Метод градиентного спуска можно использовать для задач оптимизации в бесконечномерных пространствах, например, для численного решения задач оптимального управления.
Особенно большой интерес к градиентным методам в последние годы связан с тем, что градиентные спуски и их стохастические рандомизированные варианты лежат в основе почти всех современных алгоритмов обучения, разрабатываемых в анализе данных.
Алгоритм, как находить минимум функции с помощью градиентного спуска:
1) Выбрать начальную точку.
2) Сделать шаг спуска — сдвинуться из этой точки против направления градиента. Получить новую точку.
3) Повторять второй шаг, пока не подойдём к минимуму достаточно близко.
Сделаем шаг спуска для функции f(x, y)=0.5⋅x**2+0.2⋅y**2.
В уравнении функции два слагаемых, каждое из которых — квадратичная функция от одной переменной. Минимум каждой находится в её вершине, а значит, минимум данной функции f(x, y) достигается в точке (0, 0). В качестве начальной выберем точку недалеко от неё, например, (1, 2).
Вычислим градиент функции: ∇f(x, y)=(x, 0.4y).
Код вычисления:
import numpy as np
# Используем векторную запись точки.
x = np.array([1, 2])
def f(x):
# f(x) = 0.5x^2 + 0.2y^2
return 0.5*x[0]**2 + 0.2*x[1]**2
def grad(x):
# grad(x) = [x, 0.4y]
dx = x[0]
dy = 0.4 * x[1]
return np.array([dx, dy])
print("Точка 0:", x)
print("f(x) =", f(x))
print()
# Двигаем точку против градиента.
x = x - grad(x)
print("Точка 1:", x)
print("f(x) =", f(x))
Результат:
Точка 0: [1 2]
f(x) = 1.3
Точка 1: [0. 1.2]
f(x) = 0.288
Когда мы подходим к минимуму ближе, есть риск перешагнуть через него. Поэтому при подсчёте новой точки размер шага нужно изменять. Это можно сделать, просто домножая градиент на какое-то маленькое число k=xk−1−∇f(xk−1)⋅γ. Символ γ — это строчная греческая буква, читается как «гамма».Этот коэффициент имеет много названий: «коэффициент обучения», «скорость обучения» (по-английски — “learning rate”) и другие. Часто встречается название «размер шага» или «длина шага». Формально это не верно: фактический размер шага равен произведению этого коэффициента и градиента функции. Также можно встретить обозначения разными буквами, самые популярные:α,γ,η.
Мы будем называть этот множитель коэффициентом скорости градиентного спуска и обозначать как γ.
Градиентный спуск для функций не двух параметров
С помощью градиентного спуска можно находить точки минимума функции не только двух параметров.
В одномерном случае мы просто изменяем только одну переменную и вместо градиента используем производную: Xnew=Xold−f′(Xold).
В случае, когда переменных больше двух, всё остаётся так же, как и в двумерном: Xnew=Xold−∇f(Xold), только градиент и x содержат больше элементов.
Алгоритм и код совершенно такие же, как и для функции двух переменных.
Градиентный спуск для функции трёх переменных:
f(x, y, z) = x**2+2*y**2+z**4
Код нахождения минимума этой функции:
import numpy as np
def f(x):
return x[0]**2 + 2*x[1]**2 + x[2]**4
def grad(x):
return np.array([2*x[0], 4*x[1], 4*x[2]**3])
# Стартовая точка
x = np.array([1.5, 2, 3])
gamma = 1e-2
max_iter = 10
eps = 1e-4
f_old = f(x)
x = x - grad(x) * gamma
f_new = f(x)
i = 0
while abs(f_old - f_new) > eps and i < max_iter:
i = i + 1
f_old = f_new
print(f(x))
x = x - grad(x) * gamma
f_new = f(x)
print(f(x))
Результат
23.123244959999997
16.04923590375929
12.817007917327011
10.876852546622995
9.52954769703004
8.506928194534112
7.68482259419216
6.997967477278678
6.408685637343532
5.893557173839507
5.437115515211021
Пример решения задачи:
Известно, что функция имеет минимум недалеко от точки (1, 2, −3).Найдите точку, в которой функция f(x, y, z) = xln(x)+y**2+z**2 принимает значения меньше -0.36. Воспользуйтесь для этого градиентным спуском.Определите функции f и grad для вычисления значения f(x, y, z) и её градиента в коде.
Сохраните итоговую точку в переменной result и выведите значение функции f в этой точке.
Задача выполнена, значение в которой функция f(x, y, z) = xln(x)+y**2+z**2 принимает значения меньше -0.36, последнее число в столбце.
Кроме того, градиентный спуск может использоваться для оптимизации параметров управления космическими аппаратами, такими как направление или сила тяги двигателей, что может улучшить эффективность и точность при выполнении космических миссий. Такие задачи могут решаться с помощью методов оптимизации, включая градиентный спуск.
Здесь используется библиотека numpy. Она подключается оператором import -"import numpy as np".
Для того чтобы , библиотека numpy заработала необходимо установить ее сначала , командой pip install numpy и убедитесь , что используете последнюю версию Python. Команду необходимо вводить в cmd.exe.
В других ОС, существуют подобные командные строки, я работаю в операционной системе Windows.
В этом коде есть оператор def c помощью него мы создаем функцию grad(x).
«Житейский» пример функции: каждому человеку можно однозначно поставить в соответствие его биологического отца.
Аналогично, заранее заданный алгоритм по значению входного данного выдаёт значение выходного данного. В нашем примере кода присутствует оператор while, это цикл.
Цикл while в Python. Цикл while (“пока”) позволяет выполнять одну и ту же последовательность действий, пока проверяемое условие истинно. Условие записывается до тела цикла и проверяется до выполнения тела цикла. Как правило, цикл while используется, когда невозможно заранее определить точно количество шагов.
Ссылка на другую мою статью, про обратные матрицы и транспонирование матриц: https://dzen.ru/media/id/5f572502b7204709f04ab67c/primer-vychisleniia-obratnoi-matricy-v-kode-na-iazyke-programmirovaniia-python-640ae49697036f7610331184
Чтобы запустить этот код в среде разработки Python нужно в меню выбрать пункт File->New File, в появившемся окне набрать код или скопировать его туда, проверить ошибки, в меню появившегося окна выбрать Run->Run Module, программа выполнится.
Вот-так, относительно просто можно получить обратные матрицы и транспонировать матрицы в языке программирования Python.
Маленькая просьба, поставить лайк в Дзене, если Вам понравилась публикация и подписаться, это поможет развитию канала: https://dzen.ru/id/5f572502b7204709f04ab67c