Gradient Descent - алгоритм оптимизации для нахождения минимума функции.
Очень упрощенный вид
Давайте начнем с 1D функции y = f (x)
Давайте начнем с произвольного значения x и найдем градиент (наклон) f(Икс).
- Если наклон уменьшается в точке x, то это означает, что мы должны идти дальше в направлении (справа от числовой линии) x (для достижения минимума)
Если наклонувеличивается в точке x, то это означает, что мы должны отойти (слева от числовой линии) x
Мы можем получить наклон, взяв производную функции.Производная равна -ve, если наклон уменьшается, и + ve, если наклон увеличивается
Таким образом, мы можем начать с некоторого произвольного значения x и медленно двигаться к минимуму, используя производные вэто значение х.Насколько медленно мы движемся, определяется скоростью обучения или размером шага.таким образом, у нас есть правило обновления
x = x - df_dx*lr
Мы можем видеть, что, если наклон уменьшается, производная (df_dx) равна -ve, а x увеличивается, и поэтому x перемещается вправо.С другой стороны, если наклон увеличивается, df_dx равно + ve, что уменьшает x, и поэтому мы движемся влево.
Мы продолжаем это либо в течение некоторого большого числа раз, либо до тех пор, пока производная не станет очень маленькой
Многомерная функция z = f (x, y)
Применяется та же логика, что и выше, за исключением того, что теперь мы берем частные производные вместо производных.Правило обновления:
x = x - dpf_dx*lr
y = y - dpf_dy*lr
Где dpf_dx - это частная производная от f по x
. Вышеприведенный алгоритм называется алгоритмом градиентного приличия.В машинном обучении f (x, y) - это функция затрат / потерь, минимум которой нас интересует.
Пример
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d.axes3d import Axes3D
from pylab import meshgrid
from scipy.optimize import fmin
import math
def z_func(a):
x, y = a
return ((x-1)**2+(y-2)**2)
x = np.arange(-3.0,3.0,0.1)
y = np.arange(-3.0,3.0,0.1)
X,Y = meshgrid(x, y) # grid of point
Z = z_func((X, Y)) # evaluation of the function on the grid
fig = plt.figure()
ax = fig.gca(projection='3d')
surf = ax.plot_surface(X, Y, Z, rstride=1, cstride=1,linewidth=0, antialiased=False)
plt.show()
Минимум z_func равен (1,2),Это можно проверить с помощью функции fmin scipy
fmin(z_func,np.array([10,10]))
Теперь давайте напишем наш собственный алгоритм градиентного приличия, чтобы найти минимум z_func
def gradient_decent(x,y,lr):
while True:
d_x = 2*(x-1)
d_y = 2*(y-2)
x -= d_x*lr
y -= d_y*lr
if d_x < 0.0001 and d_y < 0.0001:
break
return x,y
print (gradient_decent(10,10,0.1)
Мы начинаем с некоторого произвольного значения x= 10 и у = 10 и скорость обучения 0,1.Приведенный выше код печатает 1.000033672997724 2.0000299315535326
, что является правильным.
Итак, если у вас есть непрерывная дифференцируемая выпуклая функция, чтобы найти ее оптимальную (минимальную для выпуклой), все, что вам нужно сделать, - это найти частные производные функции по каждой переменной и использовать обновлениеПравило, упомянутое выше.Повторяйте шаги до тех пор, пока градиенты не станут маленькими, что означает, что мы достигли минимумов для выпуклой функции.
Если функция не выпуклая, мы можем застрять в локальном оптимуме.