#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
правильно.
Итак, если у вас есть непрерывная дифференцируемая выпуклая функция, чтобы найти ее оптимальную (которая минимальна для выпуклой), все, что вам нужно сделать, это найти частные производные функции по каждой переменной и использовать правило обновления, упомянутое выше. Повторяйте шаги, пока градиенты не станут небольшими, что означает, что мы достигли минимумов для выпуклой функции.
Если функция не является выпуклой, мы можем застрять в локальных оптимумах.