Каждый инженер по машинному обучению всегда стремится улучшить производительность своей модели. Здесь и появляется оптимизация, одна из наиболее важных областей машинного обучения. Оптимизация позволяет нам выбрать лучшие параметры, связанные с алгоритмом или методом машинного обучения, которые мы используем, для нашего проблемного случая. Есть несколько типов алгоритмов оптимизации. Возможно, наиболее популярным из них является алгоритм оптимизации градиентного спуска. Первое знакомство с градиентным спуском для многих инженеров машинного обучения - это знакомство с нейронными сетями. В этом руководстве мы научим вас, как реализовать градиентный спуск с нуля на Python. Но сначала, что такое градиентный спуск?

Что такое градиентный спуск?

Градиентный спуск - это алгоритм оптимизации, который помогает моделям машинного обучения сходиться с минимальным значением за счет повторяющихся шагов. По сути, градиентный спуск используется для минимизации функции путем нахождения значения, которое дает наименьший результат этой функции. Часто эта функция обычно является функцией потерь. Функции потерь измеряют, насколько плохо работает наша модель по сравнению с реальными случаями. Следовательно, имеет смысл только уменьшить эту потерю. Один из способов сделать это - градиентный спуск.

Простой алгоритм градиентного спуска выглядит следующим образом:

  1. Получите функцию минимизации F (x)
  2. Инициализируйте значение x, с которого нужно начинать спуск или оптимизацию.
  3. Укажите скорость обучения, которая определит, на какой шаг нужно спуститься или как быстро вы приблизитесь к минимальному значению.
  4. Получите производную от этого значения x (спуск)
  5. Продолжайте спускаться на производную этого значения, умноженную на скорость обучения.
  6. Обновите значение x новым значением, уменьшенным до
  7. Проверьте условие остановки, чтобы узнать, стоит ли останавливаться
  8. Если условие выполнено, остановитесь. Если нет, перейдите к шагу 4 с новым значением x и продолжайте повторять алгоритм.

Реализация градиентного спуска в Python

Здесь мы реализуем простое представление градиентного спуска с использованием Python. Мы создадим произвольную функцию потерь и попытаемся найти локальное минимальное значение для этой функции.

Наша функция будет такой - f (x) = x³ - 3x² + 7

Сначала мы визуализируем эту функцию с набором значений от -1 до 3 (произвольно выбранных для обеспечения крутой кривой).

import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
creating the function and plotting it 

function = lambda x: (x ** 3)-(3 *(x ** 2))+7

#Get 1000 evenly spaced numbers between -1 and 3 (arbitratil chosen to ensure steep curve)
x = np.linspace(-1,3,500)

#Plot the curve
plt.plot(x, function(x))
plt.show()

Вот результат:

Затем мы приступим к созданию двух функций для реализации градиентного спуска:

  • Первая - это производная функция: эта функция принимает значение x и возвращает его производную на основе указанной нами начальной функции. Это показано ниже:
def deriv(x):
    
    '''
    Description: This function takes in a value of x and returns its derivative based on the 
    initial function we specified.
    
    Arguments:
    
    x - a numerical value of x 
    
    Returns:
    
    x_deriv - a numerical value of the derivative of x
    
    '''
    
    x_deriv = 3* (x**2) - (6 * (x))
    return x_deriv
  • Вторая - это ступенчатая функция: это функция, в которой происходит фактический градиентный спуск. Эта функция принимает начальное или предыдущее значение для x, обновляет его на основе шагов, предпринятых через скорость обучения, и выводит самое минимальное значение x, которое достигает условия остановки. В качестве условия остановки мы будем использовать точную остановку. Это означает, что когда абсолютная разница между нашим старым и обновленным x больше значения, алгоритм должен остановиться. Функция также распечатает минимальное значение x, а также количество шагов или спусков, которые потребовались для достижения этого значения.

Эта функция показана ниже:

def step(x_new, x_prev, precision, l_r):
    
    '''
    Description: This function takes in an initial or previous value for x, updates it based on 
    steps taken via the learning rate and outputs the most minimum value of x that reaches the precision satisfaction.
    
    Arguments:
    
    x_new - a starting value of x that will get updated based on the learning rate
    
    x_prev - the previous value of x that is getting updated to the new one
    
    precision - a precision that determines the stop of the stepwise descent 
    
    l_r - the learning rate (size of each descent step)
    
    Output:
    
    1. Prints out the latest new value of x which equates to the minimum we are looking for
    2. Prints out the the number of x values which equates to the number of gradient descent steps
    3. Plots a first graph of the function with the gradient descent path
    4. Plots a second graph of the function with a zoomed in gradient descent path in the important area
    
    '''
    
    # create empty lists where the updated values of x and y wil be appended during each iteration
    
    x_list, y_list = [x_new], [function(x_new)]
    # keep looping until your desired precision
    while abs(x_new - x_prev) > precision:
        
        # change the value of x
        x_prev = x_new
        
        # get the derivation of the old value of x
        d_x = - deriv(x_prev)
        
        # get your new value of x by adding the previous, the multiplication of the derivative and the learning rate
        x_new = x_prev + (l_r * d_x)
        
        # append the new value of x to a list of all x-s for later visualization of path
        x_list.append(x_new)
        
        # append the new value of y to a list of all y-s for later visualization of path
        y_list.append(function(x_new))

    print ("Local minimum occurs at: "+ str(x_new))
    print ("Number of steps: " + str(len(x_list)))
    
    
    plt.subplot(1,2,2)
    plt.scatter(x_list,y_list,c="g")
    plt.plot(x_list,y_list,c="g")
    plt.plot(x,function(x), c="r")
    plt.title("Gradient descent")
    plt.show()

    plt.subplot(1,2,1)
    plt.scatter(x_list,y_list,c="g")
    plt.plot(x_list,y_list,c="g")
    plt.plot(x,function(x), c="r")
    plt.xlim([1.0,2.1])
    plt.title("Zoomed in Gradient descent to Key Area")
    plt.show()

Затем мы приступаем к построению пути градиентного спуска, как показано ниже:

#Implement gradient descent (all the arguments are arbitrarily chosen)

step(0.5, 0, 0.001, 0.05)

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

Пожалуйста, проверьте полный код записной книжки iPython здесь.

Исходное сообщение: https://tech-quantum.com/implementation-of-gradient-descent-in-python/

Также прочтите

Получайте лучшие предложения по программному обеспечению прямо в свой почтовый ящик