Это краткое руководство по настройке, работе и пониманию градиентного спуска.

Цель: минимизировать выпуклую функцию или максимизировать вогнутую функцию.

Шаги высокого уровня:

  1. Выберите функцию стоимости
  2. Вычислите первую производную (частные производные в некоторых случаях)
  3. Постепенно сходитесь к точке минимума. Простая интуиция, вогнутость можно представить как выпуклую функцию при переворачивании.
import random
import numpy as np
from sklearn import datasets

2D пример:

Задача: минимизировать функцию: f(x) = 5x + x².

theta = 3
learning_rate = .1
cost = lambda x: 5*x + x**2
derivative = lambda x: 5 + 2*(x**1)
history = [ theta ]
for iteration in range(25):
    theta = theta - ( learning_rate * derivative(theta) )
    history.append(theta)
  • используя 1-ю производную (наклон) от ( 5x + x² ) в сочетании со скоростью обучения, мы постепенно приближаемся к глобальному минимуму.

3D пример:

Задача: минимизация функции: f(a, b) = a² + b², ограничение между -10–10 для a и b.

theta = np.array([ -10, -10 ])
learning_rate = .01
cost = lambda X: np.sum(np.square(X))
derivative_x1 = lambda X: 2*X[0] + 0
derivative_x2 = lambda X: 0 + 2*X[1]
history = [ theta ]
for iteration in range(10000):
    
    derivatives = np.array([
        learning_rate * derivative_x1(theta),
        learning_rate * derivative_x2(theta)
    ])
    
    theta = theta - derivatives 
    history.append(theta)

min: [-1.82287515e-87 -1.82287515e-87], что довольно близко к [ 0, 0 ].

Пример MSE:

Задача: 1/(m) * sum( ( y — y_hat )² ), где y_hat = m*X + b.

def cost (m, b, X, y):
    y_hat = (m*X + b)
    return np.mean( np.square( y - y_hat ) )

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

X, y = datasets.make_regression()
X = np.sum(X, axis=1)
n = len(y)
learning_rate = 0.001
## initial gradient positions,
np.random.seed(11)
m_gradient = np.random.rand() 
b_gradient = np.random.rand()
for iteration in range(2, 10):
    new_m_gradient = 0
    new_b_gradient = 0
    for i in range(n):
        x_i = X[i]
        y_i = y[i]
        y_hat = m_gradient*x_i + b_gradient
        new_m_gradient +=  ( (2/n) * (y_i - y_hat) * (-1) * x_i )
        new_b_gradient +=  ( (2/n) * (y_i - y_hat) * (-1) )
    b_gradient = b_gradient - (learning_rate * new_b_gradient)
    m_gradient = m_gradient - (learning_rate * new_m_gradient)

Полный блокнот можно найти здесь.