Как решить задачу градиентного спуска (машинное обучение)?

#python #math #machine-learning #gradient #gradient-descent

#python #математика #машинное обучение #градиент #градиентный спуск

Вопрос:

не мог бы кто-нибудь, пожалуйста, объяснить, как решить задачу градиентного спуска БЕЗ контекста функции стоимости? Я видел бесчисленное количество руководств, в которых объясняется градиентный спуск с использованием функции стоимости, но я действительно не понимаю, как это работает в более общем смысле.

Мне дана 3D-функция:

z = 3 * ((1-xx)2) * np.exp(-(xx2) — (гг 1)2) — 10*(xx/ 5 — xx3 — гг5) * np.exp(-xx2 — гг2)- (1/3)* np.exp(-(xx 1) ** 2 — гг2)

И меня просят:

Создайте простой алгоритм градиентного спуска. Задайте параметры следующим образом:

  • скорость обучения = размер шага: 0.1
  • Максимальное количество итераций: 20
  • Критерий остановки: 0.0001 (Ваши итерации должны останавливаться, когда ваш градиент меньше порогового значения)

Затем запустите свой алгоритм на

  • (x0 = 0,5, y0 = -0,5)
  • (x0 = -0.3, y0 = -0.3)

Я видел этот фрагмент кода повсюду, где говорится о градиентном спуске:

 def update_weights(m, b, X, Y, learning_rate):
    m_deriv = 0
    b_deriv = 0
    N = len(X)
    for i in range(N):
        # Calculate partial derivatives
        # -2x(y - (mx   b))
        m_deriv  = -2*X[i] * (Y[i] - (m*X[i]   b))

        # -2(y - (mx   b))
        b_deriv  = -2*(Y[i] - (m*X[i]   b))

    # We subtract because the derivatives point in direction of steepest ascent
    m -= (m_deriv / float(N)) * learning_rate
    b -= (b_deriv / float(N)) * learning_rate

    return m, b
    enter code here
  

Но я не понимаю, как использовать это для моей проблемы. Как моя функция вписывается в это? Что мне настроить вместо m и b? Я очень, очень смущен.

Спасибо.

Комментарии:

1. Как это может работать без функции затрат? Вам нужен какой-то эталон для перехода из одного состояния в другое. Это не проблема программирования, поэтому здесь не по теме.

2. «Стоимость» является произвольной. Вам буквально просто нужно присвоить своему решению некоторую ценность, чтобы сравнить его с лучшим из существующих. Это никогда не должно быть ощутимой ценностью, просто чем-то, что отличает ваше существующее лучшее решение от нового. «Стоимость» можно прочитать как «Насколько это нарушает мои критерии».

3. @noahship, m -= (m_deriv / float(N)) * learning_rate b -= (b_deriv / float(N)) * learning_rate похоже, что вы вычисляете наклон m и b с помощью Python, так что вы на правильном пути с этим фрагментом кода. Я знаю, что в JavaScript вы бы настроили свою скорость обучения и итерации следующим образом: this.options = Object.assign({ learningRate: 0.1, iterations: 20 }, options);

Ответ №1:

Градиентный спуск — это алгоритм оптимизации для нахождения минимума функции.

Очень упрощенный вид

Давайте начнем с одномерной функции y = f (x)

Давайте начнем с произвольного значения x и найдем градиент (наклон) f (x).

  • Если наклон уменьшается в точке x, то это означает, что мы должны двигаться дальше к (справа от числовой строки) x (для достижения минимума)

  • Если наклон увеличивается при x, то это означает, что мы должны отойти от (слева от числовой строки) x

    Мы можем получить наклон, взяв производную функции. Производная равна -ve, если отклонение уменьшается, и ve, если наклон увеличивается

Итак, мы можем начать с некоторого произвольного значения x и медленно двигаться к минимуму, используя производные при этом значении 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 и y = 10 и скорости обучения 0,1. Приведенный выше код печатается 1.000033672997724 2.0000299315535326 правильно.

Итак, если у вас есть непрерывная дифференцируемая выпуклая функция, чтобы найти ее оптимальную (которая минимальна для выпуклой), все, что вам нужно сделать, это найти частные производные функции по каждой переменной и использовать правило обновления, упомянутое выше. Повторяйте шаги, пока градиенты не станут небольшими, что означает, что мы достигли минимумов для выпуклой функции.

Если функция не является выпуклой, мы можем застрять в локальных оптимумах.